Render square from vertex buffer
This commit is contained in:
parent
0e348fe0a0
commit
b36f5b0b84
@ -1,11 +1,7 @@
|
||||
#version 450
|
||||
|
||||
vec2 positions[3] = vec2[](
|
||||
vec2(0.0, -0.5),
|
||||
vec2(0.5, 0.5),
|
||||
vec2(-0.5, 0.5)
|
||||
);
|
||||
layout(location=0) in vec2 in_position;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
|
||||
gl_Position = vec4(in_position, 0.0, 1.0);
|
||||
}
|
||||
|
||||
12
src/geometry.zig
Normal file
12
src/geometry.zig
Normal file
@ -0,0 +1,12 @@
|
||||
pub const Vertex = extern struct {
|
||||
position: [2]f32,
|
||||
};
|
||||
|
||||
const square_vertices = [_]Vertex{
|
||||
.{ .position = .{ -0.5, -0.5 } },
|
||||
.{ .position = .{ 0.5, -0.5 } },
|
||||
.{ .position = .{ 0.5, 0.5 } },
|
||||
.{ .position = .{ -0.5, -0.5 } },
|
||||
.{ .position = .{ 0.5, 0.5 } },
|
||||
.{ .position = .{ -0.5, 0.5 } },
|
||||
};
|
||||
33
src/main.zig
33
src/main.zig
@ -12,6 +12,8 @@ const render_pass_mod = @import("vulkan/render_pass.zig");
|
||||
const swapchain_mod = @import("vulkan/swapchain.zig");
|
||||
const sync_mod = @import("vulkan/sync.zig");
|
||||
const pipeline_mod = @import("vulkan/pipeline.zig");
|
||||
const geometry = @import("geometry.zig");
|
||||
const buffer_mod = @import("vulkan/buffer.zig");
|
||||
|
||||
// The build script compiles these GLSL files to SPIR-V and exposes them as
|
||||
// anonymous imports. They are currently only loaded and printed; the program
|
||||
@ -97,12 +99,29 @@ pub fn main() !void {
|
||||
);
|
||||
defer framebuffer_context.destroy(&ldc);
|
||||
|
||||
const square_vertices = [_]geometry.Vertex{
|
||||
.{ .position = .{ -0.5, -0.5 } },
|
||||
.{ .position = .{ 0.5, -0.5 } },
|
||||
.{ .position = .{ 0.5, 0.5 } },
|
||||
.{ .position = .{ -0.5, -0.5 } },
|
||||
.{ .position = .{ 0.5, 0.5 } },
|
||||
.{ .position = .{ -0.5, 0.5 } },
|
||||
};
|
||||
|
||||
var vertex_buffer_context = try buffer_mod.initVertexBuffer(
|
||||
vc,
|
||||
ldc,
|
||||
&square_vertices,
|
||||
);
|
||||
defer vertex_buffer_context.destroy(&ldc);
|
||||
|
||||
var command_context = try commands_mod.initCommandBuffers(
|
||||
ldc,
|
||||
render_pass_context,
|
||||
framebuffer_context,
|
||||
pipeline_context,
|
||||
swapchain_context,
|
||||
vertex_buffer_context,
|
||||
std.heap.page_allocator,
|
||||
);
|
||||
defer command_context.destroy(&ldc);
|
||||
@ -129,7 +148,9 @@ pub fn main() !void {
|
||||
&render_pass_context,
|
||||
&framebuffer_context,
|
||||
&pipeline_context,
|
||||
&vertex_buffer_context,
|
||||
&command_context,
|
||||
&square_vertices,
|
||||
std.heap.page_allocator,
|
||||
);
|
||||
}
|
||||
@ -147,7 +168,9 @@ fn recreateSwapchain(
|
||||
render_pass_context: *render_pass_mod.RenderPassContext,
|
||||
framebuffer_context: *framebuffers_mod.FramebufferContext,
|
||||
pipeline_context: *pipeline_mod.PipelineContext,
|
||||
vertex_buffer_context: *buffer_mod.VertexBufferContext,
|
||||
command_context: *commands_mod.CommandContext,
|
||||
vertices: []const geometry.Vertex,
|
||||
allocator: std.mem.Allocator,
|
||||
) !void {
|
||||
// A minimized window can report a zero-sized framebuffer. Vulkan swapchain
|
||||
@ -178,8 +201,11 @@ fn recreateSwapchain(
|
||||
const new_render_pass_context = try render_pass_mod.initRenderPass(ldc, new_swapchain_context.format.format);
|
||||
errdefer new_render_pass_context.destroy(&ldc);
|
||||
|
||||
const new_pipeline_context = try pipeline_mod.initPipelineContext(ldc, swapchain_context.extent, render_pass_context.render_pass, square_vert_spv, square_frag_spv, std.heap.page_allocator);
|
||||
errdefer pipeline_context.destroy(&ldc);
|
||||
const new_pipeline_context = try pipeline_mod.initPipelineContext(ldc, new_swapchain_context.extent, new_render_pass_context.render_pass, square_vert_spv, square_frag_spv, allocator);
|
||||
errdefer new_pipeline_context.destroy(&ldc);
|
||||
|
||||
const new_vertex_buffer_context = try buffer_mod.initVertexBuffer(vc, ldc, vertices);
|
||||
errdefer new_vertex_buffer_context.destroy(&ldc);
|
||||
|
||||
const new_framebuffer_context = try framebuffers_mod.initFramebuffers(
|
||||
ldc,
|
||||
@ -195,6 +221,7 @@ fn recreateSwapchain(
|
||||
new_framebuffer_context,
|
||||
new_pipeline_context,
|
||||
new_swapchain_context,
|
||||
new_vertex_buffer_context,
|
||||
allocator,
|
||||
);
|
||||
errdefer new_command_context.destroy(&ldc);
|
||||
@ -203,6 +230,7 @@ fn recreateSwapchain(
|
||||
// dependency order: command buffers/pool -> framebuffers -> render pass ->
|
||||
// swapchain/image views/images.
|
||||
command_context.destroy(&ldc);
|
||||
vertex_buffer_context.destroy(&ldc);
|
||||
framebuffer_context.destroy(&ldc);
|
||||
pipeline_context.destroy(&ldc);
|
||||
render_pass_context.destroy(&ldc);
|
||||
@ -211,6 +239,7 @@ fn recreateSwapchain(
|
||||
swapchain_context.* = new_swapchain_context;
|
||||
render_pass_context.* = new_render_pass_context;
|
||||
pipeline_context.* = new_pipeline_context;
|
||||
vertex_buffer_context.* = new_vertex_buffer_context;
|
||||
framebuffer_context.* = new_framebuffer_context;
|
||||
command_context.* = new_command_context;
|
||||
|
||||
|
||||
109
src/vulkan/buffer.zig
Normal file
109
src/vulkan/buffer.zig
Normal file
@ -0,0 +1,109 @@
|
||||
const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const geometry = @import("../geometry.zig");
|
||||
const context = @import("context.zig");
|
||||
const device = @import("device.zig");
|
||||
|
||||
pub const VertexBufferContext = struct {
|
||||
buffer: vk.Buffer,
|
||||
memory: vk.DeviceMemory,
|
||||
vertex_count: u32,
|
||||
|
||||
pub fn destroy(self: *const VertexBufferContext, ldc: *const device.LogicalDeviceContext) void {
|
||||
ldc.vkd.destroyBuffer(ldc.device, self.buffer, null);
|
||||
ldc.vkd.freeMemory(ldc.device, self.memory, null);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn initVertexBuffer(
|
||||
vc: context.VulkanContext,
|
||||
ldc: device.LogicalDeviceContext,
|
||||
vertices: []const geometry.Vertex,
|
||||
) !VertexBufferContext {
|
||||
const buffer_size: vk.DeviceSize = @intCast(@sizeOf(geometry.Vertex) * vertices.len);
|
||||
|
||||
const buffer_create_info = vk.BufferCreateInfo{
|
||||
.size = buffer_size,
|
||||
.usage = .{
|
||||
.vertex_buffer_bit = true,
|
||||
},
|
||||
.sharing_mode = .exclusive,
|
||||
};
|
||||
|
||||
const buffer = try ldc.vkd.createBuffer(ldc.device, &buffer_create_info, null);
|
||||
errdefer ldc.vkd.destroyBuffer(ldc.device, buffer, null);
|
||||
|
||||
const memory_requirements = ldc.vkd.getBufferMemoryRequirements(
|
||||
ldc.device,
|
||||
buffer,
|
||||
);
|
||||
const memory_index = try findMemoryType(
|
||||
vc,
|
||||
ldc,
|
||||
memory_requirements.memory_type_bits,
|
||||
.{
|
||||
.host_visible_bit = true,
|
||||
.host_coherent_bit = true,
|
||||
},
|
||||
);
|
||||
|
||||
const alloc_info = vk.MemoryAllocateInfo{
|
||||
.allocation_size = memory_requirements.size,
|
||||
.memory_type_index = memory_index,
|
||||
};
|
||||
|
||||
const memory = try ldc.vkd.allocateMemory(ldc.device, &alloc_info, null);
|
||||
errdefer ldc.vkd.freeMemory(ldc.device, memory, null);
|
||||
|
||||
try ldc.vkd.bindBufferMemory(ldc.device, buffer, memory, 0);
|
||||
|
||||
const mapped = try ldc.vkd.mapMemory(
|
||||
ldc.device,
|
||||
memory,
|
||||
0,
|
||||
buffer_size,
|
||||
.{},
|
||||
);
|
||||
defer ldc.vkd.unmapMemory(ldc.device, memory);
|
||||
|
||||
const dst: [*]u8 = @ptrCast(mapped);
|
||||
const dst_slice = dst[0..buffer_size];
|
||||
|
||||
const src_bytes = std.mem.sliceAsBytes(vertices);
|
||||
std.mem.copyForwards(u8, dst_slice, src_bytes);
|
||||
|
||||
return .{
|
||||
.buffer = buffer,
|
||||
.memory = memory,
|
||||
.vertex_count = @intCast(vertices.len),
|
||||
};
|
||||
}
|
||||
|
||||
fn findMemoryType(
|
||||
vc: context.VulkanContext,
|
||||
ldc: device.LogicalDeviceContext,
|
||||
type_filter: u32,
|
||||
properties: vk.MemoryPropertyFlags,
|
||||
) !u32 {
|
||||
const memory_properties = vc.vki.getPhysicalDeviceMemoryProperties(ldc.physical_device);
|
||||
|
||||
var i: u5 = 0;
|
||||
while (i < memory_properties.memory_type_count) : (i += 1) {
|
||||
const type_supported = (type_filter & (@as(u32, 1) << i)) != 0;
|
||||
const flags = memory_properties.memory_types[i].property_flags;
|
||||
|
||||
const has_properties =
|
||||
(!properties.device_local_bit or flags.device_local_bit) and
|
||||
(!properties.host_visible_bit or flags.host_visible_bit) and
|
||||
(!properties.host_coherent_bit or flags.host_coherent_bit) and
|
||||
(!properties.host_cached_bit or flags.host_cached_bit) and
|
||||
(!properties.lazily_allocated_bit or flags.lazily_allocated_bit);
|
||||
|
||||
if (type_supported and has_properties) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return error.NoSuitableMemoryType;
|
||||
}
|
||||
@ -6,6 +6,7 @@ const framebuffers = @import("framebuffers.zig");
|
||||
const render_pass = @import("render_pass.zig");
|
||||
const swapchain = @import("swapchain.zig");
|
||||
const pipeline = @import("pipeline.zig");
|
||||
const buffer = @import("buffer.zig");
|
||||
|
||||
pub const CommandContext = struct {
|
||||
command_pool: vk.CommandPool,
|
||||
@ -24,6 +25,7 @@ pub fn initCommandBuffers(
|
||||
framebuffer_context: framebuffers.FramebufferContext,
|
||||
pipeline_context: pipeline.PipelineContext,
|
||||
swapchain_context: swapchain.SwapchainContext,
|
||||
vertex_buffer_context: buffer.VertexBufferContext,
|
||||
allocator: std.mem.Allocator,
|
||||
) !CommandContext {
|
||||
const command_pool_create_info = vk.CommandPoolCreateInfo{
|
||||
@ -94,7 +96,22 @@ pub fn initCommandBuffers(
|
||||
pipeline_context.graphics_pipeline,
|
||||
);
|
||||
|
||||
ldc.vkd.cmdDraw(command_buffer, 3, 1, 0, 0);
|
||||
const vertex_buffers = [_]vk.Buffer{
|
||||
vertex_buffer_context.buffer,
|
||||
};
|
||||
|
||||
const offsets = [_]vk.DeviceSize{
|
||||
0,
|
||||
};
|
||||
|
||||
ldc.vkd.cmdBindVertexBuffers(
|
||||
command_buffer,
|
||||
0,
|
||||
&vertex_buffers,
|
||||
&offsets,
|
||||
);
|
||||
|
||||
ldc.vkd.cmdDraw(command_buffer, vertex_buffer_context.vertex_count, 1, 0, 0);
|
||||
|
||||
ldc.vkd.cmdEndRenderPass(command_buffer);
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const device = @import("device.zig");
|
||||
const geometry = @import("../geometry.zig");
|
||||
|
||||
pub const PipelineContext = struct {
|
||||
graphics_pipeline: vk.Pipeline,
|
||||
@ -63,11 +64,24 @@ pub fn initPipelineContext(ldc: device.LogicalDeviceContext, extent: vk.Extent2D
|
||||
frag_shader_stage_info,
|
||||
};
|
||||
|
||||
const binding_description = vk.VertexInputBindingDescription{
|
||||
.binding = 0,
|
||||
.stride = @sizeOf(geometry.Vertex),
|
||||
.input_rate = .vertex,
|
||||
};
|
||||
|
||||
const attribute_description = vk.VertexInputAttributeDescription{
|
||||
.location = 0,
|
||||
.binding = 0,
|
||||
.format = .r32g32_sfloat,
|
||||
.offset = @offsetOf(geometry.Vertex, "position"),
|
||||
};
|
||||
|
||||
const vertex_input_info = vk.PipelineVertexInputStateCreateInfo{
|
||||
.vertex_binding_description_count = 0,
|
||||
.p_vertex_binding_descriptions = null,
|
||||
.vertex_attribute_description_count = 0,
|
||||
.p_vertex_attribute_descriptions = null,
|
||||
.vertex_binding_description_count = 1,
|
||||
.p_vertex_binding_descriptions = @ptrCast(&binding_description),
|
||||
.vertex_attribute_description_count = 1,
|
||||
.p_vertex_attribute_descriptions = @ptrCast(&attribute_description),
|
||||
};
|
||||
|
||||
const input_assembly = vk.PipelineInputAssemblyStateCreateInfo{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user