forked from mirror/vulkan-zig
Pipeline(Layout) & render pass creation
This commit is contained in:
@@ -15,7 +15,7 @@ pub const ResourceGenStep = struct {
|
|||||||
const self = builder.allocator.create(ResourceGenStep) catch unreachable;
|
const self = builder.allocator.create(ResourceGenStep) catch unreachable;
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.step = Step.init(.Custom, "resources", builder.allocator, make),
|
.step = Step.init(.Custom, "resources", builder.allocator, make),
|
||||||
.shader_step = vkgen.ShaderCompileStep.init(builder, "glslc"),
|
.shader_step = vkgen.ShaderCompileStep.init(builder, &[_][]const u8{"glslc", "--target-env=vulkan1.2"}),
|
||||||
.builder = builder,
|
.builder = builder,
|
||||||
.full_out_path = path.join(builder.allocator, &[_][]const u8{
|
.full_out_path = path.join(builder.allocator, &[_][]const u8{
|
||||||
self.builder.build_root,
|
self.builder.build_root,
|
||||||
@@ -32,7 +32,7 @@ pub const ResourceGenStep = struct {
|
|||||||
pub fn addShader(self: *ResourceGenStep, name: []const u8, source: []const u8) void {
|
pub fn addShader(self: *ResourceGenStep, name: []const u8, source: []const u8) void {
|
||||||
self.resources.writer().print(
|
self.resources.writer().print(
|
||||||
"pub const {} = @embedFile(\"{}\");\n",
|
"pub const {} = @embedFile(\"{}\");\n",
|
||||||
.{name, self.shader_step.add("examples/shaders/test.frag")}
|
.{name, self.shader_step.add(source)}
|
||||||
) catch unreachable;
|
) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +64,8 @@ pub fn build(b: *Builder) void {
|
|||||||
example_exe.addPackagePath("vulkan", gen.full_out_path);
|
example_exe.addPackagePath("vulkan", gen.full_out_path);
|
||||||
|
|
||||||
const res = ResourceGenStep.init(b, "resources.zig");
|
const res = ResourceGenStep.init(b, "resources.zig");
|
||||||
res.addShader("test_frag", "examples/shaders/test.frag");
|
res.addShader("triangle_vert", "examples/shaders/triangle.vert");
|
||||||
|
res.addShader("triangle_frag", "examples/shaders/triangle.frag");
|
||||||
example_exe.step.dependOn(&res.step);
|
example_exe.step.dependOn(&res.step);
|
||||||
example_exe.addPackagePath("resources", res.full_out_path);
|
example_exe.addPackagePath("resources", res.full_out_path);
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,14 @@ const DeviceDispatch = struct {
|
|||||||
vkEndCommandBuffer: vk.PfnEndCommandBuffer,
|
vkEndCommandBuffer: vk.PfnEndCommandBuffer,
|
||||||
vkQueueWaitIdle: vk.PfnQueueWaitIdle,
|
vkQueueWaitIdle: vk.PfnQueueWaitIdle,
|
||||||
vkCmdPipelineBarrier: vk.PfnCmdPipelineBarrier,
|
vkCmdPipelineBarrier: vk.PfnCmdPipelineBarrier,
|
||||||
|
vkCreateShaderModule: vk.PfnCreateShaderModule,
|
||||||
|
vkDestroyShaderModule: vk.PfnDestroyShaderModule,
|
||||||
|
vkCreatePipelineLayout: vk.PfnCreatePipelineLayout,
|
||||||
|
vkDestroyPipelineLayout: vk.PfnDestroyPipelineLayout,
|
||||||
|
vkCreateRenderPass: vk.PfnCreateRenderPass,
|
||||||
|
vkDestroyRenderPass: vk.PfnDestroyRenderPass,
|
||||||
|
vkCreateGraphicsPipelines: vk.PfnCreateGraphicsPipelines,
|
||||||
|
vkDestroyPipeline: vk.PfnDestroyPipeline,
|
||||||
usingnamespace vk.DeviceWrapper(@This());
|
usingnamespace vk.DeviceWrapper(@This());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ pub fn main() !void {
|
|||||||
if (c.glfwInit() != c.GLFW_TRUE) return error.GlfwInitFailed;
|
if (c.glfwInit() != c.GLFW_TRUE) return error.GlfwInitFailed;
|
||||||
defer c.glfwTerminate();
|
defer c.glfwTerminate();
|
||||||
|
|
||||||
const extent = vk.Extent2D{.width = 800, .height = 600};
|
var extent = vk.Extent2D{.width = 800, .height = 600};
|
||||||
|
|
||||||
c.glfwWindowHint(c.GLFW_CLIENT_API, c.GLFW_NO_API);
|
c.glfwWindowHint(c.GLFW_CLIENT_API, c.GLFW_NO_API);
|
||||||
const window = c.glfwCreateWindow(
|
const window = c.glfwCreateWindow(
|
||||||
extent.width,
|
@intCast(c_int, extent.width),
|
||||||
extent.height,
|
@intCast(c_int, extent.height),
|
||||||
app_name,
|
app_name,
|
||||||
null,
|
null,
|
||||||
null
|
null
|
||||||
@@ -34,6 +34,21 @@ pub fn main() !void {
|
|||||||
var swapchain = try Swapchain.init(&gc, allocator, extent);
|
var swapchain = try Swapchain.init(&gc, allocator, extent);
|
||||||
defer swapchain.deinit();
|
defer swapchain.deinit();
|
||||||
|
|
||||||
|
const pipeline_layout = try gc.vkd.createPipelineLayout(gc.dev, .{
|
||||||
|
.flags = .{},
|
||||||
|
.set_layout_count = 0,
|
||||||
|
.p_set_layouts = undefined,
|
||||||
|
.push_constant_range_count = 0,
|
||||||
|
.p_push_constant_ranges = undefined,
|
||||||
|
}, null);
|
||||||
|
defer gc.vkd.destroyPipelineLayout(gc.dev, pipeline_layout, null);
|
||||||
|
|
||||||
|
const render_pass = try createRenderPass(&gc, &swapchain);
|
||||||
|
defer gc.vkd.destroyRenderPass(gc.dev, render_pass, null);
|
||||||
|
|
||||||
|
const pipeline = try createPipeline(&gc, extent, pipeline_layout, render_pass);
|
||||||
|
defer gc.vkd.destroyPipeline(gc.dev, pipeline, null);
|
||||||
|
|
||||||
const pool = try gc.vkd.createCommandPool(gc.dev, .{
|
const pool = try gc.vkd.createCommandPool(gc.dev, .{
|
||||||
.flags = .{},
|
.flags = .{},
|
||||||
.queue_family_index = gc.graphics_queue.family,
|
.queue_family_index = gc.graphics_queue.family,
|
||||||
@@ -55,8 +70,9 @@ pub fn main() !void {
|
|||||||
var w: c_int = undefined;
|
var w: c_int = undefined;
|
||||||
var h: c_int = undefined;
|
var h: c_int = undefined;
|
||||||
c.glfwGetWindowSize(window, &w, &h);
|
c.glfwGetWindowSize(window, &w, &h);
|
||||||
|
extent.width = @intCast(u32, w);
|
||||||
try swapchain.recreate(.{.width = @intCast(u32, w), .height = @intCast(u32, h)});
|
extent.height = @intCast(u32, h);
|
||||||
|
try swapchain.recreate(extent);
|
||||||
|
|
||||||
destroyCommandBuffers(&gc, pool, allocator, cmdbufs);
|
destroyCommandBuffers(&gc, pool, allocator, cmdbufs);
|
||||||
cmdbufs = try createCommandBuffers(&gc, pool, allocator, swapchain);
|
cmdbufs = try createCommandBuffers(&gc, pool, allocator, swapchain);
|
||||||
@@ -141,6 +157,203 @@ fn destroyCommandBuffers(gc: *const GraphicsContext, pool: vk.CommandPool, alloc
|
|||||||
allocator.free(cmdbufs);
|
allocator.free(cmdbufs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn createRenderPass(gc: *const GraphicsContext, swapchain: *const Swapchain) !vk.RenderPass {
|
||||||
|
const color_attachment = vk.AttachmentDescription{
|
||||||
|
.flags = .{},
|
||||||
|
.format = swapchain.surface_format.format,
|
||||||
|
.samples = .{.@"1_bit" = true},
|
||||||
|
.load_op = .clear,
|
||||||
|
.store_op = .store,
|
||||||
|
.stencil_load_op = .dont_care,
|
||||||
|
.stencil_store_op = .dont_care,
|
||||||
|
.initial_layout = .@"undefined",
|
||||||
|
.final_layout = .present_src_khr,
|
||||||
|
};
|
||||||
|
|
||||||
|
const color_attachment_ref = vk.AttachmentReference{
|
||||||
|
.attachment = 0,
|
||||||
|
.layout = .color_attachment_optimal,
|
||||||
|
};
|
||||||
|
|
||||||
|
const subpass = vk.SubpassDescription{
|
||||||
|
.flags = .{},
|
||||||
|
.pipeline_bind_point = .graphics,
|
||||||
|
.input_attachment_count = 0,
|
||||||
|
.p_input_attachments = undefined,
|
||||||
|
.color_attachment_count = 1,
|
||||||
|
.p_color_attachments = @ptrCast([*]const vk.AttachmentReference, &color_attachment_ref),
|
||||||
|
.p_resolve_attachments = null,
|
||||||
|
.p_depth_stencil_attachment = null,
|
||||||
|
.preserve_attachment_count = 0,
|
||||||
|
.p_preserve_attachments = undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
return try gc.vkd.createRenderPass(gc.dev, .{
|
||||||
|
.flags = .{},
|
||||||
|
.attachment_count = 1,
|
||||||
|
.p_attachments = @ptrCast([*]const vk.AttachmentDescription, &color_attachment),
|
||||||
|
.subpass_count = 1,
|
||||||
|
.p_subpasses = @ptrCast([*]const vk.SubpassDescription, &subpass),
|
||||||
|
.dependency_count = 0,
|
||||||
|
.p_dependencies = undefined,
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn createPipeline(
|
||||||
|
gc: *const GraphicsContext,
|
||||||
|
extent: vk.Extent2D,
|
||||||
|
layout: vk.PipelineLayout,
|
||||||
|
render_pass: vk.RenderPass,
|
||||||
|
) !vk.Pipeline {
|
||||||
|
const vert = try gc.vkd.createShaderModule(gc.dev, .{
|
||||||
|
.flags = .{},
|
||||||
|
.code_size = resources.triangle_vert.len,
|
||||||
|
.p_code = @ptrCast([*]const u32, resources.triangle_vert),
|
||||||
|
}, null);
|
||||||
|
defer gc.vkd.destroyShaderModule(gc.dev, vert, null);
|
||||||
|
|
||||||
|
const frag = try gc.vkd.createShaderModule(gc.dev, .{
|
||||||
|
.flags = .{},
|
||||||
|
.code_size = resources.triangle_frag.len,
|
||||||
|
.p_code = @ptrCast([*]const u32, resources.triangle_frag),
|
||||||
|
}, null);
|
||||||
|
defer gc.vkd.destroyShaderModule(gc.dev, frag, null);
|
||||||
|
|
||||||
|
const pssci = [_]vk.PipelineShaderStageCreateInfo{
|
||||||
|
.{
|
||||||
|
.flags = .{},
|
||||||
|
.stage = .{.vertex_bit = true},
|
||||||
|
.module = vert,
|
||||||
|
.p_name = "main",
|
||||||
|
.p_specialization_info = null,
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.flags = .{},
|
||||||
|
.stage = .{.fragment_bit = true},
|
||||||
|
.module = frag,
|
||||||
|
.p_name = "main",
|
||||||
|
.p_specialization_info = null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const pvisci = vk.PipelineVertexInputStateCreateInfo{
|
||||||
|
.flags = .{},
|
||||||
|
.vertex_binding_description_count = 0,
|
||||||
|
.p_vertex_binding_descriptions = undefined,
|
||||||
|
.vertex_attribute_description_count = 0,
|
||||||
|
.p_vertex_attribute_descriptions = undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
const piasci = vk.PipelineInputAssemblyStateCreateInfo{
|
||||||
|
.flags = .{},
|
||||||
|
.topology = .triangle_list,
|
||||||
|
.primitive_restart_enable = vk.FALSE,
|
||||||
|
};
|
||||||
|
|
||||||
|
const viewport = vk.Viewport{
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
.width = @intToFloat(f32, extent.width),
|
||||||
|
.height = @intToFloat(f32, extent.height),
|
||||||
|
.min_depth = 0,
|
||||||
|
.max_depth = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const scissor = vk.Rect2D{
|
||||||
|
.offset = .{.x = 0, .y = 0},
|
||||||
|
.extent = extent,
|
||||||
|
};
|
||||||
|
|
||||||
|
const pvsci = vk.PipelineViewportStateCreateInfo{
|
||||||
|
.flags = .{},
|
||||||
|
.viewport_count = 1,
|
||||||
|
.p_viewports = @ptrCast([*]const vk.Viewport, &viewport),
|
||||||
|
.scissor_count = 1,
|
||||||
|
.p_scissors = @ptrCast([*]const vk.Rect2D, &scissor),
|
||||||
|
};
|
||||||
|
|
||||||
|
const prsci = vk.PipelineRasterizationStateCreateInfo{
|
||||||
|
.flags = .{},
|
||||||
|
.depth_clamp_enable = vk.FALSE,
|
||||||
|
.rasterizer_discard_enable = vk.FALSE,
|
||||||
|
.polygon_mode = .fill,
|
||||||
|
.cull_mode = .{.back_bit = true},
|
||||||
|
.front_face = .clockwise,
|
||||||
|
.depth_bias_enable = vk.FALSE,
|
||||||
|
.depth_bias_constant_factor = 0,
|
||||||
|
.depth_bias_clamp = 0,
|
||||||
|
.depth_bias_slope_factor = 0,
|
||||||
|
.line_width = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const pmsci = vk.PipelineMultisampleStateCreateInfo{
|
||||||
|
.flags = .{},
|
||||||
|
.rasterization_samples = .{.@"1_bit" = true},
|
||||||
|
.sample_shading_enable = vk.FALSE,
|
||||||
|
.min_sample_shading = 1,
|
||||||
|
.p_sample_mask = null,
|
||||||
|
.alpha_to_coverage_enable = vk.FALSE,
|
||||||
|
.alpha_to_one_enable = vk.FALSE,
|
||||||
|
};
|
||||||
|
|
||||||
|
const pcbas = vk.PipelineColorBlendAttachmentState{
|
||||||
|
.blend_enable = vk.FALSE,
|
||||||
|
.src_color_blend_factor = .one,
|
||||||
|
.dst_color_blend_factor = .zero,
|
||||||
|
.color_blend_op = .add,
|
||||||
|
.src_alpha_blend_factor = .one,
|
||||||
|
.dst_alpha_blend_factor = .zero,
|
||||||
|
.alpha_blend_op = .add,
|
||||||
|
.color_write_mask = .{.r_bit = true, .g_bit = true, .b_bit = true, .a_bit = true},
|
||||||
|
};
|
||||||
|
|
||||||
|
const pcbsci = vk.PipelineColorBlendStateCreateInfo{
|
||||||
|
.flags = .{},
|
||||||
|
.logic_op_enable = vk.FALSE,
|
||||||
|
.logic_op = .copy,
|
||||||
|
.attachment_count = 1,
|
||||||
|
.p_attachments = @ptrCast([*]const vk.PipelineColorBlendAttachmentState, &pcbas),
|
||||||
|
.blend_constants = [_]f32{0, 0, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
const dynstate = vk.DynamicState.viewport;
|
||||||
|
const pdsci = vk.PipelineDynamicStateCreateInfo{
|
||||||
|
.flags = .{},
|
||||||
|
.dynamic_state_count = 1,
|
||||||
|
.p_dynamic_states = @ptrCast([*]const vk.DynamicState, &dynstate),
|
||||||
|
};
|
||||||
|
|
||||||
|
const gpci = vk.GraphicsPipelineCreateInfo{
|
||||||
|
.flags = .{},
|
||||||
|
.stage_count = 2,
|
||||||
|
.p_stages = &pssci,
|
||||||
|
.p_vertex_input_state = &pvisci,
|
||||||
|
.p_input_assembly_state = &piasci,
|
||||||
|
.p_tessellation_state = null,
|
||||||
|
.p_viewport_state = &pvsci,
|
||||||
|
.p_rasterization_state = &prsci,
|
||||||
|
.p_multisample_state = &pmsci,
|
||||||
|
.p_depth_stencil_state = null,
|
||||||
|
.p_color_blend_state = &pcbsci,
|
||||||
|
.p_dynamic_state = &pdsci,
|
||||||
|
.layout = layout,
|
||||||
|
.render_pass = render_pass,
|
||||||
|
.subpass = 0,
|
||||||
|
.base_pipeline_handle = .null_handle,
|
||||||
|
.base_pipeline_index = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
var pipeline: vk.Pipeline = undefined;
|
||||||
|
_ = try gc.vkd.createGraphicsPipelines(
|
||||||
|
gc.dev,
|
||||||
|
.null_handle,
|
||||||
|
1, @ptrCast([*]const vk.GraphicsPipelineCreateInfo, &gpci),
|
||||||
|
null,
|
||||||
|
@ptrCast([*]vk.Pipeline, &pipeline),
|
||||||
|
);
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
const ImageState = struct {
|
const ImageState = struct {
|
||||||
layout: vk.ImageLayout,
|
layout: vk.ImageLayout,
|
||||||
stage: vk.PipelineStageFlags,
|
stage: vk.PipelineStageFlags,
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
#version 450
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 f_color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
f_color = vec4(1.0, 0.0, 0.0, 1.0);
|
|
||||||
}
|
|
||||||
9
examples/shaders/triangle.frag
Normal file
9
examples/shaders/triangle.frag
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 v_color;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 f_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
f_color = vec4(v_color, 1.0);
|
||||||
|
}
|
||||||
20
examples/shaders/triangle.vert
Normal file
20
examples/shaders/triangle.vert
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
const vec2 positions[3] = vec2[](
|
||||||
|
vec2(0.0, -0.5),
|
||||||
|
vec2(0.5, 0.5),
|
||||||
|
vec2(-0.5, 0.5)
|
||||||
|
);
|
||||||
|
|
||||||
|
const vec3 colors[3] = vec3[](
|
||||||
|
vec3(1.0, 0.0, 0.0),
|
||||||
|
vec3(0.0, 1.0, 0.0),
|
||||||
|
vec3(0.0, 0.0, 1.0)
|
||||||
|
);
|
||||||
|
|
||||||
|
layout(location = 0) out vec3 v_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
|
||||||
|
v_color = colors[gl_VertexIndex];
|
||||||
|
}
|
||||||
@@ -11,15 +11,15 @@ pub const ShaderCompileStep = struct {
|
|||||||
|
|
||||||
step: Step,
|
step: Step,
|
||||||
builder: *Builder,
|
builder: *Builder,
|
||||||
glslc_path: []const u8,
|
glslc_cmd: []const []const u8,
|
||||||
shaders: std.ArrayList(Shader),
|
shaders: std.ArrayList(Shader),
|
||||||
|
|
||||||
pub fn init(builder: *Builder, glslc_path: []const u8) *ShaderCompileStep {
|
pub fn init(builder: *Builder, glslc_cmd: []const []const u8) *ShaderCompileStep {
|
||||||
const self = builder.allocator.create(ShaderCompileStep) catch unreachable;
|
const self = builder.allocator.create(ShaderCompileStep) catch unreachable;
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.step = Step.init(.Custom, "shader-compile", builder.allocator, make),
|
.step = Step.init(.Custom, "shader-compile", builder.allocator, make),
|
||||||
.builder = builder,
|
.builder = builder,
|
||||||
.glslc_path = glslc_path,
|
.glslc_cmd = glslc_cmd,
|
||||||
.shaders = std.ArrayList(Shader).init(builder.allocator),
|
.shaders = std.ArrayList(Shader).init(builder.allocator),
|
||||||
};
|
};
|
||||||
return self;
|
return self;
|
||||||
@@ -40,15 +40,18 @@ pub const ShaderCompileStep = struct {
|
|||||||
const self = @fieldParentPtr(ShaderCompileStep, "step", step);
|
const self = @fieldParentPtr(ShaderCompileStep, "step", step);
|
||||||
const cwd = std.fs.cwd();
|
const cwd = std.fs.cwd();
|
||||||
|
|
||||||
|
const cmd = try self.builder.allocator.alloc([]const u8, self.glslc_cmd.len + 3);
|
||||||
|
for (self.glslc_cmd) |part, i| {
|
||||||
|
cmd[i] = part;
|
||||||
|
}
|
||||||
|
cmd[cmd.len - 2] = "-o";
|
||||||
|
|
||||||
for (self.shaders.items) |shader| {
|
for (self.shaders.items) |shader| {
|
||||||
const dir = path.dirname(shader.full_out_path).?;
|
const dir = path.dirname(shader.full_out_path).?;
|
||||||
try cwd.makePath(dir);
|
try cwd.makePath(dir);
|
||||||
try self.builder.spawnChild(&[_][]const u8{
|
cmd[cmd.len - 3] = shader.source_path;
|
||||||
self.glslc_path,
|
cmd[cmd.len - 1] = shader.full_out_path;
|
||||||
shader.source_path,
|
try self.builder.spawnChild(cmd);
|
||||||
"-o",
|
|
||||||
shader.full_out_path,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user