added compute kernel helper
This commit is contained in:
19
src/main.rs
19
src/main.rs
@@ -56,7 +56,26 @@ mod util;
|
||||
mod button;
|
||||
mod workpiece;
|
||||
|
||||
|
||||
//struct Sprite {
|
||||
// pub texture:
|
||||
//
|
||||
//
|
||||
//}
|
||||
|
||||
/*
|
||||
|
||||
|
||||
How the F am I going to do sprites?
|
||||
|
||||
I need sprites for the slider and buttons at least
|
||||
|
||||
The background + render of the toolpath can probably just be straight up hand manipulated textures
|
||||
|
||||
Sprite will have 4 verticies and a texture along with position and size attributes
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
fn main() {
|
||||
|
||||
@@ -15,7 +15,7 @@ use image::{DynamicImage, ImageBuffer};
|
||||
use image::GenericImageView;
|
||||
use vulkano::descriptor::pipeline_layout::PipelineLayout;
|
||||
use image::GenericImage;
|
||||
use shade_runner::{ComputeLayout, CompileError, FragLayout, FragInput, FragOutput, VertInput, VertOutput, VertLayout};
|
||||
use shade_runner::{ComputeLayout, CompileError, FragLayout, FragInput, FragOutput, VertInput, VertOutput, VertLayout, CompiledShaders, Entry};
|
||||
use vulkano::descriptor::descriptor_set::{PersistentDescriptorSetBuf, PersistentDescriptorSetImg, PersistentDescriptorSetSampler};
|
||||
use shaderc::CompileOptions;
|
||||
use vulkano::framebuffer::{Subpass, RenderPass, RenderPassAbstract, Framebuffer, FramebufferAbstract};
|
||||
@@ -35,6 +35,10 @@ use vulkano::image::attachment::AttachmentImage;
|
||||
use vulkano::image::{Dimensions, ImageUsage};
|
||||
use vulkano::format::Format;
|
||||
use vulkano::sampler::{Sampler, Filter, MipmapMode, SamplerAddressMode};
|
||||
use image::flat::NormalForm::ColumnMajorPacked;
|
||||
|
||||
mod compute_kernel;
|
||||
use crate::vkprocessor::compute_kernel::ComputeKernel;
|
||||
|
||||
#[derive(Default, Debug, Clone)]
|
||||
struct tVertex { position: [f32; 2] }
|
||||
@@ -64,13 +68,14 @@ fn window_size_dependent_setup(
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct MySpecConstants {
|
||||
my_integer_constant: i32,
|
||||
a_boolean: u32,
|
||||
floating_point: f32,
|
||||
#[derive(Clone)]
|
||||
struct SimpleSpecializationConstants {
|
||||
first_constant: i32,
|
||||
second_constant: u32,
|
||||
third_constant: f32,
|
||||
}
|
||||
|
||||
unsafe impl SpecializationConstants for MySpecConstants {
|
||||
unsafe impl SpecializationConstants for SimpleSpecializationConstants {
|
||||
fn descriptors() -> &'static [SpecializationMapEntry] {
|
||||
static DESCRIPTORS: [SpecializationMapEntry; 3] = [
|
||||
SpecializationMapEntry {
|
||||
@@ -96,6 +101,9 @@ unsafe impl SpecializationConstants for MySpecConstants {
|
||||
|
||||
|
||||
pub struct VkProcessor<'a> {
|
||||
pub compute_kernel: Option<ComputeKernel>,
|
||||
pub vertex_shader_path: PathBuf,
|
||||
pub fragment_shader_path: PathBuf,
|
||||
pub instance: Arc<Instance>,
|
||||
pub physical: PhysicalDevice<'a>,
|
||||
pub graphics_pipeline: Option<Arc<GraphicsPipelineAbstract + Sync + Send>>,
|
||||
@@ -107,7 +115,7 @@ pub struct VkProcessor<'a> {
|
||||
pub img_set: Option<Arc<PersistentDescriptorSet<Arc<dyn GraphicsPipelineAbstract + Send + Sync>, ((((), PersistentDescriptorSetImg<Arc<ImmutableImage<Format>>>), PersistentDescriptorSetSampler), PersistentDescriptorSetImg<Arc<AttachmentImage>>)>>>,
|
||||
pub graphics_image_buffer: Option<Arc<ImmutableImage<Format>>>,
|
||||
pub image_buffer: Vec<u8>,
|
||||
pub img_buffers: Vec<Arc<CpuAccessibleBuffer<[u8]>>>,
|
||||
pub compute_image_buffers: Vec<Arc<CpuAccessibleBuffer<[u8]>>>,
|
||||
pub settings_buffer: Option<Arc<CpuAccessibleBuffer<[u32]>>>,
|
||||
pub swapchain: Option<Arc<Swapchain<Window>>>,
|
||||
pub images: Option<Vec<Arc<SwapchainImage<Window>>>>,
|
||||
@@ -115,7 +123,7 @@ pub struct VkProcessor<'a> {
|
||||
pub render_pass: Option<Arc<RenderPassAbstract + Send + Sync>>,
|
||||
pub vertex_buffer: Option<Arc<(dyn BufferAccess + std::marker::Send + std::marker::Sync + 'static)>>,
|
||||
pub dynamic_state: DynamicState,
|
||||
pub graphics_iamge_swap_buffer: Option<std::sync::Arc<vulkano::image::attachment::AttachmentImage>>,
|
||||
pub graphics_image_swap_buffer: Option<std::sync::Arc<vulkano::image::attachment::AttachmentImage>>,
|
||||
}
|
||||
|
||||
|
||||
@@ -140,6 +148,9 @@ impl<'a> VkProcessor<'a> {
|
||||
let queue = queues.next().unwrap();
|
||||
|
||||
VkProcessor {
|
||||
compute_kernel: Option::None,
|
||||
vertex_shader_path: Default::default(),
|
||||
fragment_shader_path: Default::default(),
|
||||
instance: instance.clone(),
|
||||
physical: physical.clone(),
|
||||
graphics_pipeline: Option::None,
|
||||
@@ -151,7 +162,7 @@ impl<'a> VkProcessor<'a> {
|
||||
img_set: Option::None,
|
||||
graphics_image_buffer: None,
|
||||
image_buffer: Vec::new(),
|
||||
img_buffers: Vec::new(),
|
||||
compute_image_buffers: Vec::new(),
|
||||
settings_buffer: Option::None,
|
||||
swapchain: Option::None,
|
||||
images: Option::None,
|
||||
@@ -159,49 +170,18 @@ impl<'a> VkProcessor<'a> {
|
||||
render_pass: Option::None,
|
||||
vertex_buffer: Option::None,
|
||||
dynamic_state: DynamicState { line_width: None, viewports: None, scissors: None },
|
||||
graphics_iamge_swap_buffer: None,
|
||||
graphics_image_swap_buffer: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn compile_kernel(&mut self, filename: String) {
|
||||
let project_root =
|
||||
std::env::current_dir()
|
||||
.expect("failed to get root directory");
|
||||
|
||||
let mut compute_path = project_root.clone();
|
||||
compute_path.push(PathBuf::from("resources/shaders/"));
|
||||
compute_path.push(PathBuf::from(filename));
|
||||
|
||||
|
||||
let mut options = CompileOptions::new().ok_or(CompileError::CreateCompiler).unwrap();
|
||||
options.add_macro_definition("SETTING_POS_X", Some("0"));
|
||||
options.add_macro_definition("SETTING_POS_Y", Some("1"));
|
||||
options.add_macro_definition("SETTING_BUCKETS_START", Some("2"));
|
||||
options.add_macro_definition("SETTING_BUCKETS_LEN", Some("2"));
|
||||
|
||||
let shader =
|
||||
sr::load_compute_with_options(compute_path, options)
|
||||
.expect("Failed to compile");
|
||||
|
||||
let vulkano_entry =
|
||||
sr::parse_compute(&shader)
|
||||
.expect("failed to parse");
|
||||
|
||||
let x = unsafe {
|
||||
vulkano::pipeline::shader::ShaderModule::from_words(self.device.clone(), &shader.compute)
|
||||
}.unwrap();
|
||||
|
||||
let compute_pipeline = Arc::new({
|
||||
unsafe {
|
||||
ComputePipeline::new(self.device.clone(), &x.compute_entry_point(
|
||||
CStr::from_bytes_with_nul_unchecked(b"main\0"),
|
||||
vulkano_entry.compute_layout), &(),
|
||||
).unwrap()
|
||||
self.compute_kernel = Some(ComputeKernel::new(filename, self.device.clone()));
|
||||
self.compute_pipeline = Some(self.compute_kernel.clone().unwrap().get_pipeline());
|
||||
}
|
||||
});
|
||||
|
||||
self.compute_pipeline = Some(compute_pipeline);
|
||||
}
|
||||
|
||||
|
||||
pub fn compile_shaders(&mut self, filename: String, surface: &'a Arc<Surface<Window>>) {
|
||||
|
||||
@@ -262,16 +242,9 @@ impl<'a> VkProcessor<'a> {
|
||||
options.add_macro_definition("SETTING_BUCKETS_START", Some("2"));
|
||||
options.add_macro_definition("SETTING_BUCKETS_LEN", Some("2"));
|
||||
|
||||
let shader = sr::load(vertex_shader_path, fragment_shader_path).expect("");
|
||||
// let shader = match sr::load(vertex_shader_path, fragment_shader_path) {
|
||||
// Ok(t) => t,
|
||||
// Err(e) => {
|
||||
//
|
||||
// panic!(e);
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
// TODO: better compile message, run til successful compile
|
||||
let shader = sr::load(vertex_shader_path, fragment_shader_path)
|
||||
.expect("Shader didn't compile");
|
||||
|
||||
let vulkano_entry =
|
||||
sr::parse(&shader)
|
||||
@@ -285,7 +258,7 @@ impl<'a> VkProcessor<'a> {
|
||||
vulkano::pipeline::shader::ShaderModule::from_words(self.device.clone(), &shader.vertex)
|
||||
}.unwrap();
|
||||
|
||||
let frag_entry_point: GraphicsEntryPoint<MySpecConstants, FragInput, FragOutput, FragLayout> = unsafe {
|
||||
let frag_entry_point: GraphicsEntryPoint<SimpleSpecializationConstants, FragInput, FragOutput, FragLayout> = unsafe {
|
||||
x1.graphics_entry_point(CStr::from_bytes_with_nul_unchecked(b"main\0"),
|
||||
vulkano_entry.frag_input,
|
||||
vulkano_entry.frag_output,
|
||||
@@ -293,7 +266,7 @@ impl<'a> VkProcessor<'a> {
|
||||
GraphicsShaderType::Fragment)
|
||||
};
|
||||
|
||||
let vert_entry_point: GraphicsEntryPoint<MySpecConstants, VertInput, VertOutput, VertLayout> = unsafe {
|
||||
let vert_entry_point: GraphicsEntryPoint<SimpleSpecializationConstants, VertInput, VertOutput, VertLayout> = unsafe {
|
||||
x2.graphics_entry_point(CStr::from_bytes_with_nul_unchecked(b"main\0"),
|
||||
vulkano_entry.vert_input,
|
||||
vulkano_entry.vert_output,
|
||||
@@ -345,20 +318,20 @@ impl<'a> VkProcessor<'a> {
|
||||
// A Vulkan shader can in theory contain multiple entry points, so we have to specify
|
||||
// which one. The `main` word of `main_entry_point` actually corresponds to the name of
|
||||
// the entry point.
|
||||
.vertex_shader(vert_entry_point, MySpecConstants {
|
||||
my_integer_constant: 0,
|
||||
a_boolean: 0,
|
||||
floating_point: 0.0,
|
||||
.vertex_shader(vert_entry_point, SimpleSpecializationConstants {
|
||||
first_constant: 0,
|
||||
second_constant: 0,
|
||||
third_constant: 0.0,
|
||||
})
|
||||
// The content of the vertex buffer describes a list of triangles.
|
||||
.triangle_fan()
|
||||
// Use a resizable viewport set to draw over the entire window
|
||||
.viewports_dynamic_scissors_irrelevant(1)
|
||||
// See `vertex_shader`.
|
||||
.fragment_shader(frag_entry_point, MySpecConstants {
|
||||
my_integer_constant: 0,
|
||||
a_boolean: 0,
|
||||
floating_point: 0.0,
|
||||
.fragment_shader(frag_entry_point, SimpleSpecializationConstants {
|
||||
first_constant: 0,
|
||||
second_constant: 0,
|
||||
third_constant: 0.0,
|
||||
})
|
||||
// We have to indicate which subpass of which render pass this pipeline is going to be used
|
||||
// in. The pipeline will only be usable from this particular subpass.
|
||||
@@ -467,8 +440,8 @@ impl<'a> VkProcessor<'a> {
|
||||
|
||||
self.compute_set = Some(Arc::new(set.build().unwrap()));
|
||||
|
||||
self.img_buffers.push(write_buffer);
|
||||
self.img_buffers.push(read_buffer);
|
||||
self.compute_image_buffers.push(write_buffer);
|
||||
self.compute_image_buffers.push(read_buffer);
|
||||
self.settings_buffer = Some(settings_buffer);
|
||||
|
||||
|
||||
@@ -493,9 +466,6 @@ impl<'a> VkProcessor<'a> {
|
||||
Dimensions::Dim2d { width: self.xy.0, height: self.xy.1 },
|
||||
Format::R8G8B8A8Srgb,
|
||||
self.queue.clone()
|
||||
// self.image_buffer.iter().cloned(),
|
||||
// Format::R8G8B8A8Uint,
|
||||
|
||||
).unwrap()
|
||||
};
|
||||
|
||||
@@ -516,14 +486,13 @@ impl<'a> VkProcessor<'a> {
|
||||
MipmapMode::Nearest, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat,
|
||||
SamplerAddressMode::Repeat, 0.0, 1.0, 0.0, 0.0).unwrap();
|
||||
|
||||
|
||||
self.img_set = Some(Arc::new(PersistentDescriptorSet::start(self.graphics_pipeline.clone().unwrap().clone(), 0)
|
||||
.add_sampled_image(texture.clone(), sampler.clone()).unwrap()
|
||||
.add_image(attachment_image.clone().unwrap().clone()).unwrap()
|
||||
.build().unwrap()));
|
||||
|
||||
self.graphics_image_buffer = Some(texture.clone());
|
||||
self.graphics_iamge_swap_buffer = Some(attachment_image.clone().unwrap());
|
||||
self.graphics_image_swap_buffer = Some(attachment_image.clone().unwrap());
|
||||
}
|
||||
|
||||
pub fn run(&mut self, surface: &'a Arc<Surface<Window>>, mut frame_future: Box<dyn GpuFuture>) -> Box<dyn GpuFuture> {
|
||||
@@ -585,8 +554,8 @@ impl<'a> VkProcessor<'a> {
|
||||
self.compute_pipeline.clone().unwrap().clone(),
|
||||
self.compute_set.clone().unwrap().clone(), ()).unwrap()
|
||||
|
||||
.copy_buffer_to_image(self.img_buffers.get(0).unwrap().clone(),
|
||||
self.graphics_iamge_swap_buffer.clone().unwrap()).unwrap()
|
||||
.copy_buffer_to_image(self.compute_image_buffers.get(0).unwrap().clone(),
|
||||
self.graphics_image_swap_buffer.clone().unwrap()).unwrap()
|
||||
.begin_render_pass(framebuffers[image_num].clone(), false, clear_values)
|
||||
.unwrap()
|
||||
|
||||
@@ -600,7 +569,7 @@ impl<'a> VkProcessor<'a> {
|
||||
|
||||
.build().unwrap();
|
||||
|
||||
let mut data_buffer_content = self.img_buffers.get(0).unwrap().read().unwrap();
|
||||
let mut data_buffer_content = self.compute_image_buffers.get(0).unwrap().read().unwrap();
|
||||
let img = ImageBuffer::from_fn(self.xy.0, self.xy.1, |x, y| {
|
||||
let r = data_buffer_content[((self.xy.0 * y + x) * 4 + 0) as usize] as u8;
|
||||
let g = data_buffer_content[((self.xy.0 * y + x) * 4 + 1) as usize] as u8;
|
||||
|
||||
143
src/vkprocessor/compute_kernel.rs
Normal file
143
src/vkprocessor/compute_kernel.rs
Normal file
@@ -0,0 +1,143 @@
|
||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, DeviceLocalBuffer, ImmutableBuffer, BufferAccess};
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState};
|
||||
use vulkano::descriptor::descriptor_set::{PersistentDescriptorSet, StdDescriptorPoolAlloc};
|
||||
use vulkano::device::{Device, DeviceExtensions, QueuesIter, Queue};
|
||||
use vulkano::instance::{Instance, InstanceExtensions, PhysicalDevice, QueueFamily};
|
||||
use vulkano::pipeline::{ComputePipeline, GraphicsPipeline, GraphicsPipelineAbstract};
|
||||
use vulkano::sync::{GpuFuture, FlushError};
|
||||
use vulkano::sync;
|
||||
use std::time::SystemTime;
|
||||
use std::sync::Arc;
|
||||
use std::ffi::CStr;
|
||||
use std::path::PathBuf;
|
||||
use shade_runner as sr;
|
||||
use image::{DynamicImage, ImageBuffer};
|
||||
use image::GenericImageView;
|
||||
use vulkano::descriptor::pipeline_layout::PipelineLayout;
|
||||
use image::GenericImage;
|
||||
use shade_runner::{ComputeLayout, CompileError, FragLayout, FragInput, FragOutput, VertInput, VertOutput, VertLayout, CompiledShaders, Entry};
|
||||
use vulkano::descriptor::descriptor_set::{PersistentDescriptorSetBuf, PersistentDescriptorSetImg, PersistentDescriptorSetSampler};
|
||||
use shaderc::CompileOptions;
|
||||
use vulkano::framebuffer::{Subpass, RenderPass, RenderPassAbstract, Framebuffer, FramebufferAbstract};
|
||||
use vulkano::pipeline::shader::{GraphicsShaderType, ShaderModule, GraphicsEntryPoint, SpecializationConstants, SpecializationMapEntry};
|
||||
use vulkano::swapchain::{Swapchain, PresentMode, SurfaceTransform, Surface, SwapchainCreationError, AcquireError};
|
||||
use vulkano::swapchain::acquire_next_image;
|
||||
use vulkano::image::swapchain::SwapchainImage;
|
||||
use winit::{EventsLoop, WindowBuilder, Window, Event, WindowEvent};
|
||||
use vulkano_win::VkSurfaceBuild;
|
||||
use vulkano::pipeline::vertex::{SingleBufferDefinition, Vertex};
|
||||
use vulkano::descriptor::PipelineLayoutAbstract;
|
||||
use std::alloc::Layout;
|
||||
use vulkano::pipeline::viewport::Viewport;
|
||||
use image::ImageFormat;
|
||||
use vulkano::image::immutable::ImmutableImage;
|
||||
use vulkano::image::attachment::AttachmentImage;
|
||||
use vulkano::image::{Dimensions, ImageUsage};
|
||||
use vulkano::format::Format;
|
||||
use vulkano::sampler::{Sampler, Filter, MipmapMode, SamplerAddressMode};
|
||||
use image::flat::NormalForm::ColumnMajorPacked;
|
||||
use crate::vkprocessor::SimpleSpecializationConstants;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ComputeKernel {
|
||||
|
||||
compute_pipeline: Option<std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>>>,
|
||||
compute_kernel_path: PathBuf,
|
||||
|
||||
shader: CompiledShaders,
|
||||
entry: Entry,
|
||||
shader_module: Arc<ShaderModule>,
|
||||
device: Arc<Device>,
|
||||
specialization_constants: SimpleSpecializationConstants,
|
||||
}
|
||||
|
||||
impl ComputeKernel {
|
||||
|
||||
fn get_path(filename: String) -> PathBuf {
|
||||
|
||||
let project_root =
|
||||
std::env::current_dir()
|
||||
.expect("failed to get root directory");
|
||||
|
||||
let mut compute_path = project_root.clone();
|
||||
compute_path.push(PathBuf::from("resources/shaders/"));
|
||||
compute_path.push(PathBuf::from(filename));
|
||||
|
||||
compute_path
|
||||
}
|
||||
|
||||
pub fn new(filename: String, device: Arc<Device>) -> ComputeKernel {
|
||||
|
||||
let compute_path = ComputeKernel::get_path(filename);
|
||||
|
||||
let mut options = CompileOptions::new().ok_or(CompileError::CreateCompiler).unwrap();
|
||||
|
||||
let shader = sr::load_compute_with_options(compute_path.clone(), options)
|
||||
.expect("Failed to compile");
|
||||
|
||||
let entry = sr::parse_compute(&shader)
|
||||
.expect("Failed to parse");
|
||||
|
||||
let shader_module = unsafe {
|
||||
vulkano::pipeline::shader::ShaderModule::from_words(device.clone(), &shader.compute)
|
||||
}.unwrap();
|
||||
|
||||
|
||||
ComputeKernel {
|
||||
device: device,
|
||||
shader: shader,
|
||||
compute_pipeline: Option::None,
|
||||
compute_kernel_path: compute_path,
|
||||
entry: entry,
|
||||
shader_module: shader_module,
|
||||
specialization_constants: SimpleSpecializationConstants {
|
||||
first_constant: 0,
|
||||
second_constant: 0,
|
||||
third_constant: 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_pipeline(&mut self) -> std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>> {
|
||||
|
||||
match self.compute_pipeline.clone() {
|
||||
Some(t) => t,
|
||||
None => {
|
||||
self.compute_pipeline = Some(Arc::new({
|
||||
unsafe {
|
||||
ComputePipeline::new(self.device.clone(), &self.shader_module.compute_entry_point(
|
||||
CStr::from_bytes_with_nul_unchecked(b"main\0"),
|
||||
self.entry.compute_layout.clone()), &self.specialization_constants,
|
||||
).unwrap()
|
||||
}
|
||||
}));
|
||||
self.compute_pipeline.clone().unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recompile_kernel(&mut self) {
|
||||
self.compile_kernel(String::from(self.compute_kernel_path.clone().to_str().unwrap()));
|
||||
}
|
||||
|
||||
pub fn compile_kernel(&mut self, filename: String) -> std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>> {
|
||||
|
||||
let mut options = CompileOptions::new().ok_or(CompileError::CreateCompiler).unwrap();
|
||||
self.compute_kernel_path = ComputeKernel::get_path(filename);
|
||||
|
||||
self.shader =
|
||||
sr::load_compute_with_options(self.compute_kernel_path.clone(), options)
|
||||
.expect("Failed to compile");
|
||||
|
||||
self.entry =
|
||||
sr::parse_compute(&self.shader)
|
||||
.expect("Failed to parse");
|
||||
|
||||
self.shader_module = unsafe {
|
||||
vulkano::pipeline::shader::ShaderModule::from_words(self.device.clone(), &self.shader.compute)
|
||||
}.unwrap();
|
||||
|
||||
self.get_pipeline()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user