WIP: "Graphics pipeline basics: Shader modules"

TODO: "Graphics pipeline basics: Fixed functions"
https://vulkan-tutorial.com/Drawing_a_triangle/Graphics_pipeline_basics/Fixed_functions
This commit is contained in:
Stephen Seo 2024-03-12 14:22:57 +09:00
parent 41dbff12c3
commit 3aa79ef21a
4 changed files with 145 additions and 0 deletions

View file

@ -1,5 +1,6 @@
use std::env; use std::env;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Command;
fn main() { fn main() {
println!("cargo:rustc-link-lib=vulkan"); println!("cargo:rustc-link-lib=vulkan");
@ -17,4 +18,18 @@ fn main() {
glfw_vk_bindings glfw_vk_bindings
.write_to_file(out_path.join("glfw_vk_bindings.rs")) .write_to_file(out_path.join("glfw_vk_bindings.rs"))
.expect("Couldn't write glfw bindings!"); .expect("Couldn't write glfw bindings!");
let _vert_shader_out = Command::new("glslc")
.arg("shaders/shader.vert")
.arg("-o")
.arg(out_path.join("vert.spv"))
.output()
.expect("Should be able to compile shader.vert!");
let _frag_shader_out = Command::new("glslc")
.arg("shaders/shader.frag")
.arg("-o")
.arg(out_path.join("frag.spv"))
.output()
.expect("Should be able to compile shader.frag!");
} }

9
shaders/shader.frag Normal file
View file

@ -0,0 +1,9 @@
#version 450
layout(location = 0) in vec3 fragColor;
layout(location = 0) out vec4 outColor;
void main() {
outColor = vec4(fragColor, 1.0);
}

20
shaders/shader.vert Normal file
View file

@ -0,0 +1,20 @@
#version 450
layout(location = 0) out vec3 fragColor;
vec2 positions[3] = vec2[](
vec2( 0.0, -0.5),
vec2( 0.5, 0.5),
vec2(-0.5, 0.5)
);
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)
);
void main() {
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
fragColor = colors[gl_VertexIndex];
}

View file

@ -131,6 +131,27 @@ impl Default for SwapChainSupportDetails {
} }
} }
struct ShaderModuleWrapper {
module: ffi::VkShaderModule,
device: ffi::VkDevice,
}
impl ShaderModuleWrapper {
pub fn get_module(&self) -> ffi::VkShaderModule {
self.module
}
}
impl Drop for ShaderModuleWrapper {
fn drop(&mut self) {
if !self.module.is_null() && !self.device.is_null() {
unsafe {
ffi::vkDestroyShaderModule(self.device, self.module, std::ptr::null());
}
}
}
}
struct VulkanApp { struct VulkanApp {
window: *mut ffi::GLFWwindow, window: *mut ffi::GLFWwindow,
vk_instance: ffi::VkInstance, vk_instance: ffi::VkInstance,
@ -198,6 +219,8 @@ impl VulkanApp {
self.create_logical_device(); self.create_logical_device();
self.create_swap_chain(); self.create_swap_chain();
self.create_image_views(); self.create_image_views();
self.create_graphics_pipeline()
.expect("Should be able to set up graphics pipeline");
} }
fn create_instance(&mut self) { fn create_instance(&mut self) {
@ -807,6 +830,84 @@ impl VulkanApp {
} }
} }
} }
fn create_graphics_pipeline(&mut self) -> Result<(), String> {
let vert_shader_module = self.create_vertex_shader_module()?;
let frag_shader_module = self.create_fragment_shader_module()?;
let mut vert_shader_stage_info: ffi::VkPipelineShaderStageCreateInfo =
unsafe { std::mem::zeroed() };
vert_shader_stage_info.sType =
ffi::VkStructureType_VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vert_shader_stage_info.stage = ffi::VkShaderStageFlagBits_VK_SHADER_STAGE_VERTEX_BIT;
vert_shader_stage_info.module = vert_shader_module.get_module();
vert_shader_stage_info.pName = "main\x00".as_ptr() as *const i8;
let mut frag_shader_stage_info: ffi::VkPipelineShaderStageCreateInfo =
unsafe { std::mem::zeroed() };
frag_shader_stage_info.sType =
ffi::VkStructureType_VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
frag_shader_stage_info.stage = ffi::VkShaderStageFlagBits_VK_SHADER_STAGE_FRAGMENT_BIT;
frag_shader_stage_info.module = frag_shader_module.get_module();
frag_shader_stage_info.pName = "main\x00".as_ptr() as *const i8;
// TODO: Use the *_shader_stage_info structs before vert/frag_shader_module is cleaned up.
Ok(())
}
fn create_vertex_shader_module(&mut self) -> Result<ShaderModuleWrapper, String> {
let vertex_shader = std::include_bytes!(concat!(env!("OUT_DIR"), "/vert.spv"));
let mut create_info: ffi::VkShaderModuleCreateInfo = unsafe { std::mem::zeroed() };
create_info.sType = ffi::VkStructureType_VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
create_info.codeSize = vertex_shader.len();
create_info.pCode = vertex_shader.as_ptr() as *const u32;
let mut shader_module: ffi::VkShaderModule = unsafe { std::mem::zeroed() };
let result = unsafe {
ffi::vkCreateShaderModule(
self.device,
std::ptr::addr_of!(create_info),
std::ptr::null(),
std::ptr::addr_of_mut!(shader_module),
)
};
if result != ffi::VkResult_VK_SUCCESS {
Err(String::from("Failed to create vertex shader module!"))
} else {
Ok(ShaderModuleWrapper {
module: shader_module,
device: self.device,
})
}
}
fn create_fragment_shader_module(&mut self) -> Result<ShaderModuleWrapper, String> {
let fragment_shader = std::include_bytes!(concat!(env!("OUT_DIR"), "/frag.spv"));
let mut create_info: ffi::VkShaderModuleCreateInfo = unsafe { std::mem::zeroed() };
create_info.sType = ffi::VkStructureType_VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
create_info.codeSize = fragment_shader.len();
create_info.pCode = fragment_shader.as_ptr() as *const u32;
let mut shader_module: ffi::VkShaderModule = unsafe { std::mem::zeroed() };
let result = unsafe {
ffi::vkCreateShaderModule(
self.device,
std::ptr::addr_of!(create_info),
std::ptr::null(),
std::ptr::addr_of_mut!(shader_module),
)
};
if result != ffi::VkResult_VK_SUCCESS {
Err(String::from("Failed to create fragment shader module!"))
} else {
Ok(ShaderModuleWrapper {
module: shader_module,
device: self.device,
})
}
}
} }
impl Drop for VulkanApp { impl Drop for VulkanApp {