Most of the compute side is mocked up and compiling.

master
mitchellhansen 5 years ago
parent 9b8d5cd828
commit a3607ebc7d

@ -9,7 +9,7 @@ use vulkano::device::{Device, Queue};
use vulkano::instance::PhysicalDevice; use vulkano::instance::PhysicalDevice;
use vulkano::image::immutable::ImmutableImage; use vulkano::image::immutable::ImmutableImage;
use crate::util::shader_kernels::ShaderKernels; use crate::util::shader_kernels::ShaderKernels;
use vulkano::image::{Dimensions, ImageAccess, ImageDimensions, SwapchainImage}; use vulkano::image::{Dimensions, ImageAccess, ImageDimensions, SwapchainImage, ImageUsage, AttachmentImage};
use vulkano::sampler::{Sampler, SamplerAddressMode, MipmapMode, Filter}; use vulkano::sampler::{Sampler, SamplerAddressMode, MipmapMode, Filter};
use vulkano::descriptor::DescriptorSet; use vulkano::descriptor::DescriptorSet;
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet; use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
@ -82,7 +82,8 @@ impl Vertex for ColoredVertex2D {
pub trait Drawable { pub trait Drawable {
fn get_vertices(&self) -> Vec<(f32, f32)>; fn get_vertices(&self) -> Vec<(f32, f32)>;
fn get_color(&self) -> (f32, f32, f32, f32); fn get_color(&self) -> (f32, f32, f32, f32);
fn get_texture_id(&self) -> Option<String>; fn get_texture_handle(&self) -> Option<Arc<u32>>;
fn get_image_handle(&self) -> Option<Arc<u32>>;
} }
// Need three types of shaders. Solid, Textured, Compute // Need three types of shaders. Solid, Textured, Compute
@ -95,7 +96,7 @@ pub enum ShaderType {
pub struct CanvasFrame { pub struct CanvasFrame {
colored_drawables : Vec<ColoredVertex2D>, colored_drawables : Vec<ColoredVertex2D>,
textured_drawables: HashMap<String, Vec<Vertex2D>>, textured_drawables: HashMap<Arc<u32>, Vec<Vertex2D>>,
} }
impl CanvasFrame { impl CanvasFrame {
@ -110,10 +111,10 @@ impl CanvasFrame {
// After done using this, need to call allocated vertex buffers // After done using this, need to call allocated vertex buffers
pub fn draw(&mut self, drawable: &dyn Drawable) { pub fn draw(&mut self, drawable: &dyn Drawable) {
match drawable.get_texture_id() { match drawable.get_texture_handle() {
Some(id) => { Some(id) => {
self.textured_drawables self.textured_drawables
.entry(id) .entry(id.clone())
.or_insert(Vec::new()) .or_insert(Vec::new())
.extend(drawable.get_vertices().iter().map(|n| .extend(drawable.get_vertices().iter().map(|n|
Vertex2D { Vertex2D {
@ -145,8 +146,8 @@ pub struct Canvas {
colored_drawables : Vec<ColoredVertex2D>, colored_drawables : Vec<ColoredVertex2D>,
colored_vertex_buffer: Vec<Arc<(dyn BufferAccess + std::marker::Send + std::marker::Sync)>>, colored_vertex_buffer: Vec<Arc<(dyn BufferAccess + std::marker::Send + std::marker::Sync)>>,
textured_drawables: HashMap<String, Vec<Vertex2D>>, textured_drawables: HashMap<Arc<u32>, Vec<Vertex2D>>,
textured_vertex_buffer: HashMap<String, Arc<(dyn BufferAccess + std::marker::Send + std::marker::Sync)>>, textured_vertex_buffer: HashMap<Arc<u32>, Arc<(dyn BufferAccess + std::marker::Send + std::marker::Sync)>>,
shader_kernels: HashMap<ShaderType, ShaderKernels>, shader_kernels: HashMap<ShaderType, ShaderKernels>,
@ -154,9 +155,13 @@ pub struct Canvas {
dynamic_state: DynamicState, dynamic_state: DynamicState,
image_buffers: Vec<std::sync::Arc<vulkano::image::attachment::AttachmentImage>>,
image_buffer_handles: Vec<Arc<u32>>,
// 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>,
sampler: Arc<Sampler> sampler: Arc<Sampler>,
device: Arc<Device>,
} }
@ -177,6 +182,7 @@ impl Canvas {
]); ]);
Canvas { Canvas {
colored_drawables: vec![], colored_drawables: vec![],
colored_vertex_buffer: vec![], colored_vertex_buffer: vec![],
@ -188,6 +194,10 @@ impl Canvas {
dynamic_state: DynamicState { line_width: None, viewports: None, scissors: None }, dynamic_state: DynamicState { line_width: None, viewports: None, scissors: None },
image_buffers: Vec::new(),
image_buffer_handles: Vec::new(),
device: device.clone(),
queue: queue.clone(), queue: queue.clone(),
sampler: Sampler::new(device.clone(), Filter::Linear, Filter::Linear, sampler: Sampler::new(device.clone(), Filter::Linear, Filter::Linear,
MipmapMode::Nearest, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat, MipmapMode::Nearest, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat,
@ -196,6 +206,18 @@ impl Canvas {
} }
} }
pub fn create_image(&mut self, dimensions: (u32, u32), usage: ImageUsage) -> Arc<u32> {
self.image_buffers.push(
AttachmentImage::with_usage(
self.device.clone(),
[dimensions.0, dimensions.1],
Format::R8G8B8A8Uint,
usage).unwrap());
let id = Arc::new(self.image_buffers.len() as u32);
self.image_buffer_handles.push(id.clone());
id
}
// TODO Handle file not found gracefully // TODO Handle file not found gracefully
fn get_texture_from_file(&self, image_filename: String) -> Arc<ImmutableImage<Format>> { fn get_texture_from_file(&self, image_filename: String) -> Arc<ImmutableImage<Format>> {

@ -5,14 +5,15 @@ use vulkano::framebuffer::RenderPassAbstract;
use vulkano::pipeline::{GraphicsPipelineAbstract, ComputePipeline}; use vulkano::pipeline::{GraphicsPipelineAbstract, ComputePipeline};
use vulkano::device::Device; use vulkano::device::Device;
use crate::util::compute_kernel::ComputeKernel; use crate::util::compute_kernel::ComputeKernel;
use image::{ImageBuffer}; use image::ImageBuffer;
use image::GenericImageView; use image::GenericImageView;
use crate::util::compute_image::ComputeImage; use crate::util::compute_image::ComputeImage;
use vulkano::image::{ImageUsage, AttachmentImage}; use vulkano::image::{ImageUsage, AttachmentImage};
use vulkano::descriptor::descriptor_set::{PersistentDescriptorSetBuf, PersistentDescriptorSet}; use vulkano::descriptor::descriptor_set::{PersistentDescriptorSetBuf, PersistentDescriptorSet};
use vulkano::format::Format; use vulkano::format::Format;
use vulkano::descriptor::pipeline_layout::PipelineLayout; use vulkano::descriptor::pipeline_layout::PipelineLayout;
use std::borrow::Borrow;
use image::Rgba;
pub struct CompuSprite { pub struct CompuSprite {
vertices: [(f32, f32); 6], vertices: [(f32, f32); 6],
@ -22,28 +23,44 @@ pub struct CompuSprite {
image_handle: Arc<u32>, image_handle: Arc<u32>,
} }
impl CompuSprite { impl Drawable for CompuSprite {
fn get_vertices(&self) -> Vec<(f32, f32)> {
self.vertices.to_vec()
}
fn get_color(&self) -> (f32, f32, f32, f32) {
self.color
}
fn get_texture_handle(&self) -> Option<Arc<u32>> {
None
}
fn get_image_handle(&self) -> Option<Arc<u32>> {
Some(self.image_handle.clone())
}
}
impl CompuSprite {
pub fn new(position: (f32, f32), pub fn new(position: (f32, f32),
size: (f32, f32), size: (f32, f32),
image_handle: Arc<u32>) -> CompuSprite { image_handle: Arc<u32>) -> CompuSprite {
let fsize = (size.0 as f32, size.1 as f32); let fsize = (size.0 as f32, size.1 as f32);
CompuSprite { CompuSprite {
vertices: [ vertices: [
(position.0, position.1 ), // top left (position.0, position.1), // top left
(position.0, position.1 + fsize.1), // bottom left (position.0, position.1 + fsize.1), // bottom left
(position.0 + fsize.0, position.1 + fsize.1 ), // bottom right (position.0 + fsize.0, position.1 + fsize.1), // bottom right
(position.0, position.1 ), // top left (position.0, position.1), // top left
(position.0 + fsize.0, position.1 + fsize.1 ), // bottom right (position.0 + fsize.0, position.1 + fsize.1), // bottom right
(position.0 + fsize.0, position.1 ), // top right (position.0 + fsize.0, position.1), // top right
], ],
position: position, position: position,
size: size, size: size,
color: (0.0,0.0,0.0,0.0), color: (0.0, 0.0, 0.0, 0.0),
image_handle: image_handle.clone() image_handle: image_handle.clone(),
} }
} }
@ -60,7 +77,7 @@ impl CompuSprite {
} }
} }
#[derive(Clone)]
pub struct CompuBuffers { pub struct CompuBuffers {
dimensions: (u32, u32), dimensions: (u32, u32),
device: Arc<Device>, device: Arc<Device>,
@ -72,7 +89,6 @@ pub struct CompuBuffers {
impl CompuBuffers { impl CompuBuffers {
pub fn new(device: Arc<Device>, data: Vec<u8>, dimensions: (u32, u32), stride: u32) -> CompuBuffers { pub fn new(device: Arc<Device>, data: Vec<u8>, dimensions: (u32, u32), stride: u32) -> CompuBuffers {
let data_length = dimensions.0 * dimensions.1 * stride; let data_length = dimensions.0 * dimensions.1 * stride;
let input_buffer = { let input_buffer = {
@ -99,33 +115,46 @@ impl CompuBuffers {
data_iter).unwrap() data_iter).unwrap()
}; };
CompuBuffers{ CompuBuffers {
dimensions: dimensions, dimensions: dimensions,
device: device.clone(), device: device.clone(),
io_buffers: vec![input_buffer, output_buffer], io_buffers: vec![input_buffer, output_buffer],
settings_buffer: settings_buffer settings_buffer: settings_buffer,
} }
} }
pub fn get_size(&self) -> (u32, u32) { pub fn get_size(&self) -> (u32, u32) {
self.dimensions self.dimensions
} }
pub fn get_descriptor_set(&self, compute_pipeline: std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>>) pub fn get_descriptor_set(&self, compute_pipeline: std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>>)
-> Arc<PersistentDescriptorSet<std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>>, ((((), -> Arc<PersistentDescriptorSet<std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>>, ((((),
PersistentDescriptorSetBuf<std::sync::Arc<vulkano::buffer::cpu_access::CpuAccessibleBuffer<[u8]>>>), PersistentDescriptorSetBuf<std::sync::Arc<vulkano::buffer::cpu_access::CpuAccessibleBuffer<[u8]>>>),
PersistentDescriptorSetBuf<std::sync::Arc<vulkano::buffer::cpu_access::CpuAccessibleBuffer<[u8]>>>), PersistentDescriptorSetBuf<std::sync::Arc<vulkano::buffer::cpu_access::CpuAccessibleBuffer<[u8]>>>),
PersistentDescriptorSetBuf<std::sync::Arc<vulkano::buffer::cpu_access::CpuAccessibleBuffer<[u32]>>>)>> { PersistentDescriptorSetBuf<std::sync::Arc<vulkano::buffer::cpu_access::CpuAccessibleBuffer<[u32]>>>)>> {
Arc::new(PersistentDescriptorSet::start(compute_pipeline.clone(), 0) Arc::new(PersistentDescriptorSet::start(compute_pipeline.clone(), 0)
.add_buffer(self.io_buffers.get(0).unwrap().clone()).unwrap() .add_buffer(self.io_buffers.get(0).unwrap().clone()).unwrap()
.add_buffer(self.io_buffers.get(1).unwrap().clone()).unwrap() .add_buffer(self.io_buffers.get(1).unwrap().clone()).unwrap()
.add_buffer(self.settings_buffer.clone()).unwrap() .add_buffer(self.settings_buffer.clone()).unwrap()
.build().unwrap()) .build().unwrap())
} }
pub fn read_output_buffer(&self) -> ImageBuffer<Rgba<u8>, Vec<u8>>{
let xy = self.get_size();
self.io_buffers.get(1).unwrap().write().unwrap().map(|x| x);
let data_buffer_content = self.io_buffers.get(1).unwrap().read().unwrap();
ImageBuffer::from_fn(xy.0, xy.1, |x, y| {
let r = data_buffer_content[((xy.0 * y + x) * 4 + 0) as usize] as u8;
let g = data_buffer_content[((xy.0 * y + x) * 4 + 1) as usize] as u8;
let b = data_buffer_content[((xy.0 * y + x) * 4 + 2) as usize] as u8;
let a = data_buffer_content[((xy.0 * y + x) * 4 + 3) as usize] as u8;
image::Rgba([r, g, b, a])
})
}
} }
// Canvas analog // Canvas analog
@ -138,14 +167,42 @@ pub struct CompuState {
} }
impl CompuState { impl CompuState {
fn new_compute_buffer() -> Arc<u32> {
pub fn new() -> CompuState {
CompuState {
compute_buffers: vec![],
compute_buffer_handles: vec![],
kernels: vec![],
kernel_handles: vec![],
}
} }
fn new_kernel(&mut self, pub fn new_compute_buffer(&mut self,
filename: String, data: Vec<u8>,
device: &Arc<Device>) -> Arc<u32> { dimensions: (u32, u32),
stride: u32,
device: Arc<Device>) -> Arc<u32> {
self.compute_buffers.push(
CompuBuffers::new(device.clone(), data, dimensions, stride));
let id = Arc::new(self.compute_buffers.len() as u32);
self.compute_buffer_handles.push(id.clone());
id
}
pub fn read_compute_buffer(&mut self, handle: Arc<u32>) -> Vec<u8> {
// This is way more difficult than it should be
//let compute_buffer : CompuBuffers = self.compute_buffers.get(handle.into()).unwrap();
//compute_buffer.read_output_buffer().to_vec()
Vec::new()
}
pub fn write_compute_buffer(&self, handle: Arc<u32>, data: Vec<u8>) {
}
pub fn new_kernel(&mut self,
filename: String,
device: &Arc<Device>) -> Arc<u32> {
let kernel = ComputeKernel::new(filename, device.clone()); let kernel = ComputeKernel::new(filename, device.clone());
self.kernels.push(kernel); self.kernels.push(kernel);
@ -168,17 +225,39 @@ impl CompuState {
It will need to convert these into a logical list of command_buffer commands It will need to convert these into a logical list of command_buffer commands
*/ */
pub struct ComputeFrame { pub struct ComputeFrame {
// Vec<(Buffer, Kernel)>
pure_compute: Vec<(Arc<u32>, Arc<u32>)>,
// Vec<(Buffer, Image, Kernel)>
swapped_to_image: Vec<(Arc<u32>, Arc<u32>, Arc<u32>)>,
// Vec<(Input Buffer, Output Buffer, Kernel)>
swapped_to_buffer: Vec<(Arc<u32>, Arc<u32>, Arc<u32>)>,
} }
impl ComputeFrame { impl ComputeFrame {
fn add() { pub fn new() -> ComputeFrame {
ComputeFrame {
pure_compute: vec![],
swapped_to_image: vec![],
swapped_to_buffer: vec![]
}
}
pub fn add(&mut self, buffer: Arc<u32>, kernel: Arc<u32>) {
self.pure_compute.push((buffer, kernel));
} }
fn add_chained(output_buffer_id: Arc<u32>, input_buffer_id: Arc<u32>, kernel_id: Arc<u32> ) {
/*
INPUT_BUFFER -> input -> kernel -> output
v------------------^
OUTPUT_BUFFER -> input X kernel X output
*/
pub fn add_chained(&mut self, input_buffer: Arc<u32>, output_buffer: Arc<u32>, kernel: Arc<u32>) {
self.swapped_to_buffer.push((input_buffer, output_buffer, kernel));
} }
fn add_with_image_swap(buffer_id: Arc<u32>, sprite: CompuSprite, ) {
pub fn add_with_image_swap(&mut self, buffer: Arc<u32>, kernel: Arc<u32>, sprite: &CompuSprite) {
self.swapped_to_image.push((buffer, sprite.get_image_handle().clone(), kernel))
} }
} }

@ -21,6 +21,7 @@ use vulkano_win::VkSurfaceBuild;
use sprite::Sprite; use sprite::Sprite;
use crate::canvas::CanvasFrame; use crate::canvas::CanvasFrame;
use crate::compu_wip::{CompuSprite, ComputeFrame, CompuBuffers, CompuState}; use crate::compu_wip::{CompuSprite, ComputeFrame, CompuBuffers, CompuState};
use crate::util::compute_image::ComputeImage;
mod util; mod util;
mod slider; mod slider;
@ -221,9 +222,14 @@ fn main() {
I will also need to get the texture id I will also need to get the texture id
*/ */
let compu_sprite1 = CompuSprite::new((-1.,-0.5), (0.1,0.1));
let compu_sprite1 = CompuSprite::new((-1.,-0.5), (0.1,0.1), processor.new_swap_image((300, 300)));
let image_data = ComputeImage::load_raw(String::from("funky-bird.jpg"));
let compute_buffer = processor.new_compute_buffer(image_data.0, image_data.1, 4);
let compute_kernel = processor.get_kernel_handle(String::from("simple-edge.compute"))
.expect("Can't find that kernel");
while let Some(p) = window.get_position() { while let Some(p) = window.get_position() {
@ -273,13 +279,18 @@ fn main() {
return; return;
} }
let mut compu_frame = ComputeFrame::new();
compu_frame.add(compute_buffer.clone(), compute_kernel.clone());
compu_frame.add_with_image_swap(compute_buffer.clone(), compute_kernel.clone(), &compu_sprite1);
let mut canvas = CanvasFrame::new(); let mut canvas = CanvasFrame::new();
canvas.draw(&sprite); canvas.draw(&sprite);
canvas.draw(&sprite2); canvas.draw(&sprite2);
canvas.draw(&compu_sprite1);
(frame_future) = processor.run(&surface, frame_future,
(frame_future) = processor.run(&surface, frame_future, canvas); canvas,
compu_frame);
} }
} }

@ -1,4 +1,5 @@
use crate::canvas::Drawable; use crate::canvas::Drawable;
use std::sync::Arc;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Sprite { pub struct Sprite {
@ -9,7 +10,7 @@ pub struct Sprite {
color: (f32, f32, f32, f32), color: (f32, f32, f32, f32),
textured: bool, textured: bool,
texture_id: Option<String>, texture_id: Option<Arc<u32>>,
} }
@ -41,7 +42,7 @@ impl Sprite {
} }
} }
pub fn new_with_texture(position: (f32, f32), size: (f32, f32), texture_id: String) -> Sprite { pub fn new_with_texture(position: (f32, f32), size: (f32, f32), texture_id: Arc<u32>) -> Sprite {
let fsize = (size.0 as f32, size.1 as f32); let fsize = (size.0 as f32, size.1 as f32);
@ -75,7 +76,7 @@ impl Drawable for Sprite {
self.color.clone() self.color.clone()
} }
fn get_texture_id(&self) -> Option<String> { fn get_texture_handle(&self) -> Option<Arc<u32>> {
match self.textured { match self.textured {
true => { true => {
self.texture_id.clone() self.texture_id.clone()
@ -83,6 +84,10 @@ impl Drawable for Sprite {
false => None, false => None,
} }
} }
fn get_image_handle(&self) -> Option<Arc<u32>> {
None
}
} }
/* /*

@ -38,7 +38,7 @@ pub struct ComputeImage {
impl ComputeImage { impl ComputeImage {
fn load_raw(filename: String) -> (Vec<u8>, (u32,u32)) { pub fn load_raw(filename: String) -> (Vec<u8>, (u32,u32)) {
let project_root = let project_root =
std::env::current_dir() std::env::current_dir()
@ -141,6 +141,7 @@ impl ComputeImage {
let xy = self.get_size(); let xy = self.get_size();
self.rw_buffers.get(0).unwrap().write().unwrap().map(|x| x);
let data_buffer_content = self.rw_buffers.get(0).unwrap().read().unwrap(); let data_buffer_content = self.rw_buffers.get(0).unwrap().read().unwrap();
ImageBuffer::from_fn(xy.0, xy.1, |x, y| { ImageBuffer::from_fn(xy.0, xy.1, |x, y| {
let r = data_buffer_content[((xy.0 * y + x) * 4 + 0) as usize] as u8; let r = data_buffer_content[((xy.0 * y + x) * 4 + 0) as usize] as u8;

@ -10,6 +10,8 @@ use winit::{Window};
use crate::util::compute_kernel::ComputeKernel; use crate::util::compute_kernel::ComputeKernel;
use crate::util::compute_image::ComputeImage; use crate::util::compute_image::ComputeImage;
use crate::canvas::{Canvas, CanvasFrame}; use crate::canvas::{Canvas, CanvasFrame};
use crate::compu_wip::{CompuState, ComputeFrame};
use vulkano::image::ImageUsage;
pub struct VkProcessor<'a> { pub struct VkProcessor<'a> {
@ -29,6 +31,8 @@ pub struct VkProcessor<'a> {
swapchain_recreate_needed: bool, swapchain_recreate_needed: bool,
compute_state: CompuState,
capabilities: Capabilities, capabilities: Capabilities,
canvas: Canvas, canvas: Canvas,
} }
@ -36,6 +40,45 @@ pub struct VkProcessor<'a> {
impl<'a> VkProcessor<'a> { impl<'a> VkProcessor<'a> {
pub fn preload_textures(&mut self) {
}
pub fn preload_kernels(&mut self) {
}
pub fn preload_shaders(&mut self) {
}
pub fn get_texture_handle(&self, texture_name: String) -> Option<Arc<u32>> {
None
}
pub fn get_kernel_handle(&self, kernel_name: String) -> Option<Arc<u32>> {
None
}
pub fn get_shader_handle(&self, shader_name: String) -> Option<Arc<u32>> {
None
}
pub fn new_swap_image(&mut self, dimensions: (u32, u32)) -> Arc<u32> {
let mut usage = ImageUsage::none();
usage.transfer_destination = true;
usage.storage = true;
self.canvas.create_image(dimensions, usage)
}
pub fn new_compute_buffer(&mut self, data: Vec<u8>, dimensions: (u32, u32), stride: u32) -> Arc<u32> {
self.compute_state.new_compute_buffer(data, dimensions, stride, self.device.clone())
}
pub fn read_compute_buffer(&mut self, handle: Arc<u32>) -> Vec<u8> {
self.compute_state.read_compute_buffer(handle)
}
pub fn write_compute_buffer(&self, handle: Arc<u32>, data: Vec<u8>) {
self.compute_state.write_compute_buffer(handle, data)
}
pub fn new(instance: &'a Arc<Instance>, surface: &'a Arc<Surface<Window>>) -> VkProcessor<'a> { pub fn new(instance: &'a Arc<Instance>, surface: &'a Arc<Surface<Window>>) -> VkProcessor<'a> {
let physical = PhysicalDevice::enumerate(instance).next().unwrap(); let physical = PhysicalDevice::enumerate(instance).next().unwrap();
@ -68,6 +111,7 @@ impl<'a> VkProcessor<'a> {
swapchain: None, swapchain: None,
swapchain_images: None, swapchain_images: None,
swapchain_recreate_needed: false, swapchain_recreate_needed: false,
compute_state: CompuState::new(),
capabilities: capabilities.clone(), capabilities: capabilities.clone(),
canvas: Canvas::new(queue, device, physical, capabilities), canvas: Canvas::new(queue, device, physical, capabilities),
} }
@ -153,8 +197,12 @@ impl<'a> VkProcessor<'a> {
surface: &'a Arc<Surface<Window>>, surface: &'a Arc<Surface<Window>>,
mut frame_future: Box<dyn GpuFuture>, mut frame_future: Box<dyn GpuFuture>,
canvas_frame: CanvasFrame, canvas_frame: CanvasFrame,
compute_frame: ComputeFrame,
) -> Box<dyn GpuFuture> { ) -> Box<dyn GpuFuture> {
//
self.canvas.draw(canvas_frame); self.canvas.draw(canvas_frame);
self.canvas.allocate_vertex_buffers(self.device.clone()); self.canvas.allocate_vertex_buffers(self.device.clone());

Loading…
Cancel
Save