more documentation. Image base impl
This commit is contained in:
22
resources/shaders/simple_image.fragment
Normal file
22
resources/shaders/simple_image.fragment
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#version 450
|
||||||
|
// SIMPLE TEXTURE : FRAGMENT SHADER
|
||||||
|
|
||||||
|
// These come in from the previous shader (vertex)
|
||||||
|
layout(location = 0) in vec2 img_coords;
|
||||||
|
|
||||||
|
// This goes out to the bound image in window_size_dependent setup
|
||||||
|
layout(location = 0) out vec4 f_color;
|
||||||
|
|
||||||
|
// This is bound by the descriptor set
|
||||||
|
// Currently handled by the individual buffer and are 1:1
|
||||||
|
layout(set = 0, binding = 0, rgba32ui) readonly uniform uimage2D img;
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
ivec2 pos = ivec2(gl_FragCoord.x, gl_FragCoord.y);
|
||||||
|
|
||||||
|
f_color = imageLoad(img, ivec2(pos)) / (255.0);
|
||||||
|
|
||||||
|
float gamma = 0.5;
|
||||||
|
f_color.rgb = pow(f_color.rgb, vec3(1.0/gamma));
|
||||||
|
|
||||||
|
}
|
||||||
18
resources/shaders/simple_image.vertex
Normal file
18
resources/shaders/simple_image.vertex
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#version 450
|
||||||
|
// SIMPLE IMAGE : VERTEX SHADER
|
||||||
|
|
||||||
|
// These come in from the vertex definition
|
||||||
|
layout(location = 0) in vec2 position;
|
||||||
|
|
||||||
|
// These are made up in the shader themselves
|
||||||
|
layout(location = 0) out vec2 img_coords;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
gl_Position = vec4(position, 0.0, 1.0);
|
||||||
|
img_coords = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
145
src/canvas.rs
145
src/canvas.rs
@@ -4,7 +4,7 @@ use std::collections::HashMap;
|
|||||||
use vulkano::buffer::{BufferAccess, BufferUsage, ImmutableBuffer, CpuAccessibleBuffer};
|
use vulkano::buffer::{BufferAccess, BufferUsage, ImmutableBuffer, CpuAccessibleBuffer};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vulkano::format::{ClearValue, Format};
|
use vulkano::format::{ClearValue, Format};
|
||||||
use vulkano::framebuffer::{FramebufferAbstract, Framebuffer};
|
use vulkano::framebuffer::{FramebufferAbstract, Framebuffer, RenderPass, RenderPassAbstract};
|
||||||
use vulkano::device::{Device, Queue};
|
use vulkano::device::{Device, Queue};
|
||||||
use vulkano::instance::PhysicalDevice;
|
use vulkano::instance::PhysicalDevice;
|
||||||
use vulkano::image::immutable::ImmutableImage;
|
use vulkano::image::immutable::ImmutableImage;
|
||||||
@@ -21,16 +21,8 @@ use vulkano::pipeline::viewport::Viewport;
|
|||||||
use vulkano::descriptor::descriptor::DescriptorDescTy::TexelBuffer;
|
use vulkano::descriptor::descriptor::DescriptorDescTy::TexelBuffer;
|
||||||
use crate::canvas_frame::CanvasFrame;
|
use crate::canvas_frame::CanvasFrame;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use crate::canvas_shader::CanvasShader;
|
use crate::canvas_shader::{CanvasShader, CanvasShaderHandle};
|
||||||
use crate::canvas_buffer::{CanvasImage, CanvasTexture};
|
use crate::canvas_buffer::{CanvasImage, CanvasTexture};
|
||||||
/*
|
|
||||||
If it is textured. It needs to be rendered with the texture shader which requires a separate
|
|
||||||
graphics pipeline. Might as well have a new render pass as well.
|
|
||||||
So framebuffer is tied to the swapchains images as well as the renderpass
|
|
||||||
|
|
||||||
it appears that renderpass is tied to the individual shader
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/// Vertex trait for Drawable Vertices.
|
/// Vertex trait for Drawable Vertices.
|
||||||
pub trait Vertex {
|
pub trait Vertex {
|
||||||
@@ -81,15 +73,20 @@ pub struct CanvasImageHandle {
|
|||||||
pub handle: u32
|
pub handle: u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Canvas state is used for storage of texture and image buffers in addition to vertex buffers
|
||||||
|
/// Canvas state also contains logic for writing the stored buffers to the command_buffer
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CanvasState {
|
pub struct CanvasState {
|
||||||
|
|
||||||
|
/// Generated during new()
|
||||||
dynamic_state: DynamicState,
|
dynamic_state: DynamicState,
|
||||||
|
/// Generated during new()
|
||||||
sampler: Arc<Sampler>,
|
sampler: Arc<Sampler>,
|
||||||
|
|
||||||
// hold the image, texture, and shader buffers the same was as we do CompuState
|
// hold the image, texture, and shader buffers the same was as we do CompuState
|
||||||
image_buffers: Vec<Arc<CanvasImage>>,
|
image_buffers: Vec<Arc<CanvasImage>>,
|
||||||
texture_buffers: Vec<Arc<CanvasTexture>>,
|
texture_buffers: Vec<Arc<CanvasTexture>>,
|
||||||
shader_buffers: HashMap<String, Arc<CanvasShader>>,
|
shader_buffers: Vec<Arc<CanvasShader>>,
|
||||||
|
|
||||||
// Hold onto the vertices we get from the Compu and Canvas Frames
|
// Hold onto the vertices we get from the Compu and Canvas Frames
|
||||||
// When the run comes around, push the vertices to the GPU
|
// When the run comes around, push the vertices to the GPU
|
||||||
@@ -105,13 +102,16 @@ pub struct CanvasState {
|
|||||||
// Looks like we gotta hold onto the queue for managing textures
|
// Looks like we gotta hold onto the queue for managing textures
|
||||||
queue: Arc<Queue>,
|
queue: Arc<Queue>,
|
||||||
device: Arc<Device>,
|
device: Arc<Device>,
|
||||||
|
render_pass: Arc<dyn RenderPassAbstract + Send + Sync>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl CanvasState {
|
impl CanvasState {
|
||||||
// This method is called once during initialization, then again whenever the window is resized
|
|
||||||
|
/// This method is called once during initialization, then again whenever the window is resized
|
||||||
pub fn window_size_dependent_setup(&mut self, images: &[Arc<SwapchainImage<Window>>])
|
pub fn window_size_dependent_setup(&mut self, images: &[Arc<SwapchainImage<Window>>])
|
||||||
-> Vec<Arc<dyn FramebufferAbstract + Send + Sync>> {
|
-> Vec<Arc<dyn FramebufferAbstract + Send + Sync>> {
|
||||||
|
|
||||||
let dimensions = images[0].dimensions();
|
let dimensions = images[0].dimensions();
|
||||||
|
|
||||||
self.dynamic_state.viewports =
|
self.dynamic_state.viewports =
|
||||||
@@ -123,19 +123,54 @@ impl CanvasState {
|
|||||||
|
|
||||||
images.iter().map(|image| {
|
images.iter().map(|image| {
|
||||||
Arc::new(
|
Arc::new(
|
||||||
Framebuffer::start(self.shader_buffers.get("color-passthrough").unwrap().render_pass.clone())
|
Framebuffer::start(self.render_pass.clone())
|
||||||
.add(image.clone()).unwrap()
|
.add(image.clone()).unwrap()
|
||||||
.build().unwrap()
|
.build().unwrap()
|
||||||
) as Arc<dyn FramebufferAbstract + Send + Sync>
|
) as Arc<dyn FramebufferAbstract + Send + Sync>
|
||||||
}).collect::<Vec<_>>()
|
}).collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
// needs to take in the texture list
|
/// Creates a Canvas State. Which at this point is pretty empty
|
||||||
pub fn new(queue: Arc<Queue>,
|
pub fn new(queue: Arc<Queue>,
|
||||||
device: Arc<Device>,
|
device: Arc<Device>,
|
||||||
physical: PhysicalDevice,
|
physical: PhysicalDevice,
|
||||||
capabilities: Capabilities) -> CanvasState {
|
capabilities: Capabilities) -> CanvasState {
|
||||||
|
|
||||||
|
|
||||||
|
let format = capabilities.supported_formats[0].0;
|
||||||
|
|
||||||
|
let render_pass = Arc::new(vulkano::single_pass_renderpass!(
|
||||||
|
device.clone(),
|
||||||
|
|
||||||
|
// Attachments are outgoing like f_color
|
||||||
|
attachments: {
|
||||||
|
// `color` is a custom name we give to the first and only attachment.
|
||||||
|
color: {
|
||||||
|
// `load: Clear` means that we ask the GPU to clear the content of this
|
||||||
|
// attachment at the start of the drawing.
|
||||||
|
load: Clear,
|
||||||
|
// `store: Store` means that we ask the GPU to store the output of the draw
|
||||||
|
// in the actual image. We could also ask it to discard the result.
|
||||||
|
store: Store,
|
||||||
|
// `format: <ty>` indicates the type of the format of the image. This has to
|
||||||
|
// be one of the types of the `vulkano::format` module (or alternatively one
|
||||||
|
// of your structs that implements the `FormatDesc` trait). Here we use the
|
||||||
|
// same format as the swapchain.
|
||||||
|
format: format,
|
||||||
|
// TODO:
|
||||||
|
samples: 1,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pass: {
|
||||||
|
// We use the attachment named `color` as the one and only color attachment.
|
||||||
|
color: [color],
|
||||||
|
//color: [],
|
||||||
|
// No depth-stencil attachment is indicated with empty brackets.
|
||||||
|
depth_stencil: {}
|
||||||
|
}
|
||||||
|
).unwrap());
|
||||||
|
|
||||||
|
|
||||||
CanvasState {
|
CanvasState {
|
||||||
dynamic_state: DynamicState { line_width: None, viewports: None, scissors: None },
|
dynamic_state: DynamicState { line_width: None, viewports: None, scissors: None },
|
||||||
sampler: Sampler::new(device.clone(), Filter::Linear, Filter::Linear,
|
sampler: Sampler::new(device.clone(), Filter::Linear, Filter::Linear,
|
||||||
@@ -143,7 +178,7 @@ impl CanvasState {
|
|||||||
SamplerAddressMode::Repeat, 0.0, 1.0, 0.0, 0.0).unwrap(),
|
SamplerAddressMode::Repeat, 0.0, 1.0, 0.0, 0.0).unwrap(),
|
||||||
image_buffers: vec![],
|
image_buffers: vec![],
|
||||||
texture_buffers: vec![],
|
texture_buffers: vec![],
|
||||||
shader_buffers: HashMap::from_iter(vec![]),
|
shader_buffers: vec![],
|
||||||
|
|
||||||
colored_drawables: vec![],
|
colored_drawables: vec![],
|
||||||
colored_vertex_buffer: vec![],
|
colored_vertex_buffer: vec![],
|
||||||
@@ -154,9 +189,11 @@ impl CanvasState {
|
|||||||
|
|
||||||
queue: queue.clone(),
|
queue: queue.clone(),
|
||||||
device: device.clone(),
|
device: device.clone(),
|
||||||
|
render_pass: render_pass.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Using the dimensions and suggested usage, load a CanvasImage and return it's handle
|
||||||
pub fn create_image(&mut self, dimensions: (u32, u32), usage: ImageUsage) -> Arc<CanvasImageHandle> {
|
pub fn create_image(&mut self, dimensions: (u32, u32), usage: ImageUsage) -> Arc<CanvasImageHandle> {
|
||||||
let handle = Arc::new(CanvasImageHandle { handle: self.image_buffers.len() as u32 });
|
let handle = Arc::new(CanvasImageHandle { handle: self.image_buffers.len() as u32 });
|
||||||
|
|
||||||
@@ -175,12 +212,13 @@ impl CanvasState {
|
|||||||
handle
|
handle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the image buffer from an input image handle
|
||||||
pub fn get_image(&self, image_handle: Arc<CanvasImageHandle>) -> Arc<AttachmentImage> {
|
pub fn get_image(&self, image_handle: Arc<CanvasImageHandle>) -> Arc<AttachmentImage> {
|
||||||
self.image_buffers.get((*image_handle).clone().handle as usize).unwrap()
|
self.image_buffers.get((*image_handle).clone().handle as usize).unwrap()
|
||||||
.clone().buffer.clone()
|
.clone().buffer.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Handle file not found gracefully
|
/// Load a texture buffer from an input filename
|
||||||
fn get_texture_from_file(&self, image_filename: String) -> Arc<ImmutableImage<Format>> {
|
fn get_texture_from_file(&self, image_filename: String) -> Arc<ImmutableImage<Format>> {
|
||||||
let project_root =
|
let project_root =
|
||||||
std::env::current_dir()
|
std::env::current_dir()
|
||||||
@@ -222,6 +260,7 @@ impl CanvasState {
|
|||||||
texture
|
texture
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Load a texture using it's filename from a file. Returns the handle of the loaded texture
|
||||||
pub fn load_texture(&mut self, filename: String) -> Option<Arc<CanvasTextureHandle>> {
|
pub fn load_texture(&mut self, filename: String) -> Option<Arc<CanvasTextureHandle>> {
|
||||||
let texture_buffer = self.get_texture_from_file(filename.clone());
|
let texture_buffer = self.get_texture_from_file(filename.clone());
|
||||||
|
|
||||||
@@ -246,14 +285,25 @@ impl CanvasState {
|
|||||||
pub fn load_shader(&mut self,
|
pub fn load_shader(&mut self,
|
||||||
filename: String,
|
filename: String,
|
||||||
physical: PhysicalDevice,
|
physical: PhysicalDevice,
|
||||||
capabilities: Capabilities) {
|
capabilities: Capabilities) -> Option<Arc<CanvasShaderHandle>> {
|
||||||
|
|
||||||
self.shader_buffers.insert(filename.clone(),
|
let handle = Arc::new(CanvasShaderHandle {
|
||||||
Arc::new(CanvasShader::new_colored(filename.clone(),
|
handle: self.shader_buffers.len() as u32
|
||||||
|
});
|
||||||
|
|
||||||
|
let shader = Arc::new(CanvasShader::new_colored(
|
||||||
|
filename.clone(),
|
||||||
capabilities.clone(),
|
capabilities.clone(),
|
||||||
self.queue.clone(),
|
self.queue.clone(),
|
||||||
physical.clone(),
|
physical.clone(),
|
||||||
self.device.clone())));
|
self.device.clone(),
|
||||||
|
handle.clone(),
|
||||||
|
self.render_pass.clone())
|
||||||
|
);
|
||||||
|
|
||||||
|
self.shader_buffers.push(shader.clone());
|
||||||
|
|
||||||
|
Some(handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Using the texture name, iterates through the stored textures and matches by the name
|
/// Using the texture name, iterates through the stored textures and matches by the name
|
||||||
@@ -267,6 +317,17 @@ impl CanvasState {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Using the shader name, iterates through the stored textures and matches by the name
|
||||||
|
pub fn get_shader_handle(&self, shader_name: String)
|
||||||
|
-> Option<Arc<CanvasShaderHandle>> {
|
||||||
|
for shader in self.shader_buffers.clone() {
|
||||||
|
if shader.name == shader_name {
|
||||||
|
return Some(shader.handle.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
/// Using the texture handle, grab the stored texture and return the buffer
|
/// Using the texture handle, grab the stored texture and return the buffer
|
||||||
pub fn get_texture(&self, texture_handle: Arc<CanvasTextureHandle>)
|
pub fn get_texture(&self, texture_handle: Arc<CanvasTextureHandle>)
|
||||||
-> Arc<ImmutableImage<Format>> {
|
-> Arc<ImmutableImage<Format>> {
|
||||||
@@ -291,7 +352,6 @@ impl CanvasState {
|
|||||||
/// draw(canvas_fame) stored all the intermediate information, this function
|
/// draw(canvas_fame) stored all the intermediate information, this function
|
||||||
/// allocates the vertex buffers using that information
|
/// allocates the vertex buffers using that information
|
||||||
fn allocate_vertex_buffers(&mut self) {
|
fn allocate_vertex_buffers(&mut self) {
|
||||||
|
|
||||||
self.colored_vertex_buffer.clear();
|
self.colored_vertex_buffer.clear();
|
||||||
{
|
{
|
||||||
let g = hprof::enter("Colored Vertex Buffer");
|
let g = hprof::enter("Colored Vertex Buffer");
|
||||||
@@ -344,7 +404,8 @@ impl CanvasState {
|
|||||||
o
|
o
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes the draw commands s
|
/// Pushes the draw commands to the command buffer. Requires the framebuffers and
|
||||||
|
/// image number to be passed in as they are taken care of by the vkprocessor
|
||||||
pub fn draw_commands(&self,
|
pub fn draw_commands(&self,
|
||||||
mut command_buffer: AutoCommandBufferBuilder,
|
mut command_buffer: AutoCommandBufferBuilder,
|
||||||
framebuffers: Vec<Arc<dyn FramebufferAbstract + Send + Sync>>,
|
framebuffers: Vec<Arc<dyn FramebufferAbstract + Send + Sync>>,
|
||||||
@@ -358,7 +419,10 @@ impl CanvasState {
|
|||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
// Solid colors
|
// Solid colors
|
||||||
let mut shader = self.shader_buffers.get("color-passthrough").unwrap().clone();
|
let mut shader = self.shader_buffers.get(
|
||||||
|
self.get_shader_handle(String::from("color-passthrough"))
|
||||||
|
.unwrap().clone().handle as usize
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
// This looks a little weird as colored_vertex_buffer is a vec of GPU allocated vecs.
|
// This looks a little weird as colored_vertex_buffer is a vec of GPU allocated vecs.
|
||||||
// But we can pass in multiple vertex buffers
|
// But we can pass in multiple vertex buffers
|
||||||
@@ -372,36 +436,36 @@ impl CanvasState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Textures
|
// Textures
|
||||||
let mut shader = self.shader_buffers.get("simple_texture").unwrap().clone();
|
let mut shader = self.shader_buffers.get(
|
||||||
|
self.get_shader_handle(String::from("simple_texture"))
|
||||||
|
.unwrap().clone().handle as usize
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
if !self.textured_vertex_buffer.is_empty() {
|
if !self.textured_vertex_buffer.is_empty() {
|
||||||
let handle = self.get_texture_handle(String::from("funky-bird.jpg")).unwrap().clone();
|
for (texture_handle, vertex_buffer) in self.textured_vertex_buffer.clone() {
|
||||||
|
let handle = texture_handle.clone().handle as usize;
|
||||||
// TODO : BAD BAD BAD. SELECTS FIRST TEXTURE ONLY!!!!!!!!!!!!
|
let descriptor_set = self.texture_buffers.get(handle).clone().unwrap().clone()
|
||||||
let descriptor_set = self.texture_buffers.first().clone().unwrap().clone()
|
|
||||||
.get_descriptor_set(shader.clone(), self.sampler.clone());
|
.get_descriptor_set(shader.clone(), self.sampler.clone());
|
||||||
|
|
||||||
let vertex_buffer = self.textured_vertex_buffer.get(&handle).unwrap().clone();
|
|
||||||
|
|
||||||
command_buffer = command_buffer.draw(
|
command_buffer = command_buffer.draw(
|
||||||
shader.get_pipeline().clone(),
|
shader.get_pipeline().clone(),
|
||||||
&self.dynamic_state.clone(), vec![vertex_buffer],
|
&self.dynamic_state.clone(), vec![vertex_buffer],
|
||||||
vec![descriptor_set], (),
|
vec![descriptor_set], (),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Images
|
||||||
let mut shader = self.shader_buffers.get("simple-image").unwrap().clone();
|
let mut shader = self.shader_buffers.get(
|
||||||
|
self.get_shader_handle(String::from("simple_image"))
|
||||||
|
.unwrap().clone().handle as usize
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
if !self.image_vertex_buffer.is_empty() {
|
if !self.image_vertex_buffer.is_empty() {
|
||||||
|
for (image_handle, vertex_buffer) in self.image_vertex_buffer.clone() {
|
||||||
let handle = self.get_texture_handle(String::from("funky-bird.jpg")).unwrap().clone();
|
let handle = image_handle.clone().handle as usize;
|
||||||
|
let descriptor_set = self.image_buffers.get(handle).clone().unwrap().clone()
|
||||||
// TODO : BAD BAD BAD. SELECTS FIRST TEXTURE ONLY!!!!!!!!!!!!
|
.get_descriptor_set(shader.clone());
|
||||||
let descriptor_set = self.texture_buffers.first().clone().unwrap().clone()
|
|
||||||
.get_descriptor_set(shader.clone(), self.sampler.clone());
|
|
||||||
|
|
||||||
let vertex_buffer = self.textured_vertex_buffer.get(&handle).unwrap().clone();
|
|
||||||
|
|
||||||
command_buffer = command_buffer.draw(
|
command_buffer = command_buffer.draw(
|
||||||
shader.get_pipeline().clone(),
|
shader.get_pipeline().clone(),
|
||||||
@@ -409,6 +473,7 @@ impl CanvasState {
|
|||||||
vec![descriptor_set], (),
|
vec![descriptor_set], (),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
command_buffer
|
command_buffer
|
||||||
.end_render_pass()
|
.end_render_pass()
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ pub struct CanvasImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CanvasImage {
|
impl CanvasImage {
|
||||||
pub fn get_descriptor_set(&mut self, shader: Arc<CanvasShader>)
|
pub fn get_descriptor_set(&self, shader: Arc<CanvasShader>)
|
||||||
-> Box<dyn DescriptorSet + Send + Sync> {
|
-> Box<dyn DescriptorSet + Send + Sync> {
|
||||||
let o: Box<dyn DescriptorSet + Send + Sync> = Box::new(
|
let o: Box<dyn DescriptorSet + Send + Sync> = Box::new(
|
||||||
PersistentDescriptorSet::start(
|
PersistentDescriptorSet::start(
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use std::path::PathBuf;
|
|||||||
use shade_runner as sr;
|
use shade_runner as sr;
|
||||||
use vulkano::framebuffer::{Subpass, RenderPassAbstract, Framebuffer, FramebufferAbstract};
|
use vulkano::framebuffer::{Subpass, RenderPassAbstract, Framebuffer, FramebufferAbstract};
|
||||||
use vulkano::pipeline::shader::{GraphicsShaderType, ShaderModule, SpecializationConstants, SpecializationMapEntry};
|
use vulkano::pipeline::shader::{GraphicsShaderType, ShaderModule, SpecializationConstants, SpecializationMapEntry};
|
||||||
use vulkano::swapchain::{Capabilities};
|
use vulkano::swapchain::Capabilities;
|
||||||
use crate::vertex_2d::{ColoredVertex2D, Vertex2D};
|
use crate::vertex_2d::{ColoredVertex2D, Vertex2D};
|
||||||
|
|
||||||
/// Typed wrapper for a u32 shader handle (index id)
|
/// Typed wrapper for a u32 shader handle (index id)
|
||||||
@@ -20,18 +20,17 @@ pub struct CanvasShaderHandle {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CanvasShader {
|
pub struct CanvasShader {
|
||||||
|
|
||||||
pub render_pass: Arc<dyn RenderPassAbstract + Send + Sync>,
|
|
||||||
graphics_pipeline: Option<Arc<dyn GraphicsPipelineAbstract + Sync + Send>>,
|
graphics_pipeline: Option<Arc<dyn GraphicsPipelineAbstract + Sync + Send>>,
|
||||||
|
|
||||||
device: Arc<Device>,
|
device: Arc<Device>,
|
||||||
|
pub(crate) handle: Arc<CanvasShaderHandle>,
|
||||||
|
pub(crate) name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CanvasShader {
|
impl CanvasShader {
|
||||||
|
|
||||||
/// Takes the filename of a .vertex .fragment shader combo in resources/shaders/
|
/// Takes the filename of a .vertex .fragment shader combo in resources/shaders/
|
||||||
/// Returns pathbuffer of that vertex and fragment shader
|
/// Returns pathbuffer of that vertex and fragment shader
|
||||||
fn get_path(filename: String) -> (PathBuf, PathBuf) {
|
fn get_path(filename: String) -> (PathBuf, PathBuf) {
|
||||||
|
|
||||||
let project_root =
|
let project_root =
|
||||||
std::env::current_dir()
|
std::env::current_dir()
|
||||||
.expect("failed to get root directory");
|
.expect("failed to get root directory");
|
||||||
@@ -61,7 +60,9 @@ impl CanvasShader {
|
|||||||
capabilities: Capabilities,
|
capabilities: Capabilities,
|
||||||
queue: Arc<Queue>,
|
queue: Arc<Queue>,
|
||||||
physical: PhysicalDevice,
|
physical: PhysicalDevice,
|
||||||
device: Arc<Device>) -> CanvasShader {
|
device: Arc<Device>,
|
||||||
|
handle: Arc<CanvasShaderHandle>,
|
||||||
|
render_pass: Arc<dyn RenderPassAbstract + Send + Sync>,) -> CanvasShader {
|
||||||
|
|
||||||
let format = capabilities.supported_formats[0].0;
|
let format = capabilities.supported_formats[0].0;
|
||||||
|
|
||||||
@@ -142,7 +143,6 @@ impl CanvasShader {
|
|||||||
|
|
||||||
|
|
||||||
CanvasShader {
|
CanvasShader {
|
||||||
|
|
||||||
graphics_pipeline: Some(Arc::new(GraphicsPipeline::start()
|
graphics_pipeline: Some(Arc::new(GraphicsPipeline::start()
|
||||||
|
|
||||||
.vertex_input_single_buffer::<ColoredVertex2D>()
|
.vertex_input_single_buffer::<ColoredVertex2D>()
|
||||||
@@ -170,7 +170,8 @@ impl CanvasShader {
|
|||||||
.unwrap())),
|
.unwrap())),
|
||||||
|
|
||||||
device: device,
|
device: device,
|
||||||
render_pass: render_pass,
|
handle: handle.clone(),
|
||||||
|
name: filename.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +181,9 @@ impl CanvasShader {
|
|||||||
capabilities: Capabilities,
|
capabilities: Capabilities,
|
||||||
queue: Arc<Queue>,
|
queue: Arc<Queue>,
|
||||||
physical: PhysicalDevice,
|
physical: PhysicalDevice,
|
||||||
device: Arc<Device>) -> CanvasShader {
|
device: Arc<Device>,
|
||||||
|
handle: Arc<CanvasShaderHandle>,
|
||||||
|
render_pass: Arc<dyn RenderPassAbstract + Send + Sync>,) -> CanvasShader {
|
||||||
|
|
||||||
let format = capabilities.supported_formats[0].0;
|
let format = capabilities.supported_formats[0].0;
|
||||||
|
|
||||||
@@ -227,41 +230,7 @@ impl CanvasShader {
|
|||||||
GraphicsShaderType::Vertex))
|
GraphicsShaderType::Vertex))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
let render_pass = Arc::new(vulkano::single_pass_renderpass!(
|
|
||||||
device.clone(),
|
|
||||||
|
|
||||||
// Attachments are outgoing like f_color
|
|
||||||
attachments: {
|
|
||||||
// `color` is a custom name we give to the first and only attachment.
|
|
||||||
color: {
|
|
||||||
// `load: Clear` means that we ask the GPU to clear the content of this
|
|
||||||
// attachment at the start of the drawing.
|
|
||||||
load: Clear,
|
|
||||||
// `store: Store` means that we ask the GPU to store the output of the draw
|
|
||||||
// in the actual image. We could also ask it to discard the result.
|
|
||||||
store: Store,
|
|
||||||
// `format: <ty>` indicates the type of the format of the image. This has to
|
|
||||||
// be one of the types of the `vulkano::format` module (or alternatively one
|
|
||||||
// of your structs that implements the `FormatDesc` trait). Here we use the
|
|
||||||
// same format as the swapchain.
|
|
||||||
format: format,
|
|
||||||
// TODO:
|
|
||||||
samples: 1,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
pass: {
|
|
||||||
// We use the attachment named `color` as the one and only color attachment.
|
|
||||||
color: [color],
|
|
||||||
//color: [],
|
|
||||||
// No depth-stencil attachment is indicated with empty brackets.
|
|
||||||
depth_stencil: {}
|
|
||||||
}
|
|
||||||
).unwrap());
|
|
||||||
|
|
||||||
|
|
||||||
CanvasShader {
|
CanvasShader {
|
||||||
|
|
||||||
graphics_pipeline: Some(Arc::new(GraphicsPipeline::start()
|
graphics_pipeline: Some(Arc::new(GraphicsPipeline::start()
|
||||||
|
|
||||||
.vertex_input_single_buffer::<Vertex2D>()
|
.vertex_input_single_buffer::<Vertex2D>()
|
||||||
@@ -289,10 +258,10 @@ impl CanvasShader {
|
|||||||
.unwrap())),
|
.unwrap())),
|
||||||
|
|
||||||
device: device,
|
device: device,
|
||||||
render_pass: render_pass,
|
handle: handle.clone(),
|
||||||
|
name: filename.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|||||||
21
src/main.rs
21
src/main.rs
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
#![allow(unused_mut)]
|
#![allow(unused_mut)]
|
||||||
@@ -14,7 +13,7 @@ extern crate hprof;
|
|||||||
use sfml::system::*;
|
use sfml::system::*;
|
||||||
use vulkano::sync;
|
use vulkano::sync;
|
||||||
use crate::timer::Timer;
|
use crate::timer::Timer;
|
||||||
use vulkano::instance::{Instance};
|
use vulkano::instance::Instance;
|
||||||
use vulkano::sync::GpuFuture;
|
use vulkano::sync::GpuFuture;
|
||||||
use winit::{EventsLoop, WindowBuilder, WindowEvent, Event, DeviceEvent, VirtualKeyCode, ElementState};
|
use winit::{EventsLoop, WindowBuilder, WindowEvent, Event, DeviceEvent, VirtualKeyCode, ElementState};
|
||||||
use winit::dpi::LogicalSize;
|
use winit::dpi::LogicalSize;
|
||||||
@@ -59,7 +58,6 @@ Canvas works, but I want to use CPU accessible buffer instead of immutable buffe
|
|||||||
|
|
||||||
/// Main Entry
|
/// Main Entry
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
|
||||||
hprof::start_frame();
|
hprof::start_frame();
|
||||||
|
|
||||||
let q1 = hprof::enter("setup");
|
let q1 = hprof::enter("setup");
|
||||||
@@ -96,12 +94,12 @@ pub fn main() {
|
|||||||
let mut accumulator_time: f32 = 0.0;
|
let mut accumulator_time: f32 = 0.0;
|
||||||
let mut current_time: f32 = timer.elap_time();
|
let mut current_time: f32 = timer.elap_time();
|
||||||
|
|
||||||
let mut mouse_xy = Vector2i::new(0,0);
|
let mut mouse_xy = Vector2i::new(0, 0);
|
||||||
|
|
||||||
let sprite = Sprite::new_with_color((0.,0.), (0.1,0.1), (1.,0.,0.,1.));
|
let sprite = Sprite::new_with_color((0., 0.), (0.1, 0.1), (1., 0., 0., 1.));
|
||||||
let sprite2 = Sprite::new_with_color((-1.,-0.5), (0.1,0.1), (0.,1.,0.,1.));
|
let sprite2 = Sprite::new_with_color((-1., -0.5), (0.1, 0.1), (0., 1., 0., 1.));
|
||||||
|
|
||||||
let compu_sprite1 = CompuSprite::new((-1.,-0.5), (0.1,0.1),
|
let compu_sprite1 = CompuSprite::new((-1., -0.5), (0.1, 0.1),
|
||||||
// This swap image needs to match the size of the compute
|
// This swap image needs to match the size of the compute
|
||||||
processor.new_swap_image((720, 756)));
|
processor.new_swap_image((720, 756)));
|
||||||
|
|
||||||
@@ -113,7 +111,7 @@ pub fn main() {
|
|||||||
|
|
||||||
let handle = processor.get_texture_handle(String::from("funky-bird.jpg")).unwrap();
|
let handle = processor.get_texture_handle(String::from("funky-bird.jpg")).unwrap();
|
||||||
|
|
||||||
let sprite3 = Sprite::new_with_texture((0.3, 0.5), (0.1,0.1), handle.clone());
|
let sprite3 = Sprite::new_with_texture((0.3, 0.5), (0.1, 0.1), handle.clone());
|
||||||
|
|
||||||
drop(q2);
|
drop(q2);
|
||||||
drop(q1);
|
drop(q1);
|
||||||
@@ -141,10 +139,10 @@ pub fn main() {
|
|||||||
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } =>
|
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } =>
|
||||||
{
|
{
|
||||||
exit = true;
|
exit = true;
|
||||||
},
|
}
|
||||||
Event::WindowEvent { event: WindowEvent::Resized(_), .. } => {
|
Event::WindowEvent { event: WindowEvent::Resized(_), .. } => {
|
||||||
processor.recreate_swapchain(&surface);
|
processor.recreate_swapchain(&surface);
|
||||||
},
|
}
|
||||||
Event::DeviceEvent { event: DeviceEvent::Key(keyboard_input), .. } => {
|
Event::DeviceEvent { event: DeviceEvent::Key(keyboard_input), .. } => {
|
||||||
match keyboard_input.virtual_keycode.unwrap() {
|
match keyboard_input.virtual_keycode.unwrap() {
|
||||||
VirtualKeyCode::A => {
|
VirtualKeyCode::A => {
|
||||||
@@ -154,7 +152,7 @@ pub fn main() {
|
|||||||
}
|
}
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
// Event::DeviceEvent { event: DeviceEvent::Button(mouse_input), .. } => {
|
// Event::DeviceEvent { event: DeviceEvent::Button(mouse_input), .. } => {
|
||||||
// mouse_xy.x
|
// mouse_xy.x
|
||||||
// },
|
// },
|
||||||
@@ -178,7 +176,6 @@ pub fn main() {
|
|||||||
{
|
{
|
||||||
let g = hprof::enter("Run");
|
let g = hprof::enter("Run");
|
||||||
processor.run(&surface,
|
processor.run(&surface,
|
||||||
//frame_future,
|
|
||||||
canvas,
|
canvas,
|
||||||
compu_frame);
|
compu_frame);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,20 +157,25 @@ impl<'a> VkProcessor<'a> {
|
|||||||
pub fn preload_shaders(&mut self) {
|
pub fn preload_shaders(&mut self) {
|
||||||
self.canvas.load_shader(String::from("color-passthrough"), self.physical.clone(), self.capabilities.clone());
|
self.canvas.load_shader(String::from("color-passthrough"), self.physical.clone(), self.capabilities.clone());
|
||||||
self.canvas.load_shader(String::from("simple_texture"), self.physical.clone(), self.capabilities.clone());
|
self.canvas.load_shader(String::from("simple_texture"), self.physical.clone(), self.capabilities.clone());
|
||||||
|
self.canvas.load_shader(String::from("simple_image"), self.physical.clone(), self.capabilities.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// O(n) Lookup for the matching texture string
|
||||||
pub fn get_texture_handle(&self, texture_name: String) -> Option<Arc<CanvasTextureHandle>> {
|
pub fn get_texture_handle(&self, texture_name: String) -> Option<Arc<CanvasTextureHandle>> {
|
||||||
self.canvas.get_texture_handle(texture_name)
|
self.canvas.get_texture_handle(texture_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// O(n) Lookup for the matching kernel string
|
||||||
pub fn get_kernel_handle(&self, kernel_name: String) -> Option<Arc<CompuKernelHandle>> {
|
pub fn get_kernel_handle(&self, kernel_name: String) -> Option<Arc<CompuKernelHandle>> {
|
||||||
self.compute_state.get_kernel_handle(kernel_name)
|
self.compute_state.get_kernel_handle(kernel_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// O(n) Lookup for the matching shader string
|
||||||
pub fn get_shader_handle(&self, shader_name: String) -> Option<Arc<CanvasShaderHandle>> {
|
pub fn get_shader_handle(&self, shader_name: String) -> Option<Arc<CanvasShaderHandle>> {
|
||||||
None
|
self.canvas.get_shader_handle(shader_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new image which has the transfer usage
|
/// Create a new image which has the transfer usage
|
||||||
pub fn new_swap_image(&mut self, dimensions: (u32, u32)) -> Arc<CanvasImageHandle> {
|
pub fn new_swap_image(&mut self, dimensions: (u32, u32)) -> Arc<CanvasImageHandle> {
|
||||||
let mut usage = ImageUsage::none();
|
let mut usage = ImageUsage::none();
|
||||||
usage.transfer_destination = true;
|
usage.transfer_destination = true;
|
||||||
@@ -179,14 +184,17 @@ impl<'a> VkProcessor<'a> {
|
|||||||
self.canvas.create_image(dimensions, usage)
|
self.canvas.create_image(dimensions, usage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Builds a compute buffer and returns it's handle
|
||||||
pub fn new_compute_buffer(&mut self, data: Vec<u8>, dimensions: (u32, u32), stride: u32) -> Arc<CompuBufferHandle> {
|
pub fn new_compute_buffer(&mut self, data: Vec<u8>, dimensions: (u32, u32), stride: u32) -> Arc<CompuBufferHandle> {
|
||||||
self.compute_state.new_compute_buffer(data, dimensions, stride, self.device.clone())
|
self.compute_state.new_compute_buffer(data, dimensions, stride, self.device.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Takes a compute buffer handle and returns the read data
|
||||||
pub fn read_compute_buffer(&mut self, handle: Arc<CompuBufferHandle>) -> Vec<u8> {
|
pub fn read_compute_buffer(&mut self, handle: Arc<CompuBufferHandle>) -> Vec<u8> {
|
||||||
self.compute_state.read_compute_buffer(handle)
|
self.compute_state.read_compute_buffer(handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Takes a compute buffer handle and writes the received data
|
||||||
pub fn write_compute_buffer(&self, handle: Arc<CompuBufferHandle>, data: Vec<u8>) {
|
pub fn write_compute_buffer(&self, handle: Arc<CompuBufferHandle>, data: Vec<u8>) {
|
||||||
self.compute_state.write_compute_buffer(handle, data)
|
self.compute_state.write_compute_buffer(handle, data)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user