Implemented basic lighting!
This commit is contained in:
parent
0a001d71bc
commit
5b51a3d571
20 changed files with 8628 additions and 72 deletions
BIN
assets/models/cube.glb
Normal file
BIN
assets/models/cube.glb
Normal file
Binary file not shown.
|
|
@ -2,6 +2,37 @@
|
||||||
|
|
||||||
layout(location = 0) out vec4 outColor;
|
layout(location = 0) out vec4 outColor;
|
||||||
|
|
||||||
|
layout(location = 2) in vec3 Normal;
|
||||||
|
layout(location = 3) in vec3 FragPos;
|
||||||
|
layout(location = 4) in vec2 TexCoords;
|
||||||
|
|
||||||
|
layout (binding = 2) uniform LightUniform {
|
||||||
|
vec3 pos;
|
||||||
|
} lightPos;
|
||||||
|
|
||||||
|
layout (binding = 3) uniform ViewUniform {
|
||||||
|
vec3 pos;
|
||||||
|
} viewPos;
|
||||||
|
|
||||||
|
layout (set = 1, binding = 0) uniform sampler2D textureSampler;
|
||||||
|
layout (set = 1, binding = 1) uniform sampler2D diffuseSampler;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
outColor = vec4(1.0, 1.0, 1.0, 1.0);
|
vec3 lightDiffuse = vec3(0.5, 0.5, 0.5);
|
||||||
|
vec3 lightAmbient = vec3(0.2, 0.2, 0.2);
|
||||||
|
vec3 lightSpecular = vec3(1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
vec3 norm = normalize(Normal);
|
||||||
|
vec3 lightDir = normalize(lightPos.pos - FragPos);
|
||||||
|
float diff = max(dot(norm, lightDir), 0.0);
|
||||||
|
vec3 diffuse = lightDiffuse * diff * vec3(texture(textureSampler, TexCoords));
|
||||||
|
vec3 ambient = lightAmbient * vec3(texture(textureSampler, TexCoords));
|
||||||
|
|
||||||
|
vec3 viewDir = normalize(viewPos.pos - FragPos);
|
||||||
|
vec3 reflectDir = reflect(-lightDir, norm);
|
||||||
|
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 2);
|
||||||
|
vec3 specular = lightSpecular * spec * vec3(texture(diffuseSampler, TexCoords));
|
||||||
|
|
||||||
|
vec3 result = (ambient + diffuse + specular);
|
||||||
|
outColor = vec4(result, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) in vec3 vertPos;
|
layout(location = 0) in vec3 vertPos;
|
||||||
|
layout(location = 1) in vec3 normal;
|
||||||
|
layout(location = 2) in vec2 uv;
|
||||||
|
|
||||||
layout (binding = 0) uniform ProjUniform {
|
layout (binding = 0) uniform ProjUniform {
|
||||||
mat4 proj;
|
mat4 proj;
|
||||||
|
|
@ -10,8 +12,15 @@ layout (binding = 1) uniform ViewUniform {
|
||||||
mat4 view;
|
mat4 view;
|
||||||
} view;
|
} view;
|
||||||
|
|
||||||
|
layout(location = 2) out vec3 Normal;
|
||||||
|
layout(location = 3) out vec3 FragPos;
|
||||||
|
layout(location = 4) out vec2 TexCoords;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 out_vec = proj.proj * view.view * vec4(vertPos, 1.0);
|
vec4 out_vec = proj.proj * view.view * vec4(vertPos, 1.0);
|
||||||
//vec4 out_vec = proj.proj * vec4(vertPos, 1.0);
|
//vec4 out_vec = proj.proj * vec4(vertPos, 1.0);
|
||||||
|
FragPos = vec3(vec4(vertPos, 1.0));
|
||||||
|
Normal = normal;
|
||||||
|
TexCoords = uv;
|
||||||
gl_Position = vec4(out_vec.x, out_vec.y, out_vec.z, out_vec.w);
|
gl_Position = vec4(out_vec.x, out_vec.y, out_vec.z, out_vec.w);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 3 KiB |
BIN
assets/textures/container.png
Normal file
BIN
assets/textures/container.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 457 KiB |
BIN
assets/textures/container_specular.png
Normal file
BIN
assets/textures/container_specular.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 141 KiB |
|
|
@ -32,6 +32,7 @@ pub fn build(b: *std.Build) void {
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.link_libc = true,
|
.link_libc = true,
|
||||||
});
|
});
|
||||||
|
renderer.addCSourceFile(.{ .file = b.path("ext/stb_image.c") });
|
||||||
renderer.addImport("sideros", sideros);
|
renderer.addImport("sideros", sideros);
|
||||||
renderer.addImport("ecs", ecs);
|
renderer.addImport("ecs", ecs);
|
||||||
ecs.addImport("renderer", renderer);
|
ecs.addImport("renderer", renderer);
|
||||||
|
|
|
||||||
2
ext/stb_image.c
vendored
Normal file
2
ext/stb_image.c
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "stb_image.h"
|
||||||
7988
ext/stb_image.h
vendored
Normal file
7988
ext/stb_image.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -6,4 +6,5 @@ pub const c = @cImport({
|
||||||
@cInclude("vulkan/vulkan_wayland.h");
|
@cInclude("vulkan/vulkan_wayland.h");
|
||||||
@cInclude("vulkan/vulkan_xcb.h");
|
@cInclude("vulkan/vulkan_xcb.h");
|
||||||
@cInclude("xcb/xcb_icccm.h");
|
@cInclude("xcb/xcb_icccm.h");
|
||||||
|
@cInclude("stb_image.h");
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ pub const SyncGroup = []const System;
|
||||||
|
|
||||||
pub const Resources = struct {
|
pub const Resources = struct {
|
||||||
camera: Camera,
|
camera: Camera,
|
||||||
renderer: Renderer,
|
renderer: *Renderer,
|
||||||
input: Input,
|
input: Input,
|
||||||
delta_time: f64 = 0.0,
|
delta_time: f64 = 0.0,
|
||||||
};
|
};
|
||||||
|
|
@ -26,7 +26,7 @@ pub const Human = struct {
|
||||||
// TODO(ernesto): Move pool to its own file
|
// TODO(ernesto): Move pool to its own file
|
||||||
pub const Pool = struct {
|
pub const Pool = struct {
|
||||||
humans: std.MultiArrayList(Human),
|
humans: std.MultiArrayList(Human),
|
||||||
resources: Resources,
|
resources: *Resources,
|
||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
system_groups: std.ArrayList(SystemGroup),
|
system_groups: std.ArrayList(SystemGroup),
|
||||||
sync_groups: std.ArrayList(SyncGroup),
|
sync_groups: std.ArrayList(SyncGroup),
|
||||||
|
|
@ -34,7 +34,7 @@ pub const Pool = struct {
|
||||||
wait_group: std.Thread.WaitGroup,
|
wait_group: std.Thread.WaitGroup,
|
||||||
mutex: std.Thread.Mutex,
|
mutex: std.Thread.Mutex,
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, resources: Resources) !@This() {
|
pub fn init(allocator: Allocator, resources: *Resources) !@This() {
|
||||||
var pool = @This(){
|
var pool = @This(){
|
||||||
.humans = .{},
|
.humans = .{},
|
||||||
.resources = resources,
|
.resources = resources,
|
||||||
|
|
|
||||||
|
|
@ -50,15 +50,15 @@ pub fn main() !void {
|
||||||
//var w = try Renderer.Window.create(800, 600, "sideros");
|
//var w = try Renderer.Window.create(800, 600, "sideros");
|
||||||
//defer w.destroy();
|
//defer w.destroy();
|
||||||
|
|
||||||
const resources = ecs.Resources{
|
var resources = ecs.Resources{
|
||||||
.camera = .{
|
.camera = .{
|
||||||
.position = .{0.0, 0.0, 100},
|
.position = .{30.0, 30.0, 30.0},
|
||||||
.target = .{0.0, 0.0, 0.0},
|
.target = .{0.0, 0.0, 0.0},
|
||||||
},
|
},
|
||||||
.renderer = undefined,
|
.renderer = undefined,
|
||||||
.input = .{ .key_pressed = .{false} ** @intFromEnum(Input.KeyCode.menu) },
|
.input = .{ .key_pressed = .{false} ** @intFromEnum(Input.KeyCode.menu) },
|
||||||
};
|
};
|
||||||
var pool = try ecs.Pool.init(allocator, resources);
|
var pool = try ecs.Pool.init(allocator, &resources);
|
||||||
defer pool.deinit();
|
defer pool.deinit();
|
||||||
try pool.addSystemGroup(&[_]ecs.System{
|
try pool.addSystemGroup(&[_]ecs.System{
|
||||||
Renderer.render,
|
Renderer.render,
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,14 @@ const Mesh = @This();
|
||||||
|
|
||||||
pub const Vertex = struct {
|
pub const Vertex = struct {
|
||||||
position: [3]f32,
|
position: [3]f32,
|
||||||
|
normal: [3]f32,
|
||||||
|
uv: [2]f32,
|
||||||
|
|
||||||
pub fn create(x: f32, y: f32, z: f32) Vertex {
|
pub fn create(x: f32, y: f32, z: f32, normal_x: f32, normal_y: f32, normal_z: f32, u: f32, v: f32) Vertex {
|
||||||
return Vertex{
|
return Vertex{
|
||||||
.position = .{ x, y, z },
|
.position = .{ x, y, z },
|
||||||
|
.normal = .{ normal_x, normal_y, normal_z },
|
||||||
|
.uv = .{u, v},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -25,15 +29,29 @@ pub const Vertex = struct {
|
||||||
return binding_description;
|
return binding_description;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attributeDescription() c.VkVertexInputAttributeDescription {
|
pub fn attributeDescriptions() []const c.VkVertexInputAttributeDescription {
|
||||||
const attribute_description: c.VkVertexInputAttributeDescription = .{
|
const attributes: []const c.VkVertexInputAttributeDescription = &.{
|
||||||
.location = 0,
|
.{
|
||||||
.binding = 0,
|
.location = 0,
|
||||||
.format = c.VK_FORMAT_R32G32B32_SFLOAT,
|
.binding = 0,
|
||||||
.offset = 0,
|
.format = c.VK_FORMAT_R32G32B32_SFLOAT,
|
||||||
|
.offset = 0,
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.location = 1,
|
||||||
|
.binding = 0,
|
||||||
|
.format = c.VK_FORMAT_R32G32B32_SFLOAT,
|
||||||
|
.offset = 12,
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.location = 2,
|
||||||
|
.binding = 0,
|
||||||
|
.format = c.VK_FORMAT_R32G32_SFLOAT,
|
||||||
|
.offset = 24,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return attribute_description;
|
return attributes;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -41,15 +59,35 @@ vertex_buffer: vk.Buffer,
|
||||||
index_buffer: vk.Buffer,
|
index_buffer: vk.Buffer,
|
||||||
|
|
||||||
pub fn createVertexBuffer(allocator: Allocator, device: anytype) !vk.Buffer {
|
pub fn createVertexBuffer(allocator: Allocator, device: anytype) !vk.Buffer {
|
||||||
const gltf_data = try gltf.parseFile(allocator, "assets/models/block.glb");
|
const gltf_data = try gltf.parseFile(allocator, "assets/models/cube.glb");
|
||||||
|
|
||||||
const vertices = gltf_data.vertices;
|
const vertices = gltf_data.vertices;
|
||||||
|
const normals = gltf_data.normals;
|
||||||
|
const uvs = gltf_data.uvs;
|
||||||
|
defer allocator.free(uvs);
|
||||||
|
defer allocator.free(normals);
|
||||||
defer allocator.free(vertices);
|
defer allocator.free(vertices);
|
||||||
defer allocator.free(gltf_data.indices);
|
defer allocator.free(gltf_data.indices);
|
||||||
|
|
||||||
|
const final_array = try allocator.alloc([8]f32, vertices.len);
|
||||||
|
defer allocator.free(final_array);
|
||||||
|
|
||||||
|
for (vertices, normals, uvs, final_array) |vertex, normal, uv, *final| {
|
||||||
|
final[0] = vertex[0];
|
||||||
|
final[1] = vertex[1];
|
||||||
|
final[2] = vertex[2];
|
||||||
|
|
||||||
|
final[3] = normal[0];
|
||||||
|
final[4] = normal[1];
|
||||||
|
final[5] = normal[2];
|
||||||
|
|
||||||
|
final[6] = uv[0];
|
||||||
|
final[7] = uv[1];
|
||||||
|
}
|
||||||
|
|
||||||
var data: [*c]?*anyopaque = null;
|
var data: [*c]?*anyopaque = null;
|
||||||
|
|
||||||
const buffer = try device.createBuffer(vk.BufferUsage{ .transfer_src = true }, vk.BufferFlags{ .host_visible = true, .host_coherent = true }, @sizeOf(Vertex) * vertices.len);
|
const buffer = try device.createBuffer(vk.BufferUsage{ .transfer_src = true }, vk.BufferFlags{ .host_visible = true, .host_coherent = true }, @sizeOf([8]f32) * vertices.len);
|
||||||
|
|
||||||
try vk.mapError(c.vkMapMemory(
|
try vk.mapError(c.vkMapMemory(
|
||||||
device.handle,
|
device.handle,
|
||||||
|
|
@ -63,7 +101,7 @@ pub fn createVertexBuffer(allocator: Allocator, device: anytype) !vk.Buffer {
|
||||||
if (data) |ptr| {
|
if (data) |ptr| {
|
||||||
const gpu_vertices: [*]Vertex = @ptrCast(@alignCast(ptr));
|
const gpu_vertices: [*]Vertex = @ptrCast(@alignCast(ptr));
|
||||||
|
|
||||||
@memcpy(gpu_vertices, @as([]Vertex, @ptrCast(vertices[0..])));
|
@memcpy(gpu_vertices, @as([]Vertex, @ptrCast(final_array[0..])));
|
||||||
}
|
}
|
||||||
|
|
||||||
c.vkUnmapMemory(device.handle, buffer.memory);
|
c.vkUnmapMemory(device.handle, buffer.memory);
|
||||||
|
|
@ -77,11 +115,12 @@ pub fn createVertexBuffer(allocator: Allocator, device: anytype) !vk.Buffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createIndexBuffer(allocator: Allocator, device: anytype) !vk.Buffer {
|
pub fn createIndexBuffer(allocator: Allocator, device: anytype) !vk.Buffer {
|
||||||
const gltf_data = try gltf.parseFile(allocator, "assets/models/block.glb");
|
const gltf_data = try gltf.parseFile(allocator, "assets/models/cube.glb");
|
||||||
const indices = gltf_data.indices;
|
const indices = gltf_data.indices;
|
||||||
defer allocator.free(indices);
|
defer allocator.free(indices);
|
||||||
defer allocator.free(gltf_data.vertices);
|
defer allocator.free(gltf_data.vertices);
|
||||||
//const indices = [_]u16{ 0, 1, 2, 3, 0, 2 };
|
defer allocator.free(gltf_data.normals);
|
||||||
|
defer allocator.free(gltf_data.uvs);
|
||||||
|
|
||||||
var data: [*c]?*anyopaque = null;
|
var data: [*c]?*anyopaque = null;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ const ecs = @import("ecs");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const vk = @import("vulkan.zig");
|
const vk = @import("vulkan.zig");
|
||||||
pub const Mesh = @import("Mesh.zig");
|
pub const Mesh = @import("Mesh.zig");
|
||||||
|
const Texture = vk.Texture;
|
||||||
pub const Camera = @import("Camera.zig");
|
pub const Camera = @import("Camera.zig");
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
|
@ -37,7 +38,7 @@ pub fn init(comptime C: type, comptime S: type, allocator: Allocator, display: C
|
||||||
|
|
||||||
const swapchain = try vk.Swapchain(2).create(allocator, surface, device, physical_device, render_pass);
|
const swapchain = try vk.Swapchain(2).create(allocator, surface, device, physical_device, render_pass);
|
||||||
|
|
||||||
const graphics_pipeline = try vk.GraphicsPipeline(2).create(device, swapchain, render_pass, vertex_shader, fragment_shader);
|
var graphics_pipeline = try vk.GraphicsPipeline(2).create(allocator, device, swapchain, render_pass, vertex_shader, fragment_shader);
|
||||||
|
|
||||||
// TODO: I think the renderer shouldn't have to interact with buffers. I think the API should change to
|
// TODO: I think the renderer shouldn't have to interact with buffers. I think the API should change to
|
||||||
// something along the lines of
|
// something along the lines of
|
||||||
|
|
@ -48,6 +49,15 @@ pub fn init(comptime C: type, comptime S: type, allocator: Allocator, display: C
|
||||||
// renderer.submit()
|
// renderer.submit()
|
||||||
const triangle = try Mesh.create(allocator, device);
|
const triangle = try Mesh.create(allocator, device);
|
||||||
|
|
||||||
|
const texture = try Texture.init("assets/textures/container.png", device);
|
||||||
|
const diffuse = try Texture.init("assets/textures/container_specular.png", device);
|
||||||
|
|
||||||
|
_ = try graphics_pipeline.addTexture(device, texture, diffuse);
|
||||||
|
|
||||||
|
graphics_pipeline.light_pos[0] = 0.0;
|
||||||
|
graphics_pipeline.light_pos[1] = 2.0;
|
||||||
|
graphics_pipeline.light_pos[2] = 0.0;
|
||||||
|
|
||||||
return Renderer{
|
return Renderer{
|
||||||
.instance = instance,
|
.instance = instance,
|
||||||
.surface = surface,
|
.surface = surface,
|
||||||
|
|
@ -83,6 +93,12 @@ pub fn render(pool: *ecs.Pool) anyerror!void {
|
||||||
const view_memory = renderer.graphics_pipeline.view_memory;
|
const view_memory = renderer.graphics_pipeline.view_memory;
|
||||||
@memcpy(view_memory[0..@sizeOf(math.Matrix)], std.mem.asBytes(&camera.getView()));
|
@memcpy(view_memory[0..@sizeOf(math.Matrix)], std.mem.asBytes(&camera.getView()));
|
||||||
|
|
||||||
|
const view_pos_memory = renderer.graphics_pipeline.view_pos_memory;
|
||||||
|
const view_pos: [*]f32 = @alignCast(@ptrCast(view_pos_memory));
|
||||||
|
view_pos[0] = camera.position[0];
|
||||||
|
view_pos[1] = camera.position[1];
|
||||||
|
view_pos[2] = camera.position[2];
|
||||||
|
|
||||||
try renderer.device.waitFence(renderer.current_frame);
|
try renderer.device.waitFence(renderer.current_frame);
|
||||||
const image = try renderer.swapchain.nextImage(renderer.device, renderer.current_frame);
|
const image = try renderer.swapchain.nextImage(renderer.device, renderer.current_frame);
|
||||||
try renderer.device.resetCommand(renderer.current_frame);
|
try renderer.device.resetCommand(renderer.current_frame);
|
||||||
|
|
@ -91,7 +107,7 @@ pub fn render(pool: *ecs.Pool) anyerror!void {
|
||||||
renderer.graphics_pipeline.bind(renderer.device, renderer.current_frame);
|
renderer.graphics_pipeline.bind(renderer.device, renderer.current_frame);
|
||||||
renderer.device.bindVertexBuffer(renderer.vertex_buffer, renderer.current_frame);
|
renderer.device.bindVertexBuffer(renderer.vertex_buffer, renderer.current_frame);
|
||||||
renderer.device.bindIndexBuffer(renderer.index_buffer, renderer.current_frame);
|
renderer.device.bindIndexBuffer(renderer.index_buffer, renderer.current_frame);
|
||||||
renderer.device.bindDescriptorSets(renderer.graphics_pipeline, renderer.current_frame);
|
renderer.device.bindDescriptorSets(renderer.graphics_pipeline, renderer.current_frame, 0);
|
||||||
renderer.device.draw(@intCast(renderer.index_buffer.size / @sizeOf(u16)), renderer.current_frame);
|
renderer.device.draw(@intCast(renderer.index_buffer.size / @sizeOf(u16)), renderer.current_frame);
|
||||||
renderer.render_pass.end(renderer.device, renderer.current_frame);
|
renderer.render_pass.end(renderer.device, renderer.current_frame);
|
||||||
try renderer.device.endCommand(renderer.current_frame);
|
try renderer.device.endCommand(renderer.current_frame);
|
||||||
|
|
|
||||||
115
src/renderer/Texture.zig
Normal file
115
src/renderer/Texture.zig
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
const Texture = @This();
|
||||||
|
const c = @import("sideros").c;
|
||||||
|
const vk = @import("vulkan.zig");
|
||||||
|
|
||||||
|
image: c.VkImage,
|
||||||
|
image_memory: c.VkDeviceMemory,
|
||||||
|
image_view: c.VkImageView,
|
||||||
|
|
||||||
|
pub fn init(path: [:0]const u8, device: anytype) !Texture {
|
||||||
|
var width: i32 = 0;
|
||||||
|
var height: i32 = 0;
|
||||||
|
var channels: i32 = 0;
|
||||||
|
|
||||||
|
const pixels = c.stbi_load(path, &width, &height, &channels, c.STBI_rgb_alpha);
|
||||||
|
defer c.stbi_image_free(pixels);
|
||||||
|
|
||||||
|
const size: c.VkDeviceSize = @as(u64, @intCast(width)) * @as(u64, @intCast(height)) * 4;
|
||||||
|
const image_buffer = try device.createBuffer(vk.BufferUsage{ .transfer_src = true }, vk.BufferFlags{ .host_visible = true, .host_coherent = true }, size);
|
||||||
|
|
||||||
|
const pixel_bytes: [*]u8 = @ptrCast(pixels);
|
||||||
|
var image_data: [*c]u8 = undefined;
|
||||||
|
|
||||||
|
try vk.mapError(c.vkMapMemory(
|
||||||
|
device.handle,
|
||||||
|
image_buffer.memory,
|
||||||
|
0,
|
||||||
|
image_buffer.size,
|
||||||
|
0,
|
||||||
|
@ptrCast(&image_data),
|
||||||
|
));
|
||||||
|
|
||||||
|
@memcpy(image_data[0..size], pixel_bytes[0..size]);
|
||||||
|
|
||||||
|
c.vkUnmapMemory(
|
||||||
|
device.handle,
|
||||||
|
image_buffer.memory,
|
||||||
|
);
|
||||||
|
|
||||||
|
const create_info: c.VkImageCreateInfo = .{
|
||||||
|
.sType = c.VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||||
|
.imageType = c.VK_IMAGE_TYPE_2D,
|
||||||
|
.extent = .{
|
||||||
|
.width = @intCast(width),
|
||||||
|
.height = @intCast(height),
|
||||||
|
.depth = 1,
|
||||||
|
},
|
||||||
|
.mipLevels = 1,
|
||||||
|
.arrayLayers = 1,
|
||||||
|
.format = c.VK_FORMAT_R8G8B8A8_SRGB,
|
||||||
|
.tiling = c.VK_IMAGE_TILING_OPTIMAL,
|
||||||
|
.initialLayout = c.VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
|
.usage = c.VK_IMAGE_USAGE_TRANSFER_DST_BIT | c.VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||||
|
.sharingMode = c.VK_SHARING_MODE_EXCLUSIVE,
|
||||||
|
.samples = c.VK_SAMPLE_COUNT_1_BIT,
|
||||||
|
.flags = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
var image: c.VkImage = undefined;
|
||||||
|
var image_memory: c.VkDeviceMemory = undefined;
|
||||||
|
try vk.mapError(c.vkCreateImage(device.handle, &create_info, null, &image));
|
||||||
|
|
||||||
|
var memory_requirements: c.VkMemoryRequirements = undefined;
|
||||||
|
c.vkGetImageMemoryRequirements(device.handle, image, &memory_requirements);
|
||||||
|
|
||||||
|
const alloc_info: c.VkMemoryAllocateInfo = .{
|
||||||
|
.sType = c.VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||||
|
.allocationSize = memory_requirements.size,
|
||||||
|
.memoryTypeIndex = try device.findMemoryType(memory_requirements.memoryTypeBits, c.VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT),
|
||||||
|
};
|
||||||
|
|
||||||
|
try vk.mapError(c.vkAllocateMemory(device.handle, &alloc_info, null, &image_memory));
|
||||||
|
try vk.mapError(c.vkBindImageMemory(device.handle, image, image_memory, 0));
|
||||||
|
|
||||||
|
try device.transitionImageLayout(image, c.VK_FORMAT_R8G8B8A8_SRGB, c.VK_IMAGE_LAYOUT_UNDEFINED, c.VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
try device.copyBufferToImage(image_buffer, image, @intCast(width), @intCast(height));
|
||||||
|
try device.transitionImageLayout(image, c.VK_FORMAT_R8G8B8A8_SRGB, c.VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, c.VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
|
|
||||||
|
image_buffer.destroy(device.handle);
|
||||||
|
|
||||||
|
const image_view = try createImageView(device, image, c.VK_FORMAT_R8G8B8A8_SRGB);
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.image = image,
|
||||||
|
.image_memory = image_memory,
|
||||||
|
.image_view = image_view,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn destroy(self: Texture, device: vk.Device) void {
|
||||||
|
c.vkDestroyImageView(device.handle, self.image_view, null);
|
||||||
|
c.vkDestroyImage(device.handle, self.image, null);
|
||||||
|
c.vkFreeMemory(device.handle, self.image_memory, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn createImageView(device: anytype, image: c.VkImage, format: c.VkFormat) !c.VkImageView {
|
||||||
|
const create_info: c.VkImageViewCreateInfo = .{
|
||||||
|
.sType = c.VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||||
|
.image = image,
|
||||||
|
.viewType = c.VK_IMAGE_VIEW_TYPE_2D,
|
||||||
|
.format = format,
|
||||||
|
.subresourceRange = .{
|
||||||
|
.aspectMask = c.VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = 1,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var image_view: c.VkImageView = undefined;
|
||||||
|
|
||||||
|
try vk.mapError(c.vkCreateImageView(device.handle, &create_info, null, &image_view));
|
||||||
|
|
||||||
|
return image_view;
|
||||||
|
}
|
||||||
|
|
@ -122,6 +122,7 @@ pub const Model = struct {
|
||||||
const Binary = struct {
|
const Binary = struct {
|
||||||
data: []u8,
|
data: []u8,
|
||||||
const Vec3 = [3]f32;
|
const Vec3 = [3]f32;
|
||||||
|
const Vec2 = [2]f32;
|
||||||
|
|
||||||
pub fn readU16(self: Binary, allocator: Allocator, view: BufferView, count: usize) ![]u16 {
|
pub fn readU16(self: Binary, allocator: Allocator, view: BufferView, count: usize) ![]u16 {
|
||||||
const data = self.data[view.byteOffset .. view.byteOffset + view.byteLength];
|
const data = self.data[view.byteOffset .. view.byteOffset + view.byteLength];
|
||||||
|
|
@ -146,10 +147,21 @@ pub const Model = struct {
|
||||||
|
|
||||||
return vectors;
|
return vectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn readVec2(self: Binary, allocator: Allocator, view: BufferView, count: usize) ![]Vec2 {
|
||||||
|
const data = self.data[view.byteOffset .. view.byteOffset + view.byteLength];
|
||||||
|
const vectors = try allocator.alloc(Vec2, count);
|
||||||
|
|
||||||
|
for (0..count) |i| {
|
||||||
|
vectors[i] = std.mem.bytesAsValue(Vec2, data[(@sizeOf(Vec2) * i) .. (@sizeOf(Vec2) * i) + @sizeOf(Vec2)]).*;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vectors;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn parseFile(allocator: Allocator, name: []const u8) !struct { vertices: [][3]f32, indices: []u16 } {
|
pub fn parseFile(allocator: Allocator, name: []const u8) !struct { vertices: [][3]f32, normals: [][3]f32, uvs: [][2]f32, indices: []u16 } {
|
||||||
const file = try std.fs.cwd().openFile(name, .{});
|
const file = try std.fs.cwd().openFile(name, .{});
|
||||||
const all = try file.readToEndAlloc(allocator, 1_000_000);
|
const all = try file.readToEndAlloc(allocator, 1_000_000);
|
||||||
defer allocator.free(all);
|
defer allocator.free(all);
|
||||||
|
|
@ -162,7 +174,12 @@ pub fn parseFile(allocator: Allocator, name: []const u8) !struct { vertices: [][
|
||||||
const binary = Model.Binary{ .data = all[Model.Chunk.offset + json_chunk.length + 8 ..] };
|
const binary = Model.Binary{ .data = all[Model.Chunk.offset + json_chunk.length + 8 ..] };
|
||||||
|
|
||||||
const vertices = try binary.readVec3(allocator, data.bufferViews.?[data.meshes.?[0].primitives.?[0].attributes.?.POSITION.?], data.accessors.?[data.meshes.?[0].primitives.?[0].attributes.?.POSITION.?].count);
|
const vertices = try binary.readVec3(allocator, data.bufferViews.?[data.meshes.?[0].primitives.?[0].attributes.?.POSITION.?], data.accessors.?[data.meshes.?[0].primitives.?[0].attributes.?.POSITION.?].count);
|
||||||
|
|
||||||
|
const normals = try binary.readVec3(allocator, data.bufferViews.?[data.meshes.?[0].primitives.?[0].attributes.?.NORMAL.?], data.accessors.?[data.meshes.?[0].primitives.?[0].attributes.?.NORMAL.?].count);
|
||||||
|
|
||||||
|
const uvs = try binary.readVec2(allocator, data.bufferViews.?[data.meshes.?[0].primitives.?[0].attributes.?.TEXCOORD_0.?], data.accessors.?[data.meshes.?[0].primitives.?[0].attributes.?.TEXCOORD_0.?].count);
|
||||||
|
|
||||||
const indices = try binary.readU16(allocator, data.bufferViews.?[data.meshes.?[0].primitives.?[0].indices.?], data.accessors.?[data.meshes.?[0].primitives.?[0].indices.?].count);
|
const indices = try binary.readU16(allocator, data.bufferViews.?[data.meshes.?[0].primitives.?[0].indices.?], data.accessors.?[data.meshes.?[0].primitives.?[0].indices.?].count);
|
||||||
|
|
||||||
return .{ .vertices = vertices, .indices = indices };
|
return .{ .vertices = vertices, .normals = normals, .uvs = uvs, .indices = indices };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
pub const Texture = @import("Texture.zig");
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const c = @import("sideros").c;
|
const c = @import("sideros").c;
|
||||||
const Mesh = @import("Mesh.zig");
|
const Mesh = @import("Mesh.zig");
|
||||||
|
|
@ -165,22 +167,7 @@ pub const Buffer = struct {
|
||||||
size: usize,
|
size: usize,
|
||||||
|
|
||||||
pub fn copyTo(self: Buffer, device: anytype, dest: Buffer) !void {
|
pub fn copyTo(self: Buffer, device: anytype, dest: Buffer) !void {
|
||||||
const command_buffer_info: c.VkCommandBufferAllocateInfo = .{
|
const command_buffer = try device.beginSingleTimeCommands();
|
||||||
.sType = c.VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
|
||||||
.commandPool = device.command_pool,
|
|
||||||
.level = c.VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
|
||||||
.commandBufferCount = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
var command_buffer: c.VkCommandBuffer = undefined;
|
|
||||||
try mapError(c.vkAllocateCommandBuffers(device.handle, &command_buffer_info, @ptrCast(&command_buffer)));
|
|
||||||
|
|
||||||
const begin_info: c.VkCommandBufferBeginInfo = .{
|
|
||||||
.sType = c.VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
|
||||||
.flags = c.VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
|
||||||
};
|
|
||||||
|
|
||||||
try mapError(c.vkBeginCommandBuffer(command_buffer, &begin_info));
|
|
||||||
|
|
||||||
const copy_region: c.VkBufferCopy = .{
|
const copy_region: c.VkBufferCopy = .{
|
||||||
.srcOffset = 0,
|
.srcOffset = 0,
|
||||||
|
|
@ -189,17 +176,8 @@ pub const Buffer = struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
c.vkCmdCopyBuffer(command_buffer, self.handle, dest.handle, 1, ©_region);
|
c.vkCmdCopyBuffer(command_buffer, self.handle, dest.handle, 1, ©_region);
|
||||||
try mapError(c.vkEndCommandBuffer(command_buffer));
|
|
||||||
|
|
||||||
const submit_info: c.VkSubmitInfo = .{
|
try device.endSingleTimeCommands(command_buffer);
|
||||||
.sType = c.VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
|
||||||
.commandBufferCount = 1,
|
|
||||||
.pCommandBuffers = &command_buffer,
|
|
||||||
};
|
|
||||||
|
|
||||||
try mapError(c.vkQueueSubmit(device.graphics_queue, 1, &submit_info, null));
|
|
||||||
try mapError(c.vkQueueWaitIdle(device.graphics_queue));
|
|
||||||
c.vkFreeCommandBuffers(device.handle, device.command_pool, 1, &command_buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(self: Buffer, device_handle: c.VkDevice) void {
|
pub fn destroy(self: Buffer, device_handle: c.VkDevice) void {
|
||||||
|
|
@ -208,6 +186,43 @@ pub const Buffer = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Sampler = struct {
|
||||||
|
handle: c.VkSampler,
|
||||||
|
|
||||||
|
pub fn init(device: anytype) !Sampler {
|
||||||
|
var sampler: c.VkSampler = undefined;
|
||||||
|
|
||||||
|
const create_info: c.VkSamplerCreateInfo = .{
|
||||||
|
.sType = c.VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||||
|
.magFilter = c.VK_FILTER_LINEAR,
|
||||||
|
.minFilter = c.VK_FILTER_LINEAR,
|
||||||
|
.addressModeU = c.VK_SAMPLER_ADDRESS_MODE_REPEAT,
|
||||||
|
.addressModeV = c.VK_SAMPLER_ADDRESS_MODE_REPEAT,
|
||||||
|
.addressModeW = c.VK_SAMPLER_ADDRESS_MODE_REPEAT,
|
||||||
|
.borderColor = c.VK_BORDER_COLOR_INT_OPAQUE_BLACK,
|
||||||
|
.unnormalizedCoordinates = c.VK_FALSE,
|
||||||
|
.compareEnable = c.VK_FALSE,
|
||||||
|
.compareOp = c.VK_COMPARE_OP_ALWAYS,
|
||||||
|
.mipmapMode = c.VK_SAMPLER_MIPMAP_MODE_LINEAR,
|
||||||
|
.mipLodBias = 0.0,
|
||||||
|
.minLod = 0.0,
|
||||||
|
.maxLod = 0.0,
|
||||||
|
.anisotropyEnable = c.VK_FALSE,
|
||||||
|
.maxAnisotropy = 1.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
try mapError(c.vkCreateSampler(device.handle, &create_info, null, &sampler));
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.handle = sampler,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: Sampler, device: anytype) void {
|
||||||
|
c.vkDestroySampler(device.handle, self.handle, null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub fn RenderPass(comptime n: usize) type {
|
pub fn RenderPass(comptime n: usize) type {
|
||||||
return struct {
|
return struct {
|
||||||
handle: c.VkRenderPass,
|
handle: c.VkRenderPass,
|
||||||
|
|
@ -267,7 +282,7 @@ pub fn RenderPass(comptime n: usize) type {
|
||||||
|
|
||||||
pub fn begin(self: Self, swapchain: Swapchain(n), device: Device(n), image: usize, frame: usize) void {
|
pub fn begin(self: Self, swapchain: Swapchain(n), device: Device(n), image: usize, frame: usize) void {
|
||||||
std.debug.assert(frame < n);
|
std.debug.assert(frame < n);
|
||||||
const clear_color: c.VkClearValue = .{ .color = .{ .float32 = .{ 1.0, 0.0, 0.0, 1.0 } } };
|
const clear_color: c.VkClearValue = .{ .color = .{ .float32 = .{ 0.0, 0.0, 0.0, 1.0 } } };
|
||||||
|
|
||||||
const begin_info: c.VkRenderPassBeginInfo = .{
|
const begin_info: c.VkRenderPassBeginInfo = .{
|
||||||
.sType = c.VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
.sType = c.VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||||
|
|
@ -300,16 +315,23 @@ pub fn GraphicsPipeline(comptime n: usize) type {
|
||||||
return struct {
|
return struct {
|
||||||
layout: c.VkPipelineLayout,
|
layout: c.VkPipelineLayout,
|
||||||
handle: c.VkPipeline,
|
handle: c.VkPipeline,
|
||||||
|
texture_set_layout: c.VkDescriptorSetLayout,
|
||||||
descriptor_pool: c.VkDescriptorPool,
|
descriptor_pool: c.VkDescriptorPool,
|
||||||
descriptor_set: c.VkDescriptorSet,
|
descriptor_set: c.VkDescriptorSet,
|
||||||
descriptor_set_layout: c.VkDescriptorSetLayout,
|
descriptor_set_layout: c.VkDescriptorSetLayout,
|
||||||
projection_buffer: Buffer,
|
projection_buffer: Buffer,
|
||||||
|
light_buffer: Buffer,
|
||||||
view_buffer: Buffer,
|
view_buffer: Buffer,
|
||||||
view_memory: [*c]u8,
|
view_memory: [*c]u8,
|
||||||
|
view_pos_memory: [*c]u8,
|
||||||
|
texture_sampler: Sampler,
|
||||||
|
diffuse_sampler: Sampler,
|
||||||
|
textures: std.ArrayList(c.VkDescriptorSet),
|
||||||
|
light_pos: [*]f32,
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
pub fn create(device: Device(n), swapchain: Swapchain(n), render_pass: RenderPass(n), vertex_shader: c.VkShaderModule, fragment_shader: c.VkShaderModule) !Self {
|
pub fn create(allocator: std.mem.Allocator, device: Device(n), swapchain: Swapchain(n), render_pass: RenderPass(n), vertex_shader: c.VkShaderModule, fragment_shader: c.VkShaderModule) !Self {
|
||||||
const vertex_shader_stage_info: c.VkPipelineShaderStageCreateInfo = .{
|
const vertex_shader_stage_info: c.VkPipelineShaderStageCreateInfo = .{
|
||||||
.sType = c.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
.sType = c.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
.stage = c.VK_SHADER_STAGE_VERTEX_BIT,
|
.stage = c.VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
|
@ -327,14 +349,14 @@ pub fn GraphicsPipeline(comptime n: usize) type {
|
||||||
// TODO: shouldn't this be closer to usage?
|
// TODO: shouldn't this be closer to usage?
|
||||||
const shader_stage_infos: []const c.VkPipelineShaderStageCreateInfo = &.{ vertex_shader_stage_info, fragment_shader_stage_info };
|
const shader_stage_infos: []const c.VkPipelineShaderStageCreateInfo = &.{ vertex_shader_stage_info, fragment_shader_stage_info };
|
||||||
|
|
||||||
const vertex_attributes: []const c.VkVertexInputAttributeDescription = &.{Mesh.Vertex.attributeDescription()};
|
const vertex_attributes: []const c.VkVertexInputAttributeDescription = Mesh.Vertex.attributeDescriptions();
|
||||||
const vertex_bindings: []const c.VkVertexInputBindingDescription = &.{Mesh.Vertex.bindingDescription()};
|
const vertex_bindings: []const c.VkVertexInputBindingDescription = &.{Mesh.Vertex.bindingDescription()};
|
||||||
|
|
||||||
const vertex_input_info: c.VkPipelineVertexInputStateCreateInfo = .{
|
const vertex_input_info: c.VkPipelineVertexInputStateCreateInfo = .{
|
||||||
.sType = c.VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
.sType = c.VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
.vertexBindingDescriptionCount = 1,
|
.vertexBindingDescriptionCount = 1,
|
||||||
.pVertexBindingDescriptions = vertex_bindings.ptr,
|
.pVertexBindingDescriptions = vertex_bindings.ptr,
|
||||||
.vertexAttributeDescriptionCount = 1,
|
.vertexAttributeDescriptionCount = 3,
|
||||||
.pVertexAttributeDescriptions = vertex_attributes.ptr,
|
.pVertexAttributeDescriptions = vertex_attributes.ptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -375,8 +397,7 @@ pub fn GraphicsPipeline(comptime n: usize) type {
|
||||||
.rasterizerDiscardEnable = c.VK_FALSE,
|
.rasterizerDiscardEnable = c.VK_FALSE,
|
||||||
.polygonMode = c.VK_POLYGON_MODE_FILL,
|
.polygonMode = c.VK_POLYGON_MODE_FILL,
|
||||||
.lineWidth = 1.0,
|
.lineWidth = 1.0,
|
||||||
//.cullMode = c.VK_CULL_MODE_BACK_BIT,
|
.cullMode = c.VK_CULL_MODE_BACK_BIT,
|
||||||
.cullMode = c.VK_CULL_MODE_NONE,
|
|
||||||
.frontFace = c.VK_FRONT_FACE_COUNTER_CLOCKWISE,
|
.frontFace = c.VK_FRONT_FACE_COUNTER_CLOCKWISE,
|
||||||
.depthBiasEnable = c.VK_FALSE,
|
.depthBiasEnable = c.VK_FALSE,
|
||||||
};
|
};
|
||||||
|
|
@ -421,23 +442,60 @@ pub fn GraphicsPipeline(comptime n: usize) type {
|
||||||
.stageFlags = c.VK_SHADER_STAGE_VERTEX_BIT,
|
.stageFlags = c.VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
};
|
};
|
||||||
|
|
||||||
const bindings = [_]c.VkDescriptorSetLayoutBinding{projection_binding, view_binding};
|
const light_binding = c.VkDescriptorSetLayoutBinding{
|
||||||
|
.binding = 2,
|
||||||
|
.descriptorType = c.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.stageFlags = c.VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
};
|
||||||
|
|
||||||
|
const view_pos_binding = c.VkDescriptorSetLayoutBinding{
|
||||||
|
.binding = 3,
|
||||||
|
.descriptorType = c.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.stageFlags = c.VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
};
|
||||||
|
|
||||||
|
const texture_sampler_binding = c.VkDescriptorSetLayoutBinding{
|
||||||
|
.binding = 0,
|
||||||
|
.descriptorType = c.VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.stageFlags = c.VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
};
|
||||||
|
|
||||||
|
const diffuse_sampler_binding = c.VkDescriptorSetLayoutBinding{
|
||||||
|
.binding = 1,
|
||||||
|
.descriptorType = c.VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.stageFlags = c.VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
};
|
||||||
|
|
||||||
|
const bindings = [_]c.VkDescriptorSetLayoutBinding{projection_binding, view_binding, light_binding, view_pos_binding};
|
||||||
|
const texture_bindings = [_]c.VkDescriptorSetLayoutBinding{texture_sampler_binding, diffuse_sampler_binding};
|
||||||
|
|
||||||
var descriptor_set_layout: c.VkDescriptorSetLayout = undefined;
|
var descriptor_set_layout: c.VkDescriptorSetLayout = undefined;
|
||||||
|
var texture_descriptor_set_layout: c.VkDescriptorSetLayout = undefined;
|
||||||
|
|
||||||
const descriptor_set_layout_info = c.VkDescriptorSetLayoutCreateInfo{
|
const descriptor_set_layout_info = c.VkDescriptorSetLayoutCreateInfo{
|
||||||
.sType = c.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
.sType = c.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||||
.bindingCount = 2,
|
.bindingCount = 4,
|
||||||
.pBindings = bindings[0..].ptr,
|
.pBindings = bindings[0..].ptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
try mapError(c.vkCreateDescriptorSetLayout(device.handle, &descriptor_set_layout_info, null, &descriptor_set_layout));
|
const texture_descriptor_set_layout_info = c.VkDescriptorSetLayoutCreateInfo{
|
||||||
|
.sType = c.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||||
|
.bindingCount = 2,
|
||||||
|
.pBindings = texture_bindings[0..].ptr,
|
||||||
|
};
|
||||||
|
|
||||||
const set_layouts = [_]c.VkDescriptorSetLayout{descriptor_set_layout};
|
try mapError(c.vkCreateDescriptorSetLayout(device.handle, &descriptor_set_layout_info, null, &descriptor_set_layout));
|
||||||
|
try mapError(c.vkCreateDescriptorSetLayout(device.handle, &texture_descriptor_set_layout_info, null, &texture_descriptor_set_layout));
|
||||||
|
|
||||||
|
var set_layouts = [_]c.VkDescriptorSetLayout{descriptor_set_layout, texture_descriptor_set_layout};
|
||||||
|
|
||||||
const layout_info: c.VkPipelineLayoutCreateInfo = .{
|
const layout_info: c.VkPipelineLayoutCreateInfo = .{
|
||||||
.sType = c.VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
.sType = c.VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||||
.setLayoutCount = 1,
|
.setLayoutCount = 2,
|
||||||
.pSetLayouts = set_layouts[0..].ptr,
|
.pSetLayouts = set_layouts[0..].ptr,
|
||||||
.pushConstantRangeCount = 0,
|
.pushConstantRangeCount = 0,
|
||||||
.pPushConstantRanges = null,
|
.pPushConstantRanges = null,
|
||||||
|
|
@ -470,16 +528,23 @@ pub fn GraphicsPipeline(comptime n: usize) type {
|
||||||
|
|
||||||
try mapError(c.vkCreateGraphicsPipelines(device.handle, null, 1, &pipeline_info, null, @ptrCast(&pipeline)));
|
try mapError(c.vkCreateGraphicsPipelines(device.handle, null, 1, &pipeline_info, null, @ptrCast(&pipeline)));
|
||||||
|
|
||||||
var size = c.VkDescriptorPoolSize{
|
const size = c.VkDescriptorPoolSize{
|
||||||
.type = c.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
.type = c.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
.descriptorCount = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
const sampler_size = c.VkDescriptorPoolSize{
|
||||||
|
.type = c.VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
.descriptorCount = 2,
|
.descriptorCount = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const sizes = [_]c.VkDescriptorPoolSize {size, sampler_size};
|
||||||
|
|
||||||
const descriptor_pool_info = c.VkDescriptorPoolCreateInfo{
|
const descriptor_pool_info = c.VkDescriptorPoolCreateInfo{
|
||||||
.sType = c.VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
.sType = c.VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||||
.maxSets = 1,
|
.maxSets = 2,
|
||||||
.poolSizeCount = 1,
|
.poolSizeCount = 2,
|
||||||
.pPoolSizes = &size,
|
.pPoolSizes = sizes[0..].ptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
var descriptor_pool: c.VkDescriptorPool = undefined;
|
var descriptor_pool: c.VkDescriptorPool = undefined;
|
||||||
|
|
@ -562,24 +627,152 @@ pub fn GraphicsPipeline(comptime n: usize) type {
|
||||||
|
|
||||||
c.vkUpdateDescriptorSets(device.handle, 1, &write_view_descriptor_set, 0, null);
|
c.vkUpdateDescriptorSets(device.handle, 1, &write_view_descriptor_set, 0, null);
|
||||||
|
|
||||||
|
const light_buffer = try device.createBuffer(BufferUsage{ .uniform_buffer = true, .transfer_dst = true }, BufferFlags{ .device_local = true }, @sizeOf([3]f32));
|
||||||
|
|
||||||
|
var light_data: [*c]u8 = undefined;
|
||||||
|
|
||||||
|
try mapError(c.vkMapMemory(
|
||||||
|
device.handle,
|
||||||
|
light_buffer.memory,
|
||||||
|
0,
|
||||||
|
light_buffer.size,
|
||||||
|
0,
|
||||||
|
@ptrCast(&light_data),
|
||||||
|
));
|
||||||
|
|
||||||
|
const light_pos: [*]f32 = @alignCast(@ptrCast(light_data));
|
||||||
|
|
||||||
|
const light_descriptor_buffer_info = c.VkDescriptorBufferInfo{
|
||||||
|
.buffer = light_buffer.handle,
|
||||||
|
.offset = 0,
|
||||||
|
.range = light_buffer.size,
|
||||||
|
};
|
||||||
|
|
||||||
|
const write_light_descriptor_set = c.VkWriteDescriptorSet{
|
||||||
|
.sType = c.VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
|
.dstSet = descriptor_set,
|
||||||
|
.dstBinding = 2,
|
||||||
|
.dstArrayElement = 0,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = c.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
.pBufferInfo = &light_descriptor_buffer_info,
|
||||||
|
};
|
||||||
|
|
||||||
|
c.vkUpdateDescriptorSets(device.handle, 1, &write_light_descriptor_set, 0, null);
|
||||||
|
|
||||||
|
const view_pos_buffer = try device.createBuffer(BufferUsage{ .uniform_buffer = true, .transfer_dst = true }, BufferFlags{ .device_local = true }, @sizeOf([3]f32));
|
||||||
|
|
||||||
|
var view_pos_data: [*c]u8 = undefined;
|
||||||
|
|
||||||
|
try mapError(c.vkMapMemory(
|
||||||
|
device.handle,
|
||||||
|
view_pos_buffer.memory,
|
||||||
|
0,
|
||||||
|
view_pos_buffer.size,
|
||||||
|
0,
|
||||||
|
@ptrCast(&view_pos_data),
|
||||||
|
));
|
||||||
|
|
||||||
|
const view_pos_descriptor_buffer_info = c.VkDescriptorBufferInfo{
|
||||||
|
.buffer = view_pos_buffer.handle,
|
||||||
|
.offset = 0,
|
||||||
|
.range = view_pos_buffer.size,
|
||||||
|
};
|
||||||
|
|
||||||
|
const write_view_pos_descriptor_set = c.VkWriteDescriptorSet{
|
||||||
|
.sType = c.VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
|
.dstSet = descriptor_set,
|
||||||
|
.dstBinding = 3,
|
||||||
|
.dstArrayElement = 0,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = c.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
.pBufferInfo = &view_pos_descriptor_buffer_info,
|
||||||
|
};
|
||||||
|
|
||||||
|
c.vkUpdateDescriptorSets(device.handle, 1, &write_view_pos_descriptor_set, 0, null);
|
||||||
|
|
||||||
return Self{
|
return Self{
|
||||||
.layout = layout,
|
.layout = layout,
|
||||||
.handle = pipeline,
|
.handle = pipeline,
|
||||||
|
.texture_set_layout = texture_descriptor_set_layout,
|
||||||
.descriptor_pool = descriptor_pool,
|
.descriptor_pool = descriptor_pool,
|
||||||
.descriptor_set = descriptor_set,
|
.descriptor_set = descriptor_set,
|
||||||
.descriptor_set_layout = descriptor_set_layout,
|
.descriptor_set_layout = descriptor_set_layout,
|
||||||
.projection_buffer = projection_buffer,
|
.projection_buffer = projection_buffer,
|
||||||
.view_buffer = view_buffer,
|
.view_buffer = view_buffer,
|
||||||
.view_memory = view_data,
|
.view_memory = view_data,
|
||||||
|
.light_buffer = light_buffer,
|
||||||
|
.view_pos_memory = view_pos_data,
|
||||||
|
.texture_sampler = try Sampler.init(device),
|
||||||
|
.diffuse_sampler = try Sampler.init(device),
|
||||||
|
.textures = std.ArrayList(c.VkDescriptorSet).init(allocator),
|
||||||
|
.light_pos = light_pos,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn addTexture(self: *Self, device: anytype, texture: Texture, diffuse: Texture) !usize {
|
||||||
|
var set_layouts = [_]c.VkDescriptorSetLayout{self.texture_set_layout};
|
||||||
|
const descriptor_allocate_info = c.VkDescriptorSetAllocateInfo{
|
||||||
|
.sType = c.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||||
|
.descriptorPool = self.descriptor_pool,
|
||||||
|
.descriptorSetCount = 1,
|
||||||
|
.pSetLayouts = set_layouts[0..].ptr,
|
||||||
|
};
|
||||||
|
|
||||||
|
var descriptor_set: c.VkDescriptorSet = undefined;
|
||||||
|
try mapError(c.vkAllocateDescriptorSets(device.handle, &descriptor_allocate_info, &descriptor_set));
|
||||||
|
|
||||||
|
const texture_info: c.VkDescriptorImageInfo = .{
|
||||||
|
.imageLayout = c.VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
.imageView = texture.image_view,
|
||||||
|
.sampler = self.texture_sampler.handle,
|
||||||
|
};
|
||||||
|
|
||||||
|
const diffuse_info: c.VkDescriptorImageInfo = .{
|
||||||
|
.imageLayout = c.VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
.imageView = diffuse.image_view,
|
||||||
|
.sampler = self.diffuse_sampler.handle,
|
||||||
|
};
|
||||||
|
|
||||||
|
const write_texture_descriptor_set = c.VkWriteDescriptorSet{
|
||||||
|
.sType = c.VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
|
.dstSet = descriptor_set,
|
||||||
|
.dstBinding = 0,
|
||||||
|
.dstArrayElement = 0,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = c.VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
|
.pImageInfo = &texture_info,
|
||||||
|
};
|
||||||
|
|
||||||
|
const write_diffuse_descriptor_set = c.VkWriteDescriptorSet{
|
||||||
|
.sType = c.VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
|
.dstSet = descriptor_set,
|
||||||
|
.dstBinding = 1,
|
||||||
|
.dstArrayElement = 0,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = c.VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
|
.pImageInfo = &diffuse_info,
|
||||||
|
};
|
||||||
|
|
||||||
|
const writes = [_]c.VkWriteDescriptorSet {write_texture_descriptor_set, write_diffuse_descriptor_set};
|
||||||
|
|
||||||
|
c.vkUpdateDescriptorSets(device.handle, 2, writes[0..].ptr, 0, null);
|
||||||
|
|
||||||
|
const index = self.textures.items.len;
|
||||||
|
try self.textures.append(descriptor_set);
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bind(self: Self, device: Device(n), frame: usize) void {
|
pub fn bind(self: Self, device: Device(n), frame: usize) void {
|
||||||
std.debug.assert(frame < n);
|
std.debug.assert(frame < n);
|
||||||
c.vkCmdBindPipeline(device.command_buffers[frame], c.VK_PIPELINE_BIND_POINT_GRAPHICS, self.handle);
|
c.vkCmdBindPipeline(device.command_buffers[frame], c.VK_PIPELINE_BIND_POINT_GRAPHICS, self.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(self: Self, device: Device(n)) void {
|
pub fn destroy(self: Self, device: Device(n)) void {
|
||||||
|
self.textures.deinit();
|
||||||
|
self.texture_sampler.deinit(device);
|
||||||
|
self.diffuse_sampler.deinit(device);
|
||||||
self.projection_buffer.destroy(device.handle);
|
self.projection_buffer.destroy(device.handle);
|
||||||
c.vkDestroyDescriptorSetLayout(device.handle, self.descriptor_set_layout, null);
|
c.vkDestroyDescriptorSetLayout(device.handle, self.descriptor_set_layout, null);
|
||||||
c.vkDestroyDescriptorPool(device.handle, self.descriptor_pool, null);
|
c.vkDestroyDescriptorPool(device.handle, self.descriptor_pool, null);
|
||||||
|
|
@ -865,6 +1058,7 @@ pub fn Device(comptime n: usize) type {
|
||||||
in_flight_fence: [n]c.VkFence,
|
in_flight_fence: [n]c.VkFence,
|
||||||
graphics_family: u32,
|
graphics_family: u32,
|
||||||
present_family: u32,
|
present_family: u32,
|
||||||
|
device_properties: c.VkPhysicalDeviceProperties,
|
||||||
memory_properties: c.VkPhysicalDeviceMemoryProperties,
|
memory_properties: c.VkPhysicalDeviceMemoryProperties,
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
@ -888,11 +1082,147 @@ pub fn Device(comptime n: usize) type {
|
||||||
try mapError(c.vkEndCommandBuffer(self.command_buffers[frame]));
|
try mapError(c.vkEndCommandBuffer(self.command_buffers[frame]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn beginSingleTimeCommands(self: Self) !c.VkCommandBuffer {
|
||||||
|
const command_buffer_info: c.VkCommandBufferAllocateInfo = .{
|
||||||
|
.sType = c.VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||||
|
.commandPool = self.command_pool,
|
||||||
|
.level = c.VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||||
|
.commandBufferCount = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
var command_buffer: c.VkCommandBuffer = undefined;
|
||||||
|
try mapError(c.vkAllocateCommandBuffers(self.handle, &command_buffer_info, @ptrCast(&command_buffer)));
|
||||||
|
|
||||||
|
const begin_info: c.VkCommandBufferBeginInfo = .{
|
||||||
|
.sType = c.VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||||
|
.flags = c.VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
||||||
|
};
|
||||||
|
|
||||||
|
try mapError(c.vkBeginCommandBuffer(command_buffer, &begin_info));
|
||||||
|
|
||||||
|
return command_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn endSingleTimeCommands(self: Self, command_buffer: c.VkCommandBuffer) !void {
|
||||||
|
try mapError(c.vkEndCommandBuffer(command_buffer));
|
||||||
|
|
||||||
|
const submit_info: c.VkSubmitInfo = .{
|
||||||
|
.sType = c.VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||||
|
.commandBufferCount = 1,
|
||||||
|
.pCommandBuffers = &command_buffer,
|
||||||
|
};
|
||||||
|
|
||||||
|
try mapError(c.vkQueueSubmit(self.graphics_queue, 1, &submit_info, null));
|
||||||
|
try mapError(c.vkQueueWaitIdle(self.graphics_queue));
|
||||||
|
c.vkFreeCommandBuffers(self.handle, self.command_pool, 1, &command_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn copyBufferToImage(self: Self, buffer: Buffer, image: c.VkImage, width: u32, height: u32) !void {
|
||||||
|
const command_buffer = try self.beginSingleTimeCommands();
|
||||||
|
|
||||||
|
const region: c.VkBufferImageCopy = .{
|
||||||
|
.bufferOffset = 0,
|
||||||
|
.bufferRowLength = 0,
|
||||||
|
.bufferImageHeight = 0,
|
||||||
|
.imageSubresource = .{
|
||||||
|
.aspectMask = c.VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.mipLevel = 0,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = 1,
|
||||||
|
},
|
||||||
|
.imageOffset = .{
|
||||||
|
.x = 0, .y = 0, .z = 0,
|
||||||
|
},
|
||||||
|
.imageExtent = .{
|
||||||
|
.width = width, .height = height, .depth = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
c.vkCmdCopyBufferToImage(
|
||||||
|
command_buffer,
|
||||||
|
buffer.handle,
|
||||||
|
image,
|
||||||
|
c.VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
1,
|
||||||
|
®ion
|
||||||
|
);
|
||||||
|
|
||||||
|
try self.endSingleTimeCommands(command_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn transitionImageLayout(self: Self, image: c.VkImage, format: c.VkFormat, old_layout: c.VkImageLayout, new_layout: c.VkImageLayout) !void {
|
||||||
|
_ = format;
|
||||||
|
const command_buffer = try self.beginSingleTimeCommands();
|
||||||
|
|
||||||
|
var barrier: c.VkImageMemoryBarrier = .{
|
||||||
|
.sType = c.VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
|
.oldLayout = old_layout,
|
||||||
|
.newLayout = new_layout,
|
||||||
|
.srcQueueFamilyIndex = c.VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.dstQueueFamilyIndex = c.VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.image = image,
|
||||||
|
.subresourceRange = .{
|
||||||
|
.aspectMask = c.VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = 1,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = 1,
|
||||||
|
},
|
||||||
|
.srcAccessMask = 0,
|
||||||
|
.dstAccessMask = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
var sourceStage: c.VkPipelineStageFlags = undefined;
|
||||||
|
var destinationStage: c.VkPipelineStageFlags = undefined;
|
||||||
|
|
||||||
|
if (old_layout == c.VK_IMAGE_LAYOUT_UNDEFINED and new_layout == c.VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
|
||||||
|
barrier.srcAccessMask = 0;
|
||||||
|
barrier.dstAccessMask = c.VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
|
||||||
|
sourceStage = c.VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||||
|
destinationStage = c.VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
} else if (old_layout == c.VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL and new_layout == c.VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
|
||||||
|
barrier.srcAccessMask = c.VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
barrier.dstAccessMask = c.VK_ACCESS_SHADER_READ_BIT;
|
||||||
|
|
||||||
|
sourceStage = c.VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
destinationStage = c.VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||||
|
} else {
|
||||||
|
return error.UnsupportedTransition;
|
||||||
|
}
|
||||||
|
|
||||||
|
c.vkCmdPipelineBarrier(
|
||||||
|
command_buffer,
|
||||||
|
sourceStage,
|
||||||
|
destinationStage,
|
||||||
|
0,
|
||||||
|
0, null,
|
||||||
|
0, null,
|
||||||
|
1, &barrier
|
||||||
|
);
|
||||||
|
|
||||||
|
try self.endSingleTimeCommands(command_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub fn draw(self: Self, indices: u32, frame: usize) void {
|
pub fn draw(self: Self, indices: u32, frame: usize) void {
|
||||||
std.debug.assert(frame < n);
|
std.debug.assert(frame < n);
|
||||||
c.vkCmdDrawIndexed(self.command_buffers[frame], indices, 1, 0, 0, 0);
|
c.vkCmdDrawIndexed(self.command_buffers[frame], indices, 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn findMemoryType(self: Self, filter: u32, properties: c.VkMemoryPropertyFlags) error{NoSuitableMemory}!u32 {
|
||||||
|
const memory_properties = self.memory_properties;
|
||||||
|
|
||||||
|
for (0..memory_properties.memoryTypeCount) |i| {
|
||||||
|
if ((filter & (@as(u32, 1) << @intCast(i))) != 0 and (memory_properties.memoryTypes[i].propertyFlags & properties) == properties) {
|
||||||
|
return @intCast(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return error.NoSuitableMemory;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn waitFence(self: Self, frame: usize) !void {
|
pub fn waitFence(self: Self, frame: usize) !void {
|
||||||
//std.debug.assert(frame < n);
|
//std.debug.assert(frame < n);
|
||||||
try mapError(c.vkWaitForFences(self.handle, 1, &self.in_flight_fence[frame], c.VK_TRUE, std.math.maxInt(u64)));
|
try mapError(c.vkWaitForFences(self.handle, 1, &self.in_flight_fence[frame], c.VK_TRUE, std.math.maxInt(u64)));
|
||||||
|
|
@ -917,8 +1247,9 @@ pub fn Device(comptime n: usize) type {
|
||||||
c.vkCmdBindVertexBuffers(self.command_buffers[frame], 0, 1, &buffer.handle, &offset);
|
c.vkCmdBindVertexBuffers(self.command_buffers[frame], 0, 1, &buffer.handle, &offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bindDescriptorSets(self: Self, pipeline: GraphicsPipeline(n), frame: usize) void {
|
pub fn bindDescriptorSets(self: Self, pipeline: GraphicsPipeline(n), frame: usize, texture: usize) void {
|
||||||
c.vkCmdBindDescriptorSets(self.command_buffers[frame], c.VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.layout, 0, 1, &pipeline.descriptor_set, 0, null);
|
const sets = [_]c.VkDescriptorSet {pipeline.descriptor_set, pipeline.textures.items[texture]};
|
||||||
|
c.vkCmdBindDescriptorSets(self.command_buffers[frame], c.VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.layout, 0, 2, sets[0..].ptr, 0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateBuffer(self: Self, comptime T: type, buffer: Buffer, data: [*]T, frame: usize) void {
|
pub fn updateBuffer(self: Self, comptime T: type, buffer: Buffer, data: [*]T, frame: usize) void {
|
||||||
|
|
@ -1083,6 +1414,8 @@ pub const PhysicalDevice = struct {
|
||||||
return graphics_queue.?;
|
return graphics_queue.?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub fn presentQueue(self: PhysicalDevice, surface: Surface, allocator: Allocator) !u32 {
|
pub fn presentQueue(self: PhysicalDevice, surface: Surface, allocator: Allocator) !u32 {
|
||||||
const queue_families = try self.queueFamilyProperties(allocator);
|
const queue_families = try self.queueFamilyProperties(allocator);
|
||||||
defer allocator.free(queue_families);
|
defer allocator.free(queue_families);
|
||||||
|
|
@ -1192,6 +1525,9 @@ pub const PhysicalDevice = struct {
|
||||||
var memory_properties: c.VkPhysicalDeviceMemoryProperties = undefined;
|
var memory_properties: c.VkPhysicalDeviceMemoryProperties = undefined;
|
||||||
c.vkGetPhysicalDeviceMemoryProperties(self.handle, &memory_properties);
|
c.vkGetPhysicalDeviceMemoryProperties(self.handle, &memory_properties);
|
||||||
|
|
||||||
|
var device_properties: c.VkPhysicalDeviceProperties = undefined;
|
||||||
|
c.vkGetPhysicalDeviceProperties(self.handle, &device_properties);
|
||||||
|
|
||||||
return Device(n){
|
return Device(n){
|
||||||
.handle = device,
|
.handle = device,
|
||||||
.graphics_queue = graphics_queue,
|
.graphics_queue = graphics_queue,
|
||||||
|
|
@ -1204,6 +1540,7 @@ pub const PhysicalDevice = struct {
|
||||||
.graphics_family = graphics_queue_index,
|
.graphics_family = graphics_queue_index,
|
||||||
.present_family = present_queue_index,
|
.present_family = present_queue_index,
|
||||||
.memory_properties = memory_properties,
|
.memory_properties = memory_properties,
|
||||||
|
.device_properties = device_properties,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -58,10 +58,11 @@ fn toplevelHandleConfigure(data: ?*anyopaque, toplevel: ?*c.xdg_toplevel, width:
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toplevelHandleClose(data: ?*anyopaque, toplevel: ?*c.xdg_toplevel) callconv(.c) void {
|
fn toplevelHandleClose(data: ?*anyopaque, toplevel: ?*c.xdg_toplevel) callconv(.c) void {
|
||||||
_ = data;
|
const state: *State = @alignCast(@ptrCast(data));
|
||||||
_ = toplevel;
|
_ = toplevel;
|
||||||
|
|
||||||
quit = true;
|
quit = true;
|
||||||
|
state.pool.resources.renderer.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toplevelHandleConfigureBounds(data: ?*anyopaque, toplevel: ?*c.xdg_toplevel, width: i32, height: i32) callconv(.c) void {
|
fn toplevelHandleConfigureBounds(data: ?*anyopaque, toplevel: ?*c.xdg_toplevel, width: i32, height: i32) callconv(.c) void {
|
||||||
|
|
@ -124,7 +125,7 @@ pub fn init(allocator: std.mem.Allocator, pool: *ecs.Pool) !void {
|
||||||
state.surface = surface;
|
state.surface = surface;
|
||||||
|
|
||||||
const toplevel = c.xdg_surface_get_toplevel(xdg_surface);
|
const toplevel = c.xdg_surface_get_toplevel(xdg_surface);
|
||||||
_ = c.xdg_toplevel_add_listener(toplevel, &toplevel_listener, null);
|
_ = c.xdg_toplevel_add_listener(toplevel, &toplevel_listener, @ptrCast(&state));
|
||||||
const title = [_]u8 {'s', 'i', 'd', 'e', 'r', 'o', 's', 0};
|
const title = [_]u8 {'s', 'i', 'd', 'e', 'r', 'o', 's', 0};
|
||||||
c.xdg_toplevel_set_title(toplevel, @ptrCast(&title[0]));
|
c.xdg_toplevel_set_title(toplevel, @ptrCast(&title[0]));
|
||||||
c.xdg_toplevel_set_app_id(toplevel, @ptrCast(&title[0]));
|
c.xdg_toplevel_set_app_id(toplevel, @ptrCast(&title[0]));
|
||||||
|
|
@ -138,9 +139,8 @@ pub fn init(allocator: std.mem.Allocator, pool: *ecs.Pool) !void {
|
||||||
}
|
}
|
||||||
|
|
||||||
var renderer = try Renderer.init(@TypeOf(display), @TypeOf(surface), allocator, display, surface);
|
var renderer = try Renderer.init(@TypeOf(display), @TypeOf(surface), allocator, display, surface);
|
||||||
defer renderer.deinit();
|
|
||||||
|
|
||||||
pool.resources.renderer = renderer;
|
pool.resources.renderer = &renderer;
|
||||||
state.pool = pool;
|
state.pool = pool;
|
||||||
pool.tick();
|
pool.tick();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ pub fn init(allocator: std.mem.Allocator, pool: *ecs.Pool) !void {
|
||||||
var renderer = try Renderer.init(@TypeOf(connection), @TypeOf(window), allocator, connection, window);
|
var renderer = try Renderer.init(@TypeOf(connection), @TypeOf(window), allocator, connection, window);
|
||||||
defer renderer.deinit();
|
defer renderer.deinit();
|
||||||
|
|
||||||
pool.resources.renderer = renderer;
|
pool.resources.renderer = &renderer;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (c.xcb_poll_for_event(connection)) |e| {
|
if (c.xcb_poll_for_event(connection)) |e| {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue