Continue vulkan c++ tutorial
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 0s

This commit is contained in:
Florian RICHER 2024-11-17 20:19:34 +01:00
parent 81e4212d8e
commit b2d28ef408
Signed by: florian.richer
GPG key ID: C73D37CBED7BFC77
9 changed files with 156 additions and 3 deletions

3
.gitignore vendored
View file

@ -1,2 +1,3 @@
/target
/.direnv
/.direnv
res/shaders/*.spv

7
Cargo.lock generated
View file

@ -490,6 +490,12 @@ dependencies = [
"wasi",
]
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "hashbrown"
version = "0.15.1"
@ -1076,6 +1082,7 @@ dependencies = [
"ash",
"ash-window",
"env_logger",
"glob",
"log",
"winit",
]

View file

@ -7,10 +7,13 @@ publish = false
[dependencies]
anyhow = "1.0"
winit = { version = "0.30", features = [ "rwh_06" ] }
winit = { version = "0.30", features = ["rwh_06"] }
ash = { version = "0.38", default-features = false, features = ["linked", "debug", "std"] }
ash-window = "0.13"
# Log and tracing
log = "0.4"
env_logger = "0.11.5"
env_logger = "0.11.5"
[build-dependencies]
glob = "0.3"

24
build.rs Normal file
View file

@ -0,0 +1,24 @@
use std::process::Command;
fn main() {
for shader in glob::glob("res/shaders/*").unwrap().filter_map(Result::ok) {
if !shader.is_file() {
continue;
}
let shader_file_name = shader.to_str().unwrap();
let mut command = Command::new("glslc");
command.arg(&shader);
let out_file = match shader.extension().unwrap().to_str().unwrap() {
"vert" => shader_file_name.replace(".vert", ".vert.spv"),
"frag" => shader_file_name.replace(".frag", ".frag.spv"),
_ => continue,
};
command.arg("-o");
command.arg(out_file);
command.output().unwrap();
}
}

8
res/shaders/main.frag Normal file
View file

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

1
res/shaders/main.vert Normal file
View file

@ -0,0 +1 @@
#version 450 out gl_PerVertex { vec4 gl_Position; }; 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

@ -17,3 +17,4 @@ pub(self) mod vk_swapchain;
pub use vk_swapchain::VkSwapchain;
mod utils;
mod vk_shader_module;

View file

@ -1,5 +1,8 @@
use crate::vulkan::vk_shader_module::VkShaderModule;
use crate::vulkan::{VkDevice, VkInstance, VkPhysicalDevice, VkSurface, VkSwapchain};
use ash::vk;
use ash::vk::PrimitiveTopology;
use std::ffi::{CStr, CString};
use std::sync::Arc;
pub struct VkRenderContext {
@ -57,6 +60,69 @@ impl VkRenderContext {
&physical_device,
)?);
let shader_entry_name = CStr::from_bytes_with_nul(b"main\0")?;
let vert_shader_module =
VkShaderModule::from_spv_file(device.clone(), "res/shaders/main.vert.spv")?;
let vert_shader_info = vk::PipelineShaderStageCreateInfo::default()
.module(vert_shader_module.handle)
.name(shader_entry_name)
.stage(vk::ShaderStageFlags::VERTEX);
let frag_shader_module =
VkShaderModule::from_spv_file(device.clone(), "res/shaders/main.frag.spv")?;
let frag_shader_info = vk::PipelineShaderStageCreateInfo::default()
.module(frag_shader_module.handle)
.name(shader_entry_name)
.stage(vk::ShaderStageFlags::FRAGMENT);
let shader_stage_create_infos = [vert_shader_info, frag_shader_info];
let vertex_input_info = vk::PipelineVertexInputStateCreateInfo::default();
let input_assembly = vk::PipelineInputAssemblyStateCreateInfo::default()
.topology(PrimitiveTopology::TRIANGLE_LIST);
let viewport = vk::Viewport::default()
.width(swapchain.surface_resolution.width as f32)
.height(swapchain.surface_resolution.height as f32)
.max_depth(1.0);
let scissor = vk::Rect2D::default().extent(swapchain.surface_resolution);
let viewport_state = vk::PipelineViewportStateCreateInfo::default()
.viewports(&[viewport])
.scissors(&[scissor]);
let rasterizer = vk::PipelineRasterizationStateCreateInfo::default()
.polygon_mode(vk::PolygonMode::FILL)
.cull_mode(vk::CullModeFlags::BACK)
.front_face(vk::FrontFace::CLOCKWISE);
let multisampling = vk::PipelineMultisampleStateCreateInfo::default()
.rasterization_samples(vk::SampleCountFlags::TYPE_1)
.min_sample_shading(1.0);
let color_blend_attachment = vk::PipelineColorBlendAttachmentState::default()
.color_write_mask(vk::ColorComponentFlags::RGBA);
let color_blending =
vk::PipelineColorBlendStateCreateInfo::default().attachments(&[color_blend_attachment]);
let dynamic_state = vk::PipelineDynamicStateCreateInfo::default()
.dynamic_states(&[vk::DynamicState::VIEWPORT, vk::DynamicState::LINE_WIDTH]);
let pipeline_layout_info = vk::PipelineLayoutCreateInfo::default();
let pipeline_layout = unsafe {
device
.handle
.create_pipeline_layout(&pipeline_layout_info, None)?
};
unsafe { device.handle.destroy_pipeline_layout(pipeline_layout, None) };
// let present_queue = device.get_device_queue(0);
//
// let pool_create_info = vk::CommandPoolCreateInfo::default()

View file

@ -0,0 +1,42 @@
use crate::vulkan::VkDevice;
use ash::vk;
use std::path::Path;
use std::sync::Arc;
pub struct VkShaderModule {
device: Arc<VkDevice>,
pub(super) handle: vk::ShaderModule,
}
impl VkShaderModule {
pub fn from_spv_file<P: AsRef<Path>>(device: Arc<VkDevice>, path: P) -> anyhow::Result<Self> {
let mut file = std::fs::File::open(&path)?;
let frag_shader_str = ash::util::read_spv(&mut file)?;
let shader_create_info = vk::ShaderModuleCreateInfo::default().code(&frag_shader_str);
let shader_module = unsafe {
device
.handle
.create_shader_module(&shader_create_info, None)?
};
log::debug!(
"Shader module created ({shader_module:?}) from {:?}",
path.as_ref()
);
Ok(Self {
device,
handle: shader_module,
})
}
}
impl Drop for VkShaderModule {
fn drop(&mut self) {
unsafe {
self.device.handle.destroy_shader_module(self.handle, None);
log::debug!("Shader module destroyed ({:?})", self.handle);
}
}
}