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;
use functions::{
create_instance, create_logical_device, create_swapchain, create_swapchain_image_views,
pick_physical_device,
create_instance, create_logical_device, create_pipeline, create_swapchain,
create_swapchain_image_views, pick_physical_device,
};
use crate::VALIDATION_ENABLED;
@ -32,13 +32,17 @@ impl App {
pub unsafe fn create(window: &Window) -> Result<Self> {
let loader = LibloadingLoader::new(LIBRARY)?;
let entry = Entry::new(loader).map_err(|b| anyhow!("{}", b))?;
let mut data = AppData::default();
let instance = create_instance(window, &entry, &mut data)?;
data.surface = vk_window::create_surface(&instance, window)?;
pick_physical_device(&instance, &mut data)?;
let device = create_logical_device(&instance, &mut data)?;
create_swapchain(window, &instance, &device, &mut data)?;
create_swapchain_image_views(&device, &mut data)?;
create_pipeline(&device, &mut data)?;
Ok(Self {
entry,
@ -61,13 +65,13 @@ impl App {
.for_each(|v| self.device.destroy_image_view(*v, None));
self.device.destroy_swapchain_khr(self.data.swapchain, None);
self.device.destroy_device(None);
self.instance.destroy_surface_khr(self.data.surface, None);
if VALIDATION_ENABLED {
self.instance
.destroy_debug_utils_messenger_ext(self.data.messenger, None);
}
self.instance.destroy_surface_khr(self.data.surface, None);
self.instance.destroy_instance(None);
}
}
@ -83,6 +87,7 @@ pub struct AppData {
physical_device: vk::PhysicalDevice,
graphics_queue: vk::Queue,
present_queue: vk::Queue,
// Swapchain
swapchain_format: vk::Format,
swapchain_extent: vk::Extent2D,
swapchain: vk::SwapchainKHR,
@ -90,17 +95,19 @@ pub struct AppData {
swapchain_image_views: Vec<vk::ImageView>,
}
impl AppData {}
#[derive(Debug, Error)]
#[error("Missing {0}.")]
pub struct SuitabilityError(pub &'static str);
#[derive(Copy, Clone, Debug)]
pub(crate) struct QueueFamilyIndicies {
pub(crate) struct QueueFamilyIndices {
graphics: u32,
present: u32,
}
impl QueueFamilyIndicies {
impl QueueFamilyIndices {
unsafe fn get(
instance: &Instance,
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."))
}
pub(super) unsafe fn check_physical_device(
unsafe fn check_physical_device(
instance: &Instance,
data: &AppData,
physical_device: vk::PhysicalDevice,
) -> Result<()> {
QueueFamilyIndicies::get(instance, data, physical_device)?;
QueueFamilyIndices::get(instance, data, physical_device)?;
check_physical_device_extensions(instance, physical_device)?;
let support = SwapchainSupport::get(instance, data, physical_device)?;
@ -149,7 +149,7 @@ pub(super) unsafe fn check_physical_device(
Ok(())
}
pub(super) unsafe fn check_physical_device_extensions(
unsafe fn check_physical_device_extensions(
instance: &Instance,
physical_device: vk::PhysicalDevice,
) -> Result<()> {
@ -173,7 +173,7 @@ pub(super) unsafe fn create_logical_device(
data: &mut AppData,
) -> Result<Device> {
// 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();
unique_indices.insert(indices.graphics);
@ -230,9 +230,7 @@ pub(super) unsafe fn create_logical_device(
Ok(device)
}
pub(super) fn get_swapchain_surface_format(
formats: &[vk::SurfaceFormatKHR],
) -> vk::SurfaceFormatKHR {
fn get_swapchain_surface_format(formats: &[vk::SurfaceFormatKHR]) -> vk::SurfaceFormatKHR {
formats
.iter()
.cloned()
@ -243,9 +241,7 @@ pub(super) fn get_swapchain_surface_format(
.unwrap_or_else(|| formats[0])
}
pub(super) fn get_swapchain_present_mode(
present_modes: &[vk::PresentModeKHR],
) -> vk::PresentModeKHR {
fn get_swapchain_present_mode(present_modes: &[vk::PresentModeKHR]) -> vk::PresentModeKHR {
present_modes
.iter()
.cloned()
@ -253,10 +249,7 @@ pub(super) fn get_swapchain_present_mode(
.unwrap_or(vk::PresentModeKHR::FIFO)
}
pub(super) fn get_swapchain_extent(
window: &Window,
capabilities: vk::SurfaceCapabilitiesKHR,
) -> vk::Extent2D {
fn get_swapchain_extent(window: &Window, capabilities: vk::SurfaceCapabilitiesKHR) -> vk::Extent2D {
if capabilities.current_extent.width != u32::MAX {
capabilities.current_extent
} else {
@ -283,7 +276,7 @@ pub(super) unsafe fn create_swapchain(
device: &Device,
data: &mut AppData,
) -> 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 surface_format = get_swapchain_surface_format(&support.formats);
@ -364,3 +357,40 @@ pub(super) unsafe fn create_swapchain_image_views(
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)?)
}