Add vertex input
This commit is contained in:
parent
c4193db891
commit
2ec8a315c6
9 changed files with 179 additions and 88 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,2 +1,2 @@
|
||||||
/zig-out
|
zig-out
|
||||||
/.zig-cache
|
.zig-cache
|
||||||
|
|
1
.ignore
Normal file
1
.ignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
libs/
|
35
build.zig
35
build.zig
|
@ -2,19 +2,9 @@ const std = @import("std");
|
||||||
const sdl = @import("sdl");
|
const sdl = @import("sdl");
|
||||||
const vkgen = @import("vulkan_zig");
|
const vkgen = @import("vulkan_zig");
|
||||||
|
|
||||||
// Although this function looks imperative, note that its job is to
|
|
||||||
// declaratively construct a build graph that will be executed by an external
|
|
||||||
// runner.
|
|
||||||
pub fn build(b: *std.Build) void {
|
pub fn build(b: *std.Build) void {
|
||||||
// Standard target options allows the person running `zig build` to choose
|
|
||||||
// what target to build for. Here we do not override the defaults, which
|
|
||||||
// means any target is allowed, and the default is native. Other options
|
|
||||||
// for restricting supported target set are available.
|
|
||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
|
|
||||||
// Standard optimization options allow the person running `zig build` to select
|
|
||||||
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
|
|
||||||
// set a preferred release mode, allowing the user to decide how to optimize.
|
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
const exe = b.addExecutable(.{
|
const exe = b.addExecutable(.{
|
||||||
|
@ -24,6 +14,7 @@ pub fn build(b: *std.Build) void {
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Vulkan
|
||||||
const vkzig_dep = b.dependency("vulkan_zig", .{
|
const vkzig_dep = b.dependency("vulkan_zig", .{
|
||||||
.registry = @as([]const u8, b.pathFromRoot("./vk.xml")),
|
.registry = @as([]const u8, b.pathFromRoot("./vk.xml")),
|
||||||
});
|
});
|
||||||
|
@ -39,35 +30,24 @@ pub fn build(b: *std.Build) void {
|
||||||
shader_comp.add("shader_vert", "src/shaders/shader.vert", .{});
|
shader_comp.add("shader_vert", "src/shaders/shader.vert", .{});
|
||||||
exe.root_module.addImport("shaders", shader_comp.getModule());
|
exe.root_module.addImport("shaders", shader_comp.getModule());
|
||||||
|
|
||||||
|
// SDL2
|
||||||
const sdl_sdk = sdl.init(b, null);
|
const sdl_sdk = sdl.init(b, null);
|
||||||
sdl_sdk.link(exe, .dynamic);
|
sdl_sdk.link(exe, .dynamic);
|
||||||
|
|
||||||
exe.root_module.addImport("sdl2", sdl_sdk.getWrapperModuleVulkan(vkzig_bindings));
|
exe.root_module.addImport("sdl2", sdl_sdk.getWrapperModuleVulkan(vkzig_bindings));
|
||||||
// This declares intent for the executable to be installed into the
|
|
||||||
// standard location when the user invokes the "install" step (the default
|
|
||||||
// step when running `zig build`).
|
|
||||||
b.installArtifact(exe);
|
b.installArtifact(exe);
|
||||||
|
|
||||||
// This *creates* a Run step in the build graph, to be executed when another
|
const check = b.step("check", "Check if vulkan-test compiles");
|
||||||
// step is evaluated that depends on it. The next line below will establish
|
check.dependOn(&exe.step);
|
||||||
// such a dependency.
|
|
||||||
const run_cmd = b.addRunArtifact(exe);
|
const run_cmd = b.addRunArtifact(exe);
|
||||||
|
|
||||||
// By making the run step depend on the install step, it will be run from the
|
|
||||||
// installation directory rather than directly from within the cache directory.
|
|
||||||
// This is not necessary, however, if the application depends on other installed
|
|
||||||
// files, this ensures they will be present and in the expected location.
|
|
||||||
run_cmd.step.dependOn(b.getInstallStep());
|
run_cmd.step.dependOn(b.getInstallStep());
|
||||||
|
|
||||||
// This allows the user to pass arguments to the application in the build
|
|
||||||
// command itself, like this: `zig build run -- arg1 arg2 etc`
|
|
||||||
if (b.args) |args| {
|
if (b.args) |args| {
|
||||||
run_cmd.addArgs(args);
|
run_cmd.addArgs(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This creates a build step. It will be visible in the `zig build --help` menu,
|
|
||||||
// and can be selected like this: `zig build run`
|
|
||||||
// This will evaluate the `run` step rather than the default, which is "install".
|
|
||||||
const run_step = b.step("run", "Run the app");
|
const run_step = b.step("run", "Run the app");
|
||||||
run_step.dependOn(&run_cmd.step);
|
run_step.dependOn(&run_cmd.step);
|
||||||
|
|
||||||
|
@ -79,9 +59,6 @@ pub fn build(b: *std.Build) void {
|
||||||
|
|
||||||
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
|
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
|
||||||
|
|
||||||
// Similar to creating the run step earlier, this exposes a `test` step to
|
|
||||||
// the `zig build --help` menu, providing a way for the user to request
|
|
||||||
// running the unit tests.
|
|
||||||
const test_step = b.step("test", "Run unit tests");
|
const test_step = b.step("test", "Run unit tests");
|
||||||
test_step.dependOn(&run_exe_unit_tests.step);
|
test_step.dependOn(&run_exe_unit_tests.step);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,8 @@
|
||||||
.{
|
.{
|
||||||
// This is the default name used by packages depending on this one. For
|
|
||||||
// example, when a user runs `zig fetch --save <url>`, this field is used
|
|
||||||
// as the key in the `dependencies` table. Although the user can choose a
|
|
||||||
// different name, most users will stick with this provided value.
|
|
||||||
//
|
|
||||||
// It is redundant to include "zig" in this name because it is already
|
|
||||||
// within the Zig package namespace.
|
|
||||||
.name = "vulkan-test",
|
.name = "vulkan-test",
|
||||||
|
|
||||||
// This is a [Semantic Version](https://semver.org/).
|
.version = "0.1.0",
|
||||||
// In a future version of Zig it will be used for package deduplication.
|
|
||||||
.version = "0.0.0",
|
|
||||||
|
|
||||||
// This field is optional.
|
|
||||||
// This is currently advisory only; Zig does not yet do anything
|
|
||||||
// with this value.
|
|
||||||
//.minimum_zig_version = "0.11.0",
|
|
||||||
|
|
||||||
// This field is optional.
|
|
||||||
// Each dependency must either provide a `url` and `hash`, or a `path`.
|
|
||||||
// `zig build --fetch` can be used to fetch all dependencies of a package, recursively.
|
|
||||||
// Once all dependencies are fetched, `zig build` no longer requires
|
|
||||||
// internet connectivity.
|
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.vulkan_zig = .{
|
.vulkan_zig = .{
|
||||||
.url = "https://github.com/Snektron/vulkan-zig/archive/f637a0d2525f62c7803c18c89a95cc2f8d8b2789.tar.gz",
|
.url = "https://github.com/Snektron/vulkan-zig/archive/f637a0d2525f62c7803c18c89a95cc2f8d8b2789.tar.gz",
|
||||||
|
@ -32,6 +13,7 @@
|
||||||
.hash = "1220821a34cc5fa538f4f5f96541322019e73104586e4f3fbafc614646e8e9bf64d0",
|
.hash = "1220821a34cc5fa538f4f5f96541322019e73104586e4f3fbafc614646e8e9bf64d0",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
.paths = .{
|
.paths = .{
|
||||||
"build.zig",
|
"build.zig",
|
||||||
"build.zig.zon",
|
"build.zig.zon",
|
||||||
|
|
94
src/Mesh.zig
Normal file
94
src/Mesh.zig
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const vk = @import("vulkan");
|
||||||
|
const Utilities = @import("utilities.zig");
|
||||||
|
const Vertex = Utilities.Vertex;
|
||||||
|
const Device = @import("vulkan_renderer.zig").Device;
|
||||||
|
const Instance = @import("vulkan_renderer.zig").Instance;
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
vertex_count: u32,
|
||||||
|
vertex_buffer: vk.Buffer,
|
||||||
|
vertex_buffer_memory: vk.DeviceMemory,
|
||||||
|
|
||||||
|
instance: Instance,
|
||||||
|
physical_device: vk.PhysicalDevice,
|
||||||
|
device: Device,
|
||||||
|
|
||||||
|
pub fn new(instance: Instance, pdev: vk.PhysicalDevice, device: Device, vertices: []const Vertex) !Self {
|
||||||
|
var mesh: Self = undefined;
|
||||||
|
|
||||||
|
mesh.vertex_count = @intCast(vertices.len);
|
||||||
|
mesh.instance = instance;
|
||||||
|
mesh.physical_device = pdev;
|
||||||
|
mesh.device = device;
|
||||||
|
try mesh.createVertexBuffer(vertices);
|
||||||
|
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn destroyVertexBuffer(self: Self) void {
|
||||||
|
self.device.destroyBuffer(self.vertex_buffer, null);
|
||||||
|
self.device.freeMemory(self.vertex_buffer_memory, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn createVertexBuffer(self: *Self, vertices: []const Vertex) !void {
|
||||||
|
// Create vertex buffer
|
||||||
|
// Information to create buffer (doesn't include assigning memory)
|
||||||
|
const buffer_create_info: vk.BufferCreateInfo = .{
|
||||||
|
.size = @sizeOf(Vertex) * vertices.len, // Size of buffer (size of 1 vertex * number of vertices)
|
||||||
|
.usage = .{ .vertex_buffer_bit = true }, // Multiple types of buffer possible, we want vertex buffer
|
||||||
|
.sharing_mode = .exclusive, // Similar to swapchain images, can share vertex buffers
|
||||||
|
};
|
||||||
|
|
||||||
|
self.vertex_buffer = try self.device.createBuffer(&buffer_create_info, null);
|
||||||
|
|
||||||
|
// Get buffer memory requirements
|
||||||
|
const mem_requirements = self.device.getBufferMemoryRequirements(self.vertex_buffer);
|
||||||
|
|
||||||
|
// Allocate memory to buffer
|
||||||
|
const allocate_info: vk.MemoryAllocateInfo = .{
|
||||||
|
.allocation_size = mem_requirements.size,
|
||||||
|
.memory_type_index = self.findMemoryTypeIndex(
|
||||||
|
mem_requirements.memory_type_bits, // Index of memory type of physical device that has required bit flags
|
||||||
|
.{
|
||||||
|
.host_visible_bit = true, // CPU can interact with memory
|
||||||
|
.host_coherent_bit = true, // Allows placement of data straight into buffer after mapping (otherwise would have to specify manually)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Allocate memory to vkDeviceMemory
|
||||||
|
self.vertex_buffer_memory = try self.device.allocateMemory(&allocate_info, null);
|
||||||
|
|
||||||
|
// Allocate memory to given vertex buffer
|
||||||
|
try self.device.bindBufferMemory(self.vertex_buffer, self.vertex_buffer_memory, 0);
|
||||||
|
|
||||||
|
// Map memory to vertex
|
||||||
|
// 1. Create pointer to a point in normal memory
|
||||||
|
// 2. Map the vertex buffer memory to that point
|
||||||
|
const data = try self.device.mapMemory(self.vertex_buffer_memory, 0, vk.WHOLE_SIZE, .{});
|
||||||
|
|
||||||
|
// 3. Copy memory from vertices vector to the point in memory
|
||||||
|
const gpu_vertices: [*]Vertex = @ptrCast(@alignCast(data));
|
||||||
|
@memcpy(gpu_vertices, vertices[0..]);
|
||||||
|
|
||||||
|
// 4. Unmap the vertex buffer memory
|
||||||
|
self.device.unmapMemory(self.vertex_buffer_memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn findMemoryTypeIndex(self: Self, allowed_types: u32, properties: vk.MemoryPropertyFlags) u32 {
|
||||||
|
// Get properties of physical device memory
|
||||||
|
const memory_properties = self.instance.getPhysicalDeviceMemoryProperties(self.physical_device);
|
||||||
|
const mem_type_count = memory_properties.memory_type_count;
|
||||||
|
|
||||||
|
for (memory_properties.memory_types[0..mem_type_count], 0..mem_type_count) |mem_type, i| {
|
||||||
|
// Index of memory type must match corresponding bit in allowed_types
|
||||||
|
if (allowed_types & (@as(u32, 1) << @truncate(i)) != 0 and mem_type.property_flags.contains(properties)) {
|
||||||
|
// Return the index of the valid memory type
|
||||||
|
return @truncate(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable;
|
||||||
|
}
|
|
@ -1,11 +1,8 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
// Interpolated colour from vertex (location must match)
|
|
||||||
layout(location = 0) in vec3 fragColour;
|
|
||||||
|
|
||||||
// Final output output (must also have location)
|
// Final output output (must also have location)
|
||||||
layout(location = 0) out vec4 outColour;
|
layout(location = 0) out vec4 outColour;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
outColour = vec4(fragColour, 1.0);
|
outColour = vec4(1.0, 0.0, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,8 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
// Output colour for vertex (location is required)
|
layout(location = 0) in vec3 pos;
|
||||||
layout(location = 0) out vec3 fragColour;
|
|
||||||
|
|
||||||
// Triangle vertex positions
|
|
||||||
vec3 positions[3] = vec3[](
|
|
||||||
vec3(0.0, -0.4, 0.0),
|
|
||||||
vec3(0.4, 0.4, 0.0),
|
|
||||||
vec3(-0.4, 0.4, 0.0)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Triangle vertex colours
|
|
||||||
vec3 colours[3] = vec3[](
|
|
||||||
vec3(1.0, 0.0, 0.0),
|
|
||||||
vec3(0.0, 1.0, 0.0),
|
|
||||||
vec3(0.0, 0.0, 1.0)
|
|
||||||
);
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = vec4(positions[gl_VertexIndex], 1.0);
|
gl_Position = vec4(pos, 1.0);
|
||||||
fragColour = colours[gl_VertexIndex];
|
// fragColour = colours[gl_VertexIndex];
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,12 @@ const vk = @import("vulkan");
|
||||||
|
|
||||||
pub const device_extensions = [_][*:0]const u8{vk.extensions.khr_swapchain.name};
|
pub const device_extensions = [_][*:0]const u8{vk.extensions.khr_swapchain.name};
|
||||||
|
|
||||||
|
// Vertex data representation
|
||||||
|
pub const Vertex = struct {
|
||||||
|
// Vertex position (x, y, z)
|
||||||
|
pos: @Vector(3, f32),
|
||||||
|
};
|
||||||
|
|
||||||
pub const QueueFamilyIndices = struct {
|
pub const QueueFamilyIndices = struct {
|
||||||
graphics_family: ?u32 = null,
|
graphics_family: ?u32 = null,
|
||||||
presentation_family: ?u32 = null,
|
presentation_family: ?u32 = null,
|
||||||
|
|
|
@ -8,6 +8,9 @@ const Utilities = @import("utilities.zig");
|
||||||
const QueueFamilyIndices = Utilities.QueueFamilyIndices;
|
const QueueFamilyIndices = Utilities.QueueFamilyIndices;
|
||||||
const SwapchainDetails = Utilities.SwapchainDetails;
|
const SwapchainDetails = Utilities.SwapchainDetails;
|
||||||
const SwapchainImage = Utilities.SwapchainImage;
|
const SwapchainImage = Utilities.SwapchainImage;
|
||||||
|
const Vertex = Utilities.Vertex;
|
||||||
|
|
||||||
|
const Mesh = @import("Mesh.zig");
|
||||||
|
|
||||||
const enable_validation_layers = builtin.mode == .Debug;
|
const enable_validation_layers = builtin.mode == .Debug;
|
||||||
const validation_layers = [_][*:0]const u8{"VK_LAYER_KHRONOS_validation"};
|
const validation_layers = [_][*:0]const u8{"VK_LAYER_KHRONOS_validation"};
|
||||||
|
@ -28,10 +31,10 @@ const BaseDispatch = vk.BaseWrapper(apis);
|
||||||
const InstanceDispatch = vk.InstanceWrapper(apis);
|
const InstanceDispatch = vk.InstanceWrapper(apis);
|
||||||
const DeviceDispatch = vk.DeviceWrapper(apis);
|
const DeviceDispatch = vk.DeviceWrapper(apis);
|
||||||
|
|
||||||
const Instance = vk.InstanceProxy(apis);
|
pub const Instance = vk.InstanceProxy(apis);
|
||||||
const Device = vk.DeviceProxy(apis);
|
pub const Device = vk.DeviceProxy(apis);
|
||||||
const Queue = vk.QueueProxy(apis);
|
pub const Queue = vk.QueueProxy(apis);
|
||||||
const CommandBuffer = vk.CommandBufferProxy(apis);
|
pub const CommandBuffer = vk.CommandBufferProxy(apis);
|
||||||
|
|
||||||
pub const VulkanRenderer = struct {
|
pub const VulkanRenderer = struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
@ -44,6 +47,9 @@ pub const VulkanRenderer = struct {
|
||||||
|
|
||||||
current_frame: u32 = 0,
|
current_frame: u32 = 0,
|
||||||
|
|
||||||
|
// Scene objects
|
||||||
|
first_mesh: Mesh,
|
||||||
|
|
||||||
// Main
|
// Main
|
||||||
instance: Instance,
|
instance: Instance,
|
||||||
physical_device: vk.PhysicalDevice,
|
physical_device: vk.PhysicalDevice,
|
||||||
|
@ -95,6 +101,16 @@ pub const VulkanRenderer = struct {
|
||||||
|
|
||||||
try self.getPhysicalDevice();
|
try self.getPhysicalDevice();
|
||||||
try self.createLogicalDevice();
|
try self.createLogicalDevice();
|
||||||
|
|
||||||
|
// Create mesh
|
||||||
|
var mesh_vertices = [_]Vertex{
|
||||||
|
.{ .pos = .{ 0.0, -0.4, 0.0 } },
|
||||||
|
.{ .pos = .{ 0.4, 0.4, 0.0 } },
|
||||||
|
.{ .pos = .{ -0.4, 0.4, 0.0 } },
|
||||||
|
};
|
||||||
|
|
||||||
|
self.first_mesh = try Mesh.new(self.instance, self.physical_device, self.device, &mesh_vertices);
|
||||||
|
|
||||||
try self.createSwapchain();
|
try self.createSwapchain();
|
||||||
try self.createRenderPass();
|
try self.createRenderPass();
|
||||||
try self.createGraphicsPipeline();
|
try self.createGraphicsPipeline();
|
||||||
|
@ -157,11 +173,13 @@ pub const VulkanRenderer = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Self) void {
|
pub fn deinit(self: *Self) void {
|
||||||
|
self.device.deviceWaitIdle() catch undefined;
|
||||||
|
|
||||||
if (enable_validation_layers) {
|
if (enable_validation_layers) {
|
||||||
self.instance.destroyDebugUtilsMessengerEXT(self.debug_utils.?, null);
|
self.instance.destroyDebugUtilsMessengerEXT(self.debug_utils.?, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.device.deviceWaitIdle() catch undefined;
|
self.first_mesh.destroyVertexBuffer();
|
||||||
|
|
||||||
for (0..MAX_FRAME_DRAWS) |i| {
|
for (0..MAX_FRAME_DRAWS) |i| {
|
||||||
self.device.destroySemaphore(self.render_finished[i], null);
|
self.device.destroySemaphore(self.render_finished[i], null);
|
||||||
|
@ -470,10 +488,32 @@ pub const VulkanRenderer = struct {
|
||||||
fragment_shader_create_info,
|
fragment_shader_create_info,
|
||||||
};
|
};
|
||||||
|
|
||||||
// -- Vertex input (TODO: Put in vertex descriptions when resources created) --
|
// How the data for a single vertex (including info such as position, colour, texture coords, normals, etc...) is as a whole
|
||||||
|
const binding_description: vk.VertexInputBindingDescription = .{
|
||||||
|
.binding = 0, // Can bind multiple streams of data, this defines which one
|
||||||
|
.stride = @sizeOf(Vertex), // Size of simple vertex object
|
||||||
|
.input_rate = .vertex, // How to move between data after each vertex
|
||||||
|
// vertex: move to the next vertex
|
||||||
|
// instance: move to a vertex for the next instance
|
||||||
|
};
|
||||||
|
|
||||||
|
// How the data for an attribute is defined within the vertex
|
||||||
|
const attribute_descriptions = [_]vk.VertexInputAttributeDescription{
|
||||||
|
// Position attribute
|
||||||
|
.{
|
||||||
|
.binding = 0, // Which binding the data is at (should be same as above)
|
||||||
|
.location = 0, // Location in shader where data will be read from
|
||||||
|
.format = vk.Format.r32g32b32_sfloat, // Format the data will take (also helps define size of data)
|
||||||
|
.offset = @offsetOf(Vertex, "pos"), // Where this attribute is defined in data for a single vertex
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// -- Vertex input --
|
||||||
const vertex_input_create_info: vk.PipelineVertexInputStateCreateInfo = .{
|
const vertex_input_create_info: vk.PipelineVertexInputStateCreateInfo = .{
|
||||||
.p_vertex_binding_descriptions = null, // List of vertex binding descriptions (data spacing, stride info)
|
.vertex_binding_description_count = 1,
|
||||||
.p_vertex_attribute_descriptions = null, // List of vertex attribute descriptions (data format and where to bind to/from)
|
.p_vertex_binding_descriptions = @ptrCast(&binding_description), // List of vertex binding descriptions (data spacing, stride info)
|
||||||
|
.vertex_attribute_description_count = @intCast(attribute_descriptions.len),
|
||||||
|
.p_vertex_attribute_descriptions = &attribute_descriptions, // List of vertex attribute descriptions (data format and where to bind to/from)
|
||||||
};
|
};
|
||||||
|
|
||||||
// -- Input assembly --
|
// -- Input assembly --
|
||||||
|
@ -697,15 +737,24 @@ pub const VulkanRenderer = struct {
|
||||||
// Begin render pass
|
// Begin render pass
|
||||||
command_buffer.beginRenderPass(&render_pass_begin_info, vk.SubpassContents.@"inline");
|
command_buffer.beginRenderPass(&render_pass_begin_info, vk.SubpassContents.@"inline");
|
||||||
|
|
||||||
|
{
|
||||||
// Bind pipeline to be used in render pass
|
// Bind pipeline to be used in render pass
|
||||||
command_buffer.bindPipeline(.graphics, self.graphics_pipeline);
|
command_buffer.bindPipeline(.graphics, self.graphics_pipeline);
|
||||||
|
|
||||||
|
// Buffers to bind
|
||||||
|
const vertex_buffers = [_]vk.Buffer{self.first_mesh.vertex_buffer};
|
||||||
|
// Offsets into buffers being bound
|
||||||
|
const offsets = [_]vk.DeviceSize{0};
|
||||||
|
// Command to bind vertex buffer before drawing with them
|
||||||
|
command_buffer.bindVertexBuffers(0, 1, &vertex_buffers, &offsets);
|
||||||
|
|
||||||
// Needed when using dynamic state
|
// Needed when using dynamic state
|
||||||
command_buffer.setViewport(0, 1, @ptrCast(&self.viewport));
|
command_buffer.setViewport(0, 1, @ptrCast(&self.viewport));
|
||||||
command_buffer.setScissor(0, 1, @ptrCast(&self.scissor));
|
command_buffer.setScissor(0, 1, @ptrCast(&self.scissor));
|
||||||
|
|
||||||
// Execute a pipeline
|
// Execute a pipeline
|
||||||
command_buffer.draw(3, 1, 0, 0);
|
command_buffer.draw(self.first_mesh.vertex_count, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// End render pass
|
// End render pass
|
||||||
command_buffer.endRenderPass();
|
command_buffer.endRenderPass();
|
||||||
|
|
Loading…
Reference in a new issue