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:
parent
41dbff12c3
commit
3aa79ef21a
4 changed files with 145 additions and 0 deletions
15
build.rs
15
build.rs
|
@ -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
9
shaders/shader.frag
Normal 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
20
shaders/shader.vert
Normal 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];
|
||||||
|
}
|
101
src/main.rs
101
src/main.rs
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue