moved to rust style file tree
This commit is contained in:
617
src/canvas/canvas_state.rs
Normal file
617
src/canvas/canvas_state.rs
Normal file
@@ -0,0 +1,617 @@
|
||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState};
|
||||
use std::collections::HashMap;
|
||||
use vulkano::buffer::{BufferAccess, BufferUsage, ImmutableBuffer, CpuAccessibleBuffer};
|
||||
use std::sync::Arc;
|
||||
use vulkano::format::{ClearValue, Format, R8Unorm};
|
||||
use vulkano::framebuffer::{FramebufferAbstract, Framebuffer, RenderPass, RenderPassAbstract};
|
||||
use vulkano::device::{Device, Queue};
|
||||
use vulkano::instance::PhysicalDevice;
|
||||
use vulkano::image::immutable::ImmutableImage;
|
||||
use vulkano::image::{Dimensions, ImageAccess, ImageDimensions, SwapchainImage, ImageUsage, AttachmentImage, ImageLayout};
|
||||
use vulkano::sampler::{Sampler, SamplerAddressMode, MipmapMode, Filter};
|
||||
use vulkano::descriptor::DescriptorSet;
|
||||
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
||||
use std::path::PathBuf;
|
||||
use image::GenericImageView;
|
||||
use std::iter::FromIterator;
|
||||
use vulkano::swapchain::Capabilities;
|
||||
use winit::Window;
|
||||
use vulkano::pipeline::viewport::Viewport;
|
||||
use vulkano::descriptor::descriptor::DescriptorDescTy::TexelBuffer;
|
||||
use crate::canvas::canvas_frame::CanvasFrame;
|
||||
use std::hash::Hash;
|
||||
use crate::canvas::canvas_text::{CanvasText, CanvasTextHandle};
|
||||
use crate::canvas::canvas_shader::{CanvasShader, CanvasShaderHandle};
|
||||
use crate::canvas::canvas_buffer::{CanvasImage, CanvasTexture, CanvasTextCache};
|
||||
use crate::util::vertex_3d::Vertex3D;
|
||||
use vulkano::pipeline::depth_stencil::{StencilFaceFlags, DynamicStencilValue};
|
||||
|
||||
/// A drawable object can be passed into a CanvasFrame to be rendered
|
||||
/// Very generic implementation. (N % 2 == 0) vertices, ditto for texture coords, and rgba color
|
||||
/// Provides Image and Texture handles for drawing
|
||||
/// Split out to two drawables?
|
||||
///
|
||||
pub trait Drawable {
|
||||
|
||||
fn get_vertices(&self) -> Vec<(f32, f32, f32)>;
|
||||
fn get_color(&self) -> (f32, f32, f32, f32);
|
||||
fn get_ti_coords(&self) -> Vec<(f32, f32)>;
|
||||
|
||||
fn get_texture_handle(&self) -> Option<Arc<CanvasTextureHandle>>;
|
||||
fn get_image_handle(&self) -> Option<Arc<CanvasImageHandle>>;
|
||||
// fn get_text_handle(&self) -> Option<Arc<CanvasTextHandle>>;
|
||||
|
||||
fn collect(&self) -> Vec<Vertex3D> {
|
||||
let color = self.get_color();
|
||||
self.get_vertices().iter().zip(self.get_ti_coords().iter()).map(|(a, b)|
|
||||
Vertex3D {
|
||||
v_position: [a.0, a.1, a.2],
|
||||
color: [color.0, color.1, color.2, color.3],
|
||||
ti_position: [b.0, b.1],
|
||||
}).collect()
|
||||
}
|
||||
}
|
||||
|
||||
/// Legacy ShaderType enum for single type shaders.
|
||||
#[derive(PartialEq, Eq, Hash, Clone)]
|
||||
pub enum ShaderType {
|
||||
SOLID = 0,
|
||||
TEXTURED = 1,
|
||||
IMAGE = 2,
|
||||
}
|
||||
|
||||
/// Typed wrapper for a u32 texture handle (index id)
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||
pub struct CanvasTextureHandle {
|
||||
pub handle: u32
|
||||
}
|
||||
|
||||
/// Typed wrapper for a u32 image handle (index id)
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||
pub struct CanvasImageHandle {
|
||||
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)]
|
||||
pub struct CanvasState {
|
||||
/// Generated during new()
|
||||
dynamic_state: DynamicState,
|
||||
/// Generated during new()
|
||||
sampler: Arc<Sampler>,
|
||||
|
||||
// hold the image, texture, and shader buffers the same was as we do CompuState
|
||||
image_buffers: Vec<Arc<CanvasImage>>,
|
||||
texture_buffers: Vec<Arc<CanvasTexture>>,
|
||||
shader_buffers: Vec<Arc<CanvasShader>>,
|
||||
text_buffers: Vec<Arc<(CanvasText, CanvasTextCache)>>,
|
||||
|
||||
// Hold onto the vertices we get from the Compu and Canvas Frames
|
||||
// When the run comes around, push the vertices to the GPU
|
||||
colored_drawables: Vec<Vertex3D>,
|
||||
colored_vertex_buffer: Vec<Arc<(dyn BufferAccess + std::marker::Send + std::marker::Sync)>>,
|
||||
|
||||
textured_drawables: HashMap<Arc<CanvasTextureHandle>, Vec<Vec<Vertex3D>>>,
|
||||
textured_vertex_buffer: HashMap<Arc<CanvasTextureHandle>, Arc<(dyn BufferAccess + std::marker::Send + std::marker::Sync)>>,
|
||||
|
||||
image_drawables: HashMap<Arc<CanvasImageHandle>, Vec<Vec<Vertex3D>>>,
|
||||
image_vertex_buffer: HashMap<Arc<CanvasImageHandle>, Arc<(dyn BufferAccess + std::marker::Send + std::marker::Sync)>>,
|
||||
|
||||
// Looks like we gotta hold onto the queue for managing textures
|
||||
queue: Arc<Queue>,
|
||||
device: Arc<Device>,
|
||||
render_pass: Arc<dyn RenderPassAbstract + Send + Sync>,
|
||||
}
|
||||
|
||||
|
||||
impl CanvasState {
|
||||
/// 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>>])
|
||||
-> Vec<Arc<dyn FramebufferAbstract + Send + Sync>> {
|
||||
let dimensions = images[0].dimensions();
|
||||
|
||||
self.dynamic_state.viewports =
|
||||
Some(vec![Viewport {
|
||||
origin: [0.0, 0.0],
|
||||
dimensions: [dimensions.width() as f32, dimensions.height() as f32],
|
||||
depth_range: 0.0..1.0,
|
||||
}]);
|
||||
|
||||
let dimensions = [dimensions.width(), dimensions.height()];
|
||||
let depth_buffer = AttachmentImage::transient(self.device.clone(), dimensions, Format::D32Sfloat_S8Uint).unwrap();
|
||||
|
||||
images.iter().map(|image| {
|
||||
Arc::new(
|
||||
Framebuffer::start(self.render_pass.clone())
|
||||
.add(image.clone()).unwrap()
|
||||
.add(depth_buffer.clone()).unwrap()
|
||||
.build().unwrap()
|
||||
) as Arc<dyn FramebufferAbstract + Send + Sync>
|
||||
}).collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
/// Creates a Canvas State. Which at this point is pretty empty
|
||||
pub fn new(queue: Arc<Queue>,
|
||||
device: Arc<Device>,
|
||||
physical: PhysicalDevice,
|
||||
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,
|
||||
samples: 1,
|
||||
},
|
||||
|
||||
depth: {
|
||||
load: Clear,
|
||||
store: DontCare,
|
||||
format: Format::D32Sfloat_S8Uint,
|
||||
samples: 1,
|
||||
}
|
||||
},
|
||||
pass: {
|
||||
// We use the attachment named `color` as the one and only color attachment.
|
||||
color: [color],
|
||||
// No depth-stencil attachment is indicated with empty brackets.
|
||||
depth_stencil: {depth}
|
||||
}
|
||||
).unwrap());
|
||||
|
||||
|
||||
CanvasState {
|
||||
dynamic_state: DynamicState {
|
||||
line_width: None,
|
||||
viewports: None,
|
||||
scissors: None,
|
||||
compare_mask: Some(DynamicStencilValue {
|
||||
face: StencilFaceFlags::StencilFrontAndBack,
|
||||
value: 0xFF,
|
||||
}),
|
||||
write_mask: Some(DynamicStencilValue {
|
||||
face: StencilFaceFlags::StencilFrontAndBack,
|
||||
value: 0xFF,
|
||||
}),
|
||||
reference: Some(DynamicStencilValue {
|
||||
face: StencilFaceFlags::StencilFrontAndBack,
|
||||
value: 0xFF,
|
||||
}),
|
||||
},
|
||||
sampler: Sampler::new(device.clone(),
|
||||
Filter::Linear, Filter::Linear,
|
||||
MipmapMode::Nearest,
|
||||
SamplerAddressMode::Repeat, SamplerAddressMode::Repeat,
|
||||
SamplerAddressMode::Repeat, 0.0, 1.0, 0.0, 0.0).unwrap(),
|
||||
image_buffers: vec![],
|
||||
texture_buffers: vec![],
|
||||
shader_buffers: vec![],
|
||||
|
||||
text_buffers: vec![],
|
||||
colored_drawables: vec![],
|
||||
colored_vertex_buffer: vec![],
|
||||
textured_drawables: HashMap::default(),
|
||||
textured_vertex_buffer: Default::default(),
|
||||
image_drawables: Default::default(),
|
||||
image_vertex_buffer: Default::default(),
|
||||
|
||||
queue: queue.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_text_buffers(&mut self, dimensions: (u32, u32)) -> Arc<CanvasTextHandle> {
|
||||
|
||||
let handle = Arc::new(CanvasTextHandle { handle: self.text_buffers.len() as u32 });
|
||||
//
|
||||
// let text = CanvasText {
|
||||
// handle: handle.clone(),
|
||||
// buffer: ImmutableImage::uninitialized(
|
||||
// self.device.clone(),
|
||||
// Dimensions::Dim2d { width: CACHE_WIDTH as u32, height: CACHE_HEIGHT as u32 },
|
||||
// R8Unorm,
|
||||
// 1,
|
||||
// ImageUsage {
|
||||
// sampled: true,
|
||||
// transfer_destination: true,
|
||||
// .. ImageUsage::none()
|
||||
// },
|
||||
// ImageLayout::General,
|
||||
// Some(self.queue.family())
|
||||
// ).unwrap().0,
|
||||
// size: dimensions,
|
||||
// };
|
||||
//
|
||||
// let text_cache = CanvasTextCache {
|
||||
// handle: handle.clone(),
|
||||
// buffer: CpuAccessibleBuffer::<[u8]>::from_iter(
|
||||
// self.device.clone(),
|
||||
// BufferUsage::all(),
|
||||
// cache_pixel_buffer.iter().cloned()
|
||||
// ).unwrap(),
|
||||
// size: dimensions,
|
||||
// };
|
||||
//
|
||||
// self.text_buffers.push(Arc::new((text, text_cache)));
|
||||
//
|
||||
handle
|
||||
}
|
||||
|
||||
|
||||
/// 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> {
|
||||
let handle = Arc::new(CanvasImageHandle { handle: self.image_buffers.len() as u32 });
|
||||
|
||||
let image = CanvasImage {
|
||||
handle: handle.clone(),
|
||||
buffer: AttachmentImage::with_usage(
|
||||
self.device.clone(),
|
||||
[dimensions.0, dimensions.1],
|
||||
Format::R8G8B8A8Uint,
|
||||
usage).unwrap(),
|
||||
size: dimensions,
|
||||
};
|
||||
|
||||
self.image_buffers.push(Arc::new(image));
|
||||
|
||||
handle
|
||||
}
|
||||
|
||||
/// Return the image buffer from an input image handle
|
||||
pub fn get_image(&self, image_handle: Arc<CanvasImageHandle>) -> Arc<AttachmentImage> {
|
||||
self.image_buffers.get((*image_handle).clone().handle as usize).unwrap()
|
||||
.clone().buffer.clone()
|
||||
}
|
||||
|
||||
/// Load a texture buffer from an input filename
|
||||
fn get_texture_from_file(&self, image_filename: String) -> Arc<ImmutableImage<Format>> {
|
||||
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/images/"));
|
||||
compute_path.push(PathBuf::from(image_filename));
|
||||
|
||||
let img = image::open(compute_path).expect("Couldn't find image");
|
||||
|
||||
let xy = img.dimensions();
|
||||
|
||||
let data_length = xy.0 * xy.1 * 4;
|
||||
let pixel_count = img.raw_pixels().len();
|
||||
|
||||
let mut image_buffer = Vec::new();
|
||||
|
||||
if pixel_count != data_length as usize {
|
||||
println!("Creating apha channel...");
|
||||
for i in img.raw_pixels().iter() {
|
||||
if (image_buffer.len() + 1) % 4 == 0 {
|
||||
image_buffer.push(255);
|
||||
}
|
||||
image_buffer.push(*i);
|
||||
}
|
||||
image_buffer.push(255);
|
||||
} else {
|
||||
image_buffer = img.raw_pixels();
|
||||
}
|
||||
|
||||
let (texture, tex_future) = ImmutableImage::from_iter(
|
||||
image_buffer.iter().cloned(),
|
||||
Dimensions::Dim2d { width: xy.0, height: xy.1 },
|
||||
Format::R8G8B8A8Srgb,
|
||||
self.queue.clone(),
|
||||
).unwrap();
|
||||
|
||||
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>> {
|
||||
let texture_buffer = self.get_texture_from_file(filename.clone());
|
||||
|
||||
let handle = Arc::new(CanvasTextureHandle {
|
||||
handle: self.texture_buffers.len() as u32
|
||||
});
|
||||
|
||||
let texture = Arc::new(CanvasTexture {
|
||||
handle: handle.clone(),
|
||||
buffer: self.get_texture_from_file(filename.clone()),
|
||||
name: filename.clone(),
|
||||
size: (0, 0),
|
||||
});
|
||||
|
||||
self.texture_buffers.push(texture);
|
||||
|
||||
Some(handle)
|
||||
}
|
||||
|
||||
/// Load and Compile a shader with the filename at resources/shaders
|
||||
/// Takes physical and capabilities as we don't store that in Canvas
|
||||
pub fn load_shader(&mut self,
|
||||
filename: String,
|
||||
shader_type: ShaderType,
|
||||
physical: PhysicalDevice,
|
||||
capabilities: Capabilities) -> Option<Arc<CanvasShaderHandle>> {
|
||||
|
||||
let handle = Arc::new(CanvasShaderHandle {
|
||||
handle: self.shader_buffers.len() as u32
|
||||
});
|
||||
|
||||
// TODO : what is even going on here
|
||||
let shader = match shader_type {
|
||||
ShaderType::SOLID => {
|
||||
Arc::new(CanvasShader::new(
|
||||
filename.clone(),
|
||||
capabilities.clone(),
|
||||
self.queue.clone(),
|
||||
physical.clone(),
|
||||
self.device.clone(),
|
||||
handle.clone(),
|
||||
self.render_pass.clone())
|
||||
)
|
||||
}
|
||||
ShaderType::IMAGE | ShaderType::TEXTURED => {
|
||||
Arc::new(CanvasShader::new(
|
||||
filename.clone(),
|
||||
capabilities.clone(),
|
||||
self.queue.clone(),
|
||||
physical.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
|
||||
pub fn get_texture_handle(&self, texture_name: String)
|
||||
-> Option<Arc<CanvasTextureHandle>> {
|
||||
for i in self.texture_buffers.clone() {
|
||||
if i.name == texture_name {
|
||||
return Some(i.handle.clone());
|
||||
}
|
||||
}
|
||||
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
|
||||
pub fn get_texture(&self, texture_handle: Arc<CanvasTextureHandle>)
|
||||
-> Arc<ImmutableImage<Format>> {
|
||||
let handle = texture_handle.handle as usize;
|
||||
|
||||
if let Some(i) = self.texture_buffers.get(handle) {
|
||||
return i.clone().buffer.clone();
|
||||
} else {
|
||||
panic!("{} : Texture not loaded", handle);
|
||||
}
|
||||
}
|
||||
|
||||
/// Scrape all the values from the CanvasFrame and then allocate the vertex buffers
|
||||
pub fn draw(&mut self, canvas_frame: CanvasFrame) {
|
||||
self.textured_drawables = canvas_frame.textured_drawables;
|
||||
self.colored_drawables = canvas_frame.colored_drawables;
|
||||
self.image_drawables = canvas_frame.image_drawables;
|
||||
|
||||
self.allocate_vertex_buffers();
|
||||
}
|
||||
|
||||
/// draw(canvas_fame) stored all the intermediate information, this function
|
||||
/// allocates the vertex buffers using that information
|
||||
fn allocate_vertex_buffers(&mut self) {
|
||||
self.colored_vertex_buffer.clear();
|
||||
{
|
||||
let g = hprof::enter("Colored Vertex Buffer");
|
||||
self.colored_vertex_buffer.push(
|
||||
ImmutableBuffer::from_iter(
|
||||
self.colored_drawables.iter().cloned(),
|
||||
BufferUsage::vertex_buffer(),
|
||||
self.queue.clone(),
|
||||
).unwrap().0
|
||||
);
|
||||
}
|
||||
|
||||
self.textured_vertex_buffer.clear();
|
||||
{
|
||||
let g = hprof::enter("Textured Vertex Buffer");
|
||||
for (k, v) in self.textured_drawables.drain() {
|
||||
let vertex_buffer = v.clone().iter()
|
||||
.fold(Vec::new(), |mut a: Vec<Vertex3D>, b| {
|
||||
a.extend(b);
|
||||
a
|
||||
});
|
||||
|
||||
self.textured_vertex_buffer.insert(
|
||||
k.clone(),
|
||||
ImmutableBuffer::from_iter(
|
||||
vertex_buffer.iter().cloned(),
|
||||
BufferUsage::vertex_buffer(),
|
||||
self.queue.clone(),
|
||||
).unwrap().0,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self.image_vertex_buffer.clear();
|
||||
{
|
||||
let g = hprof::enter("Image Vertex Buffer");
|
||||
for (k, v) in self.image_drawables.drain() {
|
||||
let vertex_buffer = v.clone().iter()
|
||||
.fold(Vec::new(), |mut a: Vec<Vertex3D>, b| {
|
||||
a.extend(b);
|
||||
a
|
||||
});
|
||||
|
||||
self.image_vertex_buffer.insert(
|
||||
k.clone(),
|
||||
ImmutableBuffer::from_iter(
|
||||
vertex_buffer.iter().cloned(),
|
||||
BufferUsage::vertex_buffer(),
|
||||
self.queue.clone(),
|
||||
).unwrap().0,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds the descriptor set for solid colors using the input kernel (needs to support solid colors)
|
||||
fn get_solid_color_descriptor_set(&self, kernel: Arc<CanvasShader>) -> Box<dyn DescriptorSet + Send + Sync> {
|
||||
let o: Box<dyn DescriptorSet + Send + Sync> = Box::new(
|
||||
PersistentDescriptorSet::start(
|
||||
kernel.clone().get_pipeline().clone(), 0,
|
||||
).build().unwrap());
|
||||
o
|
||||
}
|
||||
|
||||
/// 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(&mut self,
|
||||
mut command_buffer: AutoCommandBufferBuilder,
|
||||
framebuffers: Vec<Arc<dyn FramebufferAbstract + Send + Sync>>,
|
||||
image_num: usize) -> AutoCommandBufferBuilder {
|
||||
|
||||
// Specify the color to clear the framebuffer with i.e. blue
|
||||
let clear_values = vec!(
|
||||
ClearValue::Float([0.0, 0.0, 1.0, 1.0]),
|
||||
ClearValue::DepthStencil((1.0, 0x00)),
|
||||
);
|
||||
|
||||
// self.dynamic_state = DynamicState {
|
||||
// line_width: None,
|
||||
// viewports: self.dynamic_state.viewports.clone(),
|
||||
// scissors: None,
|
||||
// compare_mask: Some(StencilMask{ face: StencilFaceFlags::StencilFaceFrontBit, mask: 0xFF }),
|
||||
// };
|
||||
|
||||
let mut command_buffer = command_buffer.begin_render_pass(
|
||||
framebuffers[image_num].clone(), false, clear_values.clone(),
|
||||
).unwrap();
|
||||
|
||||
// Solid colors
|
||||
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.
|
||||
// But we can pass in multiple vertex buffers
|
||||
|
||||
if !self.colored_vertex_buffer.is_empty() {
|
||||
command_buffer = command_buffer.draw(
|
||||
shader.get_pipeline().clone(),
|
||||
&self.dynamic_state.clone(),
|
||||
self.colored_vertex_buffer.clone(),
|
||||
(), (),
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
// Images
|
||||
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() {
|
||||
for (image_handle, vertex_buffer) in self.image_vertex_buffer.clone() {
|
||||
let handle = image_handle.clone().handle as usize;
|
||||
let descriptor_set = self.image_buffers.get(handle).clone().unwrap().clone()
|
||||
.get_descriptor_set(shader.clone());
|
||||
|
||||
command_buffer = command_buffer.draw(
|
||||
shader.get_pipeline().clone(),
|
||||
// Multiple vertex buffers must have their definition in the pipeline!
|
||||
&self.dynamic_state.clone(), vec![vertex_buffer],
|
||||
vec![descriptor_set], (),
|
||||
).unwrap();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Textures
|
||||
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() {
|
||||
for (texture_handle, vertex_buffer) in self.textured_vertex_buffer.clone() {
|
||||
let handle = texture_handle.clone().handle as usize;
|
||||
let descriptor_set = self.texture_buffers.get(handle).clone().unwrap().clone()
|
||||
.get_descriptor_set(shader.clone(), self.sampler.clone());
|
||||
|
||||
command_buffer = command_buffer.draw(
|
||||
shader.get_pipeline().clone(),
|
||||
// Multiple vertex buffers must have their definition in the pipeline!
|
||||
&self.dynamic_state.clone(), vec![vertex_buffer],
|
||||
vec![descriptor_set], (),
|
||||
).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
command_buffer
|
||||
.end_render_pass()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user