Create pipeline and shader modules
This commit is contained in:
parent
cc941caa71
commit
6f9d56d370
8
justfile
Normal file
8
justfile
Normal 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
BIN
shaders/frag.spv
Normal file
Binary file not shown.
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];
|
||||||
|
}
|
BIN
shaders/vert.spv
Normal file
BIN
shaders/vert.spv
Normal file
Binary file not shown.
17
src/app.rs
17
src/app.rs
@ -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,
|
||||||
|
@ -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)?)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user