mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-21 14:24:18 +00:00
Fix examples so that cargo test works
This commit is contained in:
parent
68cc6057c9
commit
3a6ff66200
@ -15,7 +15,7 @@ job1:
|
||||
script:
|
||||
- cargo test -v --manifest-path glsl-to-spirv/Cargo.toml
|
||||
- cargo test -v --manifest-path vulkano-shaders/Cargo.toml
|
||||
- cargo build -v --manifest-path vulkano/Cargo.toml
|
||||
- cargo test --no-run -v --manifest-path vulkano/Cargo.toml
|
||||
|
||||
pages:
|
||||
stage: deploy
|
||||
|
@ -21,7 +21,7 @@ addons:
|
||||
script:
|
||||
- cargo test -v --manifest-path glsl-to-spirv/Cargo.toml
|
||||
- cargo test -v --manifest-path vulkano-shaders/Cargo.toml
|
||||
- cargo build -v --manifest-path vulkano/Cargo.toml # TODO: should be "cargo test --no-run"
|
||||
- cargo test --no-run -v --manifest-path vulkano/Cargo.toml
|
||||
|
||||
after_success:
|
||||
- |
|
||||
|
@ -1,65 +0,0 @@
|
||||
// Copyright (c) 2016 The vulkano developers
|
||||
// Licensed under the Apache License, Version 2.0
|
||||
// <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
|
||||
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
|
||||
// at your option. All files in the project carrying such
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate vulkano;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
fn main() {
|
||||
let app = vulkano::instance::ApplicationInfo { application_name: "test", application_version: 1, engine_name: "test", engine_version: 1 };
|
||||
let instance = vulkano::instance::Instance::new(Some(&app), None).expect("failed to create instance");
|
||||
|
||||
let physical = vulkano::instance::PhysicalDevice::enumerate(&instance)
|
||||
.next().expect("no device available");
|
||||
println!("Using device: {} (type: {:?})", physical.name(), physical.ty());
|
||||
|
||||
let queue = physical.queue_families().find(|q| q.supports_transfers())
|
||||
.expect("couldn't find a graphical queue family");
|
||||
|
||||
|
||||
let (device, queues) = vulkano::device::Device::new(&physical, physical.supported_features(),
|
||||
[(queue, 0.5)].iter().cloned(), &[])
|
||||
.expect("failed to create device");
|
||||
let queue = queues.into_iter().next().unwrap();
|
||||
|
||||
|
||||
|
||||
let src: Arc<vulkano::buffer::Buffer<[u8; 16], _>> =
|
||||
vulkano::buffer::Buffer::new(&device, &vulkano::buffer::Usage::all(),
|
||||
vulkano::memory::HostVisible, &queue)
|
||||
.expect("failed to create buffer");
|
||||
|
||||
{
|
||||
let mut mapping = src.try_write().unwrap();
|
||||
for (v, o) in mapping.iter_mut().enumerate() { *o = v as u8; }
|
||||
}
|
||||
|
||||
let dest: Arc<vulkano::buffer::Buffer<[u8; 16], _>> =
|
||||
vulkano::buffer::Buffer::new(&device, &vulkano::buffer::Usage::all(),
|
||||
vulkano::memory::HostVisible, &queue)
|
||||
.expect("failed to create buffer");
|
||||
|
||||
let cb_pool = vulkano::command_buffer::CommandBufferPool::new(&device, &queue.lock().unwrap().family())
|
||||
.expect("failed to create command buffer pool");
|
||||
|
||||
let command_buffer = vulkano::command_buffer::PrimaryCommandBufferBuilder::new(&cb_pool).unwrap()
|
||||
.copy_buffer(&src, &dest)
|
||||
.build().unwrap();
|
||||
|
||||
{
|
||||
let mut queue = queue.lock().unwrap();
|
||||
command_buffer.submit(&mut queue).unwrap();
|
||||
}
|
||||
|
||||
{
|
||||
let mut mapping = dest.read(1000000000);
|
||||
for (v, o) in mapping.iter_mut().enumerate() { assert_eq!(*o, v as u8); }
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@ use std::ffi::OsStr;
|
||||
use std::os::windows::ffi::OsStrExt;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::time::Duration;
|
||||
|
||||
fn main() {
|
||||
// The start of this example is exactly the same as `triangle`. You should read the
|
||||
@ -70,8 +71,7 @@ fn main() {
|
||||
};
|
||||
|
||||
|
||||
let cb_pool = vulkano::command_buffer::CommandBufferPool::new(&device, &queue.family())
|
||||
.expect("failed to create command buffer pool");
|
||||
let cb_pool = vulkano::command_buffer::CommandBufferPool::new(&device, &queue.family());
|
||||
|
||||
|
||||
|
||||
@ -89,7 +89,7 @@ fn main() {
|
||||
{
|
||||
// The `write` function would return `Err` if the buffer was in use by the GPU. This
|
||||
// obviously can't happen here, since we haven't ask the GPU to do anything yet.
|
||||
let mut mapping = vertex_buffer.write(0).unwrap();
|
||||
let mut mapping = vertex_buffer.write(Duration::new(0, 0)).unwrap();
|
||||
mapping[0].position = [-0.5, -0.5];
|
||||
mapping[1].position = [-0.5, 0.5];
|
||||
mapping[2].position = [ 0.5, -0.5];
|
||||
@ -108,7 +108,7 @@ fn main() {
|
||||
color: {
|
||||
load: Clear,
|
||||
store: Store,
|
||||
format: B8G8R8A8Srgb,
|
||||
format: ::vulkano::format::B8G8R8A8Srgb,
|
||||
}
|
||||
},
|
||||
pass: {
|
||||
@ -118,7 +118,9 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
let renderpass = renderpass::CustomRenderPass::new(&device).unwrap();
|
||||
let renderpass = renderpass::CustomRenderPass::new(&device, &renderpass::Formats {
|
||||
color: (vulkano::format::B8G8R8A8Srgb, 1)
|
||||
});
|
||||
|
||||
let texture = vulkano::image::immutable::ImmutableImage::new(&device, vulkano::image::sys::Dimensions::Dim2d { width: 93, height: 93 },
|
||||
vulkano::format::R8G8B8A8Unorm, Some(queue.family())).unwrap();
|
||||
@ -135,7 +137,7 @@ fn main() {
|
||||
Some(queue.family())).expect("failed to create buffer");
|
||||
|
||||
{
|
||||
let mut mapping = pixel_buffer.write(0).unwrap();
|
||||
let mut mapping = pixel_buffer.write(Duration::new(0, 0)).unwrap();
|
||||
for (o, i) in mapping.iter_mut().zip(image_data.chunks(4)) {
|
||||
o[0] = i[0];
|
||||
o[1] = i[1];
|
||||
@ -155,7 +157,7 @@ fn main() {
|
||||
vulkano::sampler::SamplerAddressMode::Repeat,
|
||||
0.0, 1.0, 0.0, 0.0).unwrap();
|
||||
|
||||
let descriptor_pool = vulkano::descriptor::descriptor_set::DescriptorPool::new(&device).unwrap();
|
||||
let descriptor_pool = vulkano::descriptor::descriptor_set::DescriptorPool::new(&device);
|
||||
mod pipeline_layout {
|
||||
pipeline_layout!{
|
||||
set0: {
|
||||
@ -167,41 +169,35 @@ fn main() {
|
||||
let pipeline_layout = pipeline_layout::CustomPipeline::new(&device).unwrap();
|
||||
let set = pipeline_layout::set0::Set::new(&descriptor_pool, &pipeline_layout, &pipeline_layout::set0::Descriptors {
|
||||
tex: (&sampler, &texture)
|
||||
}).unwrap();
|
||||
});
|
||||
|
||||
let pipeline = {
|
||||
let ia = vulkano::pipeline::input_assembly::InputAssembly {
|
||||
|
||||
let pipeline = vulkano::pipeline::GraphicsPipeline::new(&device, vulkano::pipeline::GraphicsPipelineParams {
|
||||
vertex_input: vulkano::pipeline::vertex::SingleBufferDefinition::new(),
|
||||
vertex_shader: vs.main_entry_point(),
|
||||
input_assembly: vulkano::pipeline::input_assembly::InputAssembly {
|
||||
topology: vulkano::pipeline::input_assembly::PrimitiveTopology::TriangleStrip,
|
||||
primitive_restart_enable: false,
|
||||
};
|
||||
|
||||
let raster = Default::default();
|
||||
let ms = vulkano::pipeline::multisample::Multisample::disabled();
|
||||
let blend = vulkano::pipeline::blend::Blend {
|
||||
logic_op: None,
|
||||
blend_constants: Some([0.0; 4]),
|
||||
};
|
||||
|
||||
let viewports = vulkano::pipeline::viewport::ViewportsState::Fixed {
|
||||
},
|
||||
geometry_shader: None,
|
||||
viewport: vulkano::pipeline::viewport::ViewportsState::Fixed {
|
||||
data: vec![(
|
||||
vulkano::pipeline::viewport::Viewport {
|
||||
origin: [0.0, 0.0],
|
||||
dimensions: [1244.0, 699.0],
|
||||
depth_range: 0.0 .. 1.0
|
||||
depth_range: 0.0 .. 1.0,
|
||||
dimensions: [images[0].dimensions()[0] as f32, images[0].dimensions()[1] as f32],
|
||||
},
|
||||
vulkano::pipeline::viewport::Scissor {
|
||||
origin: [0, 0],
|
||||
dimensions: [1244, 699],
|
||||
}
|
||||
vulkano::pipeline::viewport::Scissor::irrelevant()
|
||||
)],
|
||||
};
|
||||
|
||||
vulkano::pipeline::GraphicsPipeline::new(&device, vulkano::pipeline::vertex::SingleBufferDefinition::new(),
|
||||
&vs.main_entry_point(), &ia, &viewports,
|
||||
&raster, &ms, &blend, &fs.main_entry_point(),
|
||||
&pipeline_layout, vulkano::framebuffer::Subpass::from(&renderpass, 0).unwrap())
|
||||
.unwrap()
|
||||
};
|
||||
},
|
||||
raster: Default::default(),
|
||||
multisample: vulkano::pipeline::multisample::Multisample::disabled(),
|
||||
fragment_shader: fs.main_entry_point(),
|
||||
depth_stencil: vulkano::pipeline::depth_stencil::DepthStencil::simple_depth_test(),
|
||||
blend: vulkano::pipeline::blend::Blend::pass_through(),
|
||||
layout: &pipeline_layout,
|
||||
render_pass: vulkano::framebuffer::Subpass::from(&renderpass, 0).unwrap(),
|
||||
}).unwrap();
|
||||
|
||||
let framebuffers = images.iter().map(|image| {
|
||||
let attachments = renderpass::AList {
|
||||
@ -213,20 +209,21 @@ fn main() {
|
||||
|
||||
|
||||
let command_buffers = framebuffers.iter().map(|framebuffer| {
|
||||
vulkano::command_buffer::PrimaryCommandBufferBuilder::new(&cb_pool).unwrap()
|
||||
vulkano::command_buffer::PrimaryCommandBufferBuilder::new(&cb_pool)
|
||||
.copy_buffer_to_color_image(&pixel_buffer, &texture, 0, 0 .. 1, [0, 0, 0],
|
||||
[texture.dimensions().width(), texture.dimensions().height(), 1])
|
||||
//.clear_color_image(&texture, [0.0, 1.0, 0.0, 1.0])
|
||||
.draw_inline(&renderpass, &framebuffer, renderpass::ClearValues {
|
||||
color: [0.0, 0.0, 1.0, 1.0]
|
||||
})
|
||||
.draw(&pipeline, &vertex_buffer, &vulkano::command_buffer::DynamicState::none(), set.clone(), &())
|
||||
.draw(&pipeline, &vertex_buffer, &vulkano::command_buffer::DynamicState::none(),
|
||||
&set, &())
|
||||
.draw_end()
|
||||
.build().unwrap()
|
||||
.build()
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
loop {
|
||||
let image_num = swapchain.acquire_next_image(1000000).unwrap();
|
||||
let image_num = swapchain.acquire_next_image(Duration::new(10, 0)).unwrap();
|
||||
vulkano::command_buffer::submit(&command_buffers[image_num], &queue).unwrap();
|
||||
swapchain.present(&queue, image_num).unwrap();
|
||||
|
||||
|
@ -19,6 +19,7 @@ use std::ffi::OsStr;
|
||||
use std::os::windows::ffi::OsStrExt;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::time::Duration;
|
||||
|
||||
fn main() {
|
||||
// The first step of any vulkan program is to create an instance.
|
||||
@ -26,11 +27,10 @@ fn main() {
|
||||
let app = vulkano::instance::ApplicationInfo { application_name: "test", application_version: 1, engine_name: "test", engine_version: 1 };
|
||||
let extensions = vulkano::instance::InstanceExtensions {
|
||||
khr_surface: true,
|
||||
khr_swapchain: true,
|
||||
khr_win32_surface: true,
|
||||
.. vulkano::instance::InstanceExtensions::none()
|
||||
};
|
||||
let instance = vulkano::instance::Instance::new(Some(&app), &["VK_LAYER_LUNARG_draw_state"], &extensions).expect("failed to create instance");
|
||||
let instance = vulkano::instance::Instance::new(Some(&app), &extensions, None).expect("failed to create instance");
|
||||
|
||||
// We then choose which physical device to use.
|
||||
//
|
||||
@ -74,9 +74,12 @@ fn main() {
|
||||
// We also have to pass a list of queues to create and their priorities relative to each other.
|
||||
// Since we create one queue, we don't really care about the priority and just pass `0.5`.
|
||||
// The list of created queues is returned by the function alongside with the device.
|
||||
let device_ext = vulkano::device::DeviceExtensions {
|
||||
khr_swapchain: true,
|
||||
.. vulkano::device::DeviceExtensions::none()
|
||||
};
|
||||
let (device, queues) = vulkano::device::Device::new(&physical, physical.supported_features(),
|
||||
[(queue, 0.5)].iter().cloned(),
|
||||
&["VK_LAYER_LUNARG_draw_state"])
|
||||
&device_ext, None, [(queue, 0.5)].iter().cloned())
|
||||
.expect("failed to create device");
|
||||
|
||||
// Since we can request multiple queues, the `queues` variable is a `Vec`. Our actual queue
|
||||
@ -114,9 +117,8 @@ fn main() {
|
||||
// the CPU and one buffer on the GPU. We then write our data to the buffer on the CPU and
|
||||
// ask the GPU to copy it to the real buffer. This way the data is located on the most
|
||||
// efficient memory possible.
|
||||
let vertex_buffer = vulkano::buffer::Buffer::<[Vertex; 3], _>
|
||||
::new(&device, &vulkano::buffer::Usage::all(),
|
||||
vulkano::memory::HostVisible, &queue)
|
||||
let vertex_buffer = vulkano::buffer::cpu_access::CpuAccessibleBuffer::<[Vertex], _>
|
||||
::array(&device, 3, &vulkano::buffer::Usage::all(), Some(queue.family()))
|
||||
.expect("failed to create buffer");
|
||||
struct Vertex { position: [f32; 2] }
|
||||
impl_vertex!(Vertex, position);
|
||||
@ -126,7 +128,7 @@ fn main() {
|
||||
{
|
||||
// The `write` function would return `Err` if the buffer was in use by the GPU. This
|
||||
// obviously can't happen here, since we haven't ask the GPU to do anything yet.
|
||||
let mut mapping = vertex_buffer.write(0).unwrap();
|
||||
let mut mapping = vertex_buffer.write(Duration::new(0, 0)).unwrap();
|
||||
mapping[0].position = [-0.5, -0.25];
|
||||
mapping[1].position = [0.0, 0.5];
|
||||
mapping[2].position = [0.25, -0.1];
|
||||
@ -155,16 +157,7 @@ fn main() {
|
||||
|
||||
// We are going to create a command buffer below. Command buffers need to be allocated
|
||||
// from a *command buffer pool*, so we create the pool.
|
||||
let cb_pool = vulkano::command_buffer::CommandBufferPool::new(&device, &queue.family())
|
||||
.expect("failed to create command buffer pool");
|
||||
|
||||
// We are going to draw on the images returned when creating the swapchain. To do so, we must
|
||||
// convert them into *image views*. TODO: explain more
|
||||
let images = images.into_iter().map(|image| {
|
||||
let image = image.transition(vulkano::image::Layout::PresentSrc, &cb_pool,
|
||||
&queue).unwrap();
|
||||
vulkano::image::ImageView::new(&image).expect("failed to create image view")
|
||||
}).collect::<Vec<_>>();
|
||||
let cb_pool = vulkano::command_buffer::CommandBufferPool::new(&device, &queue.family());
|
||||
|
||||
// The next step is to create a *renderpass*, which is an object that describes where the
|
||||
// output of the graphics pipeline will go. It describes the layout of the images
|
||||
@ -175,7 +168,7 @@ fn main() {
|
||||
color: {
|
||||
load: Clear,
|
||||
store: Store,
|
||||
format: B8G8R8A8Srgb,
|
||||
format: ::vulkano::format::B8G8R8A8Srgb,
|
||||
}
|
||||
},
|
||||
pass: {
|
||||
@ -185,36 +178,33 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
let renderpass = renderpass::CustomRenderPass::new(&device).unwrap();
|
||||
let renderpass = renderpass::CustomRenderPass::new(&device, &renderpass::Formats {
|
||||
color: (vulkano::format::B8G8R8A8Srgb, 1)
|
||||
});
|
||||
|
||||
let pipeline = {
|
||||
let ia = vulkano::pipeline::input_assembly::InputAssembly::triangle_list();
|
||||
let raster = Default::default();
|
||||
let ms = vulkano::pipeline::multisample::Multisample::disabled();
|
||||
let blend = vulkano::pipeline::blend::Blend {
|
||||
logic_op: None,
|
||||
blend_constants: Some([0.0; 4]),
|
||||
};
|
||||
|
||||
let viewports = vulkano::pipeline::viewport::ViewportsState::Fixed {
|
||||
let pipeline = vulkano::pipeline::GraphicsPipeline::new(&device, vulkano::pipeline::GraphicsPipelineParams {
|
||||
vertex_input: vulkano::pipeline::vertex::SingleBufferDefinition::new(),
|
||||
vertex_shader: vs.main_entry_point(),
|
||||
input_assembly: vulkano::pipeline::input_assembly::InputAssembly::triangle_list(),
|
||||
geometry_shader: None,
|
||||
viewport: vulkano::pipeline::viewport::ViewportsState::Fixed {
|
||||
data: vec![(
|
||||
vulkano::pipeline::viewport::Viewport {
|
||||
origin: [0.0, 0.0],
|
||||
dimensions: [1244.0, 699.0],
|
||||
depth_range: 0.0 .. 1.0
|
||||
depth_range: 0.0 .. 1.0,
|
||||
dimensions: [images[0].dimensions()[0] as f32, images[0].dimensions()[1] as f32],
|
||||
},
|
||||
vulkano::pipeline::viewport::Scissor {
|
||||
origin: [0, 0],
|
||||
dimensions: [1244, 699],
|
||||
}
|
||||
vulkano::pipeline::viewport::Scissor::irrelevant()
|
||||
)],
|
||||
};
|
||||
|
||||
vulkano::pipeline::GraphicsPipeline::new(&device, &vs.main_entry_point(), &ia, &viewports,
|
||||
&raster, &ms, &blend, &fs.main_entry_point(),
|
||||
&vulkano::descriptor_set::PipelineLayout::new(&device, vulkano::descriptor_set::EmptyPipelineDesc, ()).unwrap(),
|
||||
renderpass.subpass(0).unwrap()).unwrap()
|
||||
};
|
||||
},
|
||||
raster: Default::default(),
|
||||
multisample: vulkano::pipeline::multisample::Multisample::disabled(),
|
||||
fragment_shader: fs.main_entry_point(),
|
||||
depth_stencil: vulkano::pipeline::depth_stencil::DepthStencil::simple_depth_test(),
|
||||
blend: vulkano::pipeline::blend::Blend::pass_through(),
|
||||
layout: &vulkano::descriptor::pipeline_layout::EmptyPipeline::new(&device).unwrap(),
|
||||
render_pass: vulkano::framebuffer::Subpass::from(&renderpass, 0).unwrap(),
|
||||
}).unwrap();
|
||||
|
||||
// The renderpass we created above only describes the layout of our framebuffers. We also need
|
||||
// to create the actual framebuffers.
|
||||
@ -222,7 +212,9 @@ fn main() {
|
||||
// Since we need to draw to multiple images, we are going to create a different framebuffer for
|
||||
// each image.
|
||||
let framebuffers = images.iter().map(|image| {
|
||||
vulkano::framebuffer::Framebuffer::new(&renderpass, (1244, 699, 1), (image.clone() as Arc<_>,)).unwrap()
|
||||
vulkano::framebuffer::Framebuffer::new(&renderpass, (1244, 699, 1), renderpass::AList {
|
||||
color: image
|
||||
}).unwrap()
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
// The final initialization step is to create a command buffer.
|
||||
@ -235,11 +227,11 @@ fn main() {
|
||||
// Since we have several images to draw on, we are also going to create one command buffer for
|
||||
// each image.
|
||||
let command_buffers = framebuffers.iter().map(|framebuffer| {
|
||||
vulkano::command_buffer::PrimaryCommandBufferBuilder::new(&cb_pool).unwrap()
|
||||
.draw_inline(&renderpass, &framebuffer, ([0.0, 0.0, 1.0, 1.0],))
|
||||
.draw(&pipeline, vertex_buffer.clone(), &vulkano::command_buffer::DynamicState::none(), (), &())
|
||||
vulkano::command_buffer::PrimaryCommandBufferBuilder::new(&cb_pool)
|
||||
.draw_inline(&renderpass, &framebuffer, renderpass::ClearValues { color: [0.0, 0.0, 1.0, 1.0] })
|
||||
.draw(&pipeline, &vertex_buffer, &vulkano::command_buffer::DynamicState::none(), (), &())
|
||||
.draw_end()
|
||||
.build().unwrap()
|
||||
.build()
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
// Initialization is finally finished!
|
||||
@ -248,14 +240,14 @@ fn main() {
|
||||
// Everything else is kept alive internally with `Arc`s (even the vertex buffer for example),
|
||||
// so the only variable that we need is this one.
|
||||
|
||||
let mut submissions: Vec<vulkano::command_buffer::Submission> = Vec::new();
|
||||
let mut submissions: Vec<Arc<vulkano::command_buffer::Submission>> = Vec::new();
|
||||
|
||||
loop {
|
||||
submissions.retain(|s| !s.destroying_would_block());
|
||||
|
||||
// Before we can draw on the output, we have to *acquire* an image from the swapchain.
|
||||
// This operation returns the index of the image that we are allowed to draw upon..
|
||||
let image_num = swapchain.acquire_next_image(1000000).unwrap();
|
||||
let image_num = swapchain.acquire_next_image(Duration::new(1, 0)).unwrap();
|
||||
|
||||
// In order to draw, all we need to do is submit the command buffer to the queue.
|
||||
submissions.push(vulkano::command_buffer::submit(&command_buffers[image_num], &queue).unwrap());
|
||||
|
@ -53,7 +53,7 @@
|
||||
//! use vulkano::framebuffer::EmptySinglePassRenderPass;
|
||||
//!
|
||||
//! # let device: std::sync::Arc<vulkano::device::Device> = unsafe { ::std::mem::uninitialized() };
|
||||
//! let renderpass = EmptySinglePassRenderPass::new(&device).unwrap();
|
||||
//! let renderpass = EmptySinglePassRenderPass::new(&device);
|
||||
//! ```
|
||||
//!
|
||||
//! # Framebuffers
|
||||
|
@ -27,7 +27,7 @@
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! ```ignore // TODO:
|
||||
//! # #[macro_use] extern crate vulkano
|
||||
//! # fn main() {
|
||||
//! # use std::sync::Arc;
|
||||
|
Loading…
Reference in New Issue
Block a user