Create pipeline and shader modules

This commit is contained in:
Timothy Warren 2023-04-06 15:28:09 -04:00
parent cc941caa71
commit 6f9d56d370
7 changed files with 94 additions and 20 deletions

8
justfile Normal file
View File

@ -0,0 +1,8 @@
# Lists the available actions
default:
@just --list
# Convert the human-readable shader code to Vulkan bytecode
compile-shaders:
glslc shaders/shader.vert -o shaders/vert.spv
glslc shaders/shader.frag -o shaders/frag.spv

BIN
shaders/frag.spv Normal file

Binary file not shown.

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];
}

BIN
shaders/vert.spv Normal file

Binary file not shown.

View File

@ -1,7 +1,7 @@
mod functions; mod functions;
use functions::{ use functions::{
create_instance, create_logical_device, create_swapchain, create_swapchain_image_views, create_instance, create_logical_device, create_pipeline, create_swapchain,
pick_physical_device, create_swapchain_image_views, pick_physical_device,
}; };
use crate::VALIDATION_ENABLED; use crate::VALIDATION_ENABLED;
@ -32,13 +32,17 @@ impl App {
pub unsafe fn create(window: &Window) -> Result<Self> { pub unsafe fn create(window: &Window) -> Result<Self> {
let loader = LibloadingLoader::new(LIBRARY)?; let loader = LibloadingLoader::new(LIBRARY)?;
let entry = Entry::new(loader).map_err(|b| anyhow!("{}", b))?; let entry = Entry::new(loader).map_err(|b| anyhow!("{}", b))?;
let mut data = AppData::default(); let mut data = AppData::default();
let instance = create_instance(window, &entry, &mut data)?; let instance = create_instance(window, &entry, &mut data)?;
data.surface = vk_window::create_surface(&instance, window)?; data.surface = vk_window::create_surface(&instance, window)?;
pick_physical_device(&instance, &mut data)?; pick_physical_device(&instance, &mut data)?;
let device = create_logical_device(&instance, &mut data)?; let device = create_logical_device(&instance, &mut data)?;
create_swapchain(window, &instance, &device, &mut data)?; create_swapchain(window, &instance, &device, &mut data)?;
create_swapchain_image_views(&device, &mut data)?; create_swapchain_image_views(&device, &mut data)?;
create_pipeline(&device, &mut data)?;
Ok(Self { Ok(Self {
entry, entry,
@ -61,13 +65,13 @@ impl App {
.for_each(|v| self.device.destroy_image_view(*v, None)); .for_each(|v| self.device.destroy_image_view(*v, None));
self.device.destroy_swapchain_khr(self.data.swapchain, None); self.device.destroy_swapchain_khr(self.data.swapchain, None);
self.device.destroy_device(None); self.device.destroy_device(None);
self.instance.destroy_surface_khr(self.data.surface, None);
if VALIDATION_ENABLED { if VALIDATION_ENABLED {
self.instance self.instance
.destroy_debug_utils_messenger_ext(self.data.messenger, None); .destroy_debug_utils_messenger_ext(self.data.messenger, None);
} }
self.instance.destroy_surface_khr(self.data.surface, None);
self.instance.destroy_instance(None); self.instance.destroy_instance(None);
} }
} }
@ -83,6 +87,7 @@ pub struct AppData {
physical_device: vk::PhysicalDevice, physical_device: vk::PhysicalDevice,
graphics_queue: vk::Queue, graphics_queue: vk::Queue,
present_queue: vk::Queue, present_queue: vk::Queue,
// Swapchain
swapchain_format: vk::Format, swapchain_format: vk::Format,
swapchain_extent: vk::Extent2D, swapchain_extent: vk::Extent2D,
swapchain: vk::SwapchainKHR, swapchain: vk::SwapchainKHR,
@ -90,17 +95,19 @@ pub struct AppData {
swapchain_image_views: Vec<vk::ImageView>, swapchain_image_views: Vec<vk::ImageView>,
} }
impl AppData {}
#[derive(Debug, Error)] #[derive(Debug, Error)]
#[error("Missing {0}.")] #[error("Missing {0}.")]
pub struct SuitabilityError(pub &'static str); pub struct SuitabilityError(pub &'static str);
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub(crate) struct QueueFamilyIndicies { pub(crate) struct QueueFamilyIndices {
graphics: u32, graphics: u32,
present: u32, present: u32,
} }
impl QueueFamilyIndicies { impl QueueFamilyIndices {
unsafe fn get( unsafe fn get(
instance: &Instance, instance: &Instance,
data: &AppData, data: &AppData,

View File

@ -133,12 +133,12 @@ pub(super) unsafe fn pick_physical_device(instance: &Instance, data: &mut AppDat
Err(anyhow!("Failed to find suitable physical device.")) Err(anyhow!("Failed to find suitable physical device."))
} }
pub(super) unsafe fn check_physical_device( unsafe fn check_physical_device(
instance: &Instance, instance: &Instance,
data: &AppData, data: &AppData,
physical_device: vk::PhysicalDevice, physical_device: vk::PhysicalDevice,
) -> Result<()> { ) -> Result<()> {
QueueFamilyIndicies::get(instance, data, physical_device)?; QueueFamilyIndices::get(instance, data, physical_device)?;
check_physical_device_extensions(instance, physical_device)?; check_physical_device_extensions(instance, physical_device)?;
let support = SwapchainSupport::get(instance, data, physical_device)?; let support = SwapchainSupport::get(instance, data, physical_device)?;
@ -149,7 +149,7 @@ pub(super) unsafe fn check_physical_device(
Ok(()) Ok(())
} }
pub(super) unsafe fn check_physical_device_extensions( unsafe fn check_physical_device_extensions(
instance: &Instance, instance: &Instance,
physical_device: vk::PhysicalDevice, physical_device: vk::PhysicalDevice,
) -> Result<()> { ) -> Result<()> {
@ -173,7 +173,7 @@ pub(super) unsafe fn create_logical_device(
data: &mut AppData, data: &mut AppData,
) -> Result<Device> { ) -> Result<Device> {
// Queue Create Infos // Queue Create Infos
let indices = QueueFamilyIndicies::get(instance, data, data.physical_device)?; let indices = QueueFamilyIndices::get(instance, data, data.physical_device)?;
let mut unique_indices = HashSet::new(); let mut unique_indices = HashSet::new();
unique_indices.insert(indices.graphics); unique_indices.insert(indices.graphics);
@ -230,9 +230,7 @@ pub(super) unsafe fn create_logical_device(
Ok(device) Ok(device)
} }
pub(super) fn get_swapchain_surface_format( fn get_swapchain_surface_format(formats: &[vk::SurfaceFormatKHR]) -> vk::SurfaceFormatKHR {
formats: &[vk::SurfaceFormatKHR],
) -> vk::SurfaceFormatKHR {
formats formats
.iter() .iter()
.cloned() .cloned()
@ -243,9 +241,7 @@ pub(super) fn get_swapchain_surface_format(
.unwrap_or_else(|| formats[0]) .unwrap_or_else(|| formats[0])
} }
pub(super) fn get_swapchain_present_mode( fn get_swapchain_present_mode(present_modes: &[vk::PresentModeKHR]) -> vk::PresentModeKHR {
present_modes: &[vk::PresentModeKHR],
) -> vk::PresentModeKHR {
present_modes present_modes
.iter() .iter()
.cloned() .cloned()
@ -253,10 +249,7 @@ pub(super) fn get_swapchain_present_mode(
.unwrap_or(vk::PresentModeKHR::FIFO) .unwrap_or(vk::PresentModeKHR::FIFO)
} }
pub(super) fn get_swapchain_extent( fn get_swapchain_extent(window: &Window, capabilities: vk::SurfaceCapabilitiesKHR) -> vk::Extent2D {
window: &Window,
capabilities: vk::SurfaceCapabilitiesKHR,
) -> vk::Extent2D {
if capabilities.current_extent.width != u32::MAX { if capabilities.current_extent.width != u32::MAX {
capabilities.current_extent capabilities.current_extent
} else { } else {
@ -283,7 +276,7 @@ pub(super) unsafe fn create_swapchain(
device: &Device, device: &Device,
data: &mut AppData, data: &mut AppData,
) -> Result<()> { ) -> Result<()> {
let indices = QueueFamilyIndicies::get(instance, data, data.physical_device)?; let indices = QueueFamilyIndices::get(instance, data, data.physical_device)?;
let support = SwapchainSupport::get(instance, data, data.physical_device)?; let support = SwapchainSupport::get(instance, data, data.physical_device)?;
let surface_format = get_swapchain_surface_format(&support.formats); let surface_format = get_swapchain_surface_format(&support.formats);
@ -364,3 +357,40 @@ pub(super) unsafe fn create_swapchain_image_views(
Ok(()) Ok(())
} }
pub(super) unsafe fn create_pipeline(device: &Device, data: &mut AppData) -> Result<()> {
let vert = include_bytes!("../../shaders/vert.spv");
let frag = include_bytes!("../../shaders/frag.spv");
let vert_shader_module = create_shader_module(device, &vert[..])?;
let frag_shader_module = create_shader_module(device, &frag[..])?;
let vert_stage = vk::PipelineShaderStageCreateInfo::builder()
.stage(vk::ShaderStageFlags::VERTEX)
.module(vert_shader_module)
.name(b"main\0");
let frag_stage = vk::PipelineShaderStageCreateInfo::builder()
.stage(vk::ShaderStageFlags::FRAGMENT)
.module(frag_shader_module)
.name(b"main\0");
device.destroy_shader_module(vert_shader_module, None);
device.destroy_shader_module(frag_shader_module, None);
Ok(())
}
unsafe fn create_shader_module(device: &Device, bytecode: &[u8]) -> Result<vk::ShaderModule> {
let bytecode = Vec::<u8>::from(bytecode);
let (prefix, code, suffix) = bytecode.align_to::<u32>();
if !prefix.is_empty() || !suffix.is_empty() {
return Err(anyhow!("Shader bytecode is not properly aligned."));
}
let info = vk::ShaderModuleCreateInfo::builder()
.code_size(bytecode.len())
.code(code);
Ok(device.create_shader_module(&info, None)?)
}