Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- extern crate gfx_backend_vulkan as back;
- extern crate gfx_hal;
- extern crate glsl_to_spirv;
- extern crate winit;
- #[macro_use]
- extern crate memoffset;
- use std::io::Read;
- use std::mem;
- use std::path::Path;
- use gfx_hal::adapter::{MemoryType, MemoryTypeId, PhysicalDevice};
- use gfx_hal::command::{ClearColor, ClearValue, BufferCopy};
- use gfx_hal::format::{Aspects, ChannelType, Format, Swizzle};
- use gfx_hal::image::{Access, Extent, Layout, SubresourceRange, ViewKind};
- use gfx_hal::memory::Properties;
- use gfx_hal::pass::{
- Attachment, AttachmentLoadOp, AttachmentOps, AttachmentStoreOp, Subpass, SubpassDependency,
- SubpassDesc, SubpassRef,
- };
- use gfx_hal::pool::{CommandPool, CommandPoolCreateFlags};
- use gfx_hal::pso::{
- AttributeDesc, ColorBlendDesc, Element, EntryPoint, GraphicsPipelineDesc, GraphicsShaderSet,
- PipelineStage, Rasterizer, Rect, VertexBufferDesc, Viewport,
- };
- use gfx_hal::queue::submission::Submission;
- use gfx_hal::queue::CommandQueue;
- use gfx_hal::window::{Backbuffer, FrameSync, PresentMode, Swapchain, SwapchainConfig};
- use gfx_hal::{buffer, Backend, Device, Instance, Primitive, Surface, Graphics};
- use glsl_to_spirv::ShaderType;
- #[derive(Debug, Copy, Clone)]
- pub struct Vertex {
- pos: [f32; 2],
- color: [f32; 3],
- }
- impl Vertex {
- pub fn new(pos: [f32; 2], color: [f32; 3]) -> Vertex {
- Vertex { pos, color }
- }
- }
- fn main() {
- let instance = back::Instance::create("hell", 1);
- let mut adapters = instance.enumerate_adapters();
- println!("Extensions: {:?}", instance.extensions);
- println!("Adapters: ");
- for (i, adapter) in adapters.iter().enumerate() {
- println!(" {}: {:?}", i, adapter.info);
- }
- let mut adapter = adapters.remove(0);
- let memory_properties = adapter.physical_device.memory_properties();
- let memory_types = memory_properties.memory_types;
- let mut events_loop = winit::EventsLoop::new();
- let window = winit::WindowBuilder::new()
- .with_dimensions((800, 600).into())
- .with_resizable(false)
- .with_title("Hell")
- .build(&events_loop)
- .expect("Failed to create window");
- let mut surface = instance.create_surface(&window);
- let (device, mut queues) = adapter
- .open_with::<_, Graphics>(1, |f| surface.supports_queue_family(f))
- .expect("Failed to create logical device");
- let (caps, formats, _) = surface.compatibility(&adapter.physical_device);
- let formats = formats.unwrap_or(vec![Format::Rgba8Srgb]);
- let format = formats
- .iter()
- .find(|f| f.base_format().1 == ChannelType::Srgb)
- .cloned()
- .unwrap_or(formats[0]);
- let present_mode = PresentMode::Immediate;
- let mut swapchain_config = SwapchainConfig::from_caps(&caps, format);
- swapchain_config.present_mode = present_mode;
- let extent = swapchain_config.extent.to_extent();
- let (mut swapchain, mut backbuffer) = device
- .create_swapchain(&mut surface, swapchain_config, None)
- .expect("Failed to create swapchain");
- let attachment = Attachment {
- format: Some(format),
- samples: 1,
- ops: AttachmentOps::new(AttachmentLoadOp::Clear, AttachmentStoreOp::Store),
- stencil_ops: AttachmentOps::DONT_CARE,
- layouts: Layout::Undefined..Layout::Present,
- };
- let subpass_desc = SubpassDesc {
- colors: &[(0, Layout::ColorAttachmentOptimal)],
- depth_stencil: None,
- inputs: &[],
- resolves: &[],
- preserves: &[],
- };
- let dependency = SubpassDependency {
- passes: SubpassRef::External..SubpassRef::Pass(0),
- stages: PipelineStage::COLOR_ATTACHMENT_OUTPUT..PipelineStage::COLOR_ATTACHMENT_OUTPUT,
- accesses: Access::empty()..(Access::COLOR_ATTACHMENT_READ | Access::COLOR_ATTACHMENT_WRITE),
- };
- let render_pass = device
- .create_render_pass(&[attachment], &[subpass_desc], &[dependency])
- .expect("Failed to create render pass");
- let pipeline_layout = device
- .create_pipeline_layout(&[], &[])
- .expect("Failed to create pipeline layout");
- let vert_shader = load_shader::<back::Backend, _>(&device, "shader.vert", ShaderType::Vertex);
- let frag_shader = load_shader::<back::Backend, _>(&device, "shader.frag", ShaderType::Fragment);
- let pipeline = {
- let vert_entry = EntryPoint::<back::Backend> {
- entry: "main",
- module: &vert_shader,
- specialization: Default::default(),
- };
- let frag_entry = EntryPoint::<back::Backend> {
- entry: "main",
- module: &frag_shader,
- specialization: Default::default(),
- };
- let shader_set = GraphicsShaderSet {
- vertex: vert_entry,
- fragment: Some(frag_entry),
- hull: None,
- domain: None,
- geometry: None,
- };
- let subpass = Subpass {
- index: 0,
- main_pass: &render_pass,
- };
- let mut pipeline_desc = GraphicsPipelineDesc::new(
- shader_set,
- Primitive::TriangleList,
- Rasterizer::FILL,
- &pipeline_layout,
- subpass,
- );
- pipeline_desc.blender.targets.push(ColorBlendDesc::EMPTY);
- pipeline_desc.vertex_buffers.push(VertexBufferDesc {
- binding: 0,
- stride: mem::size_of::<Vertex>() as _,
- rate: 0,
- });
- pipeline_desc.attributes.push(AttributeDesc {
- location: 0,
- binding: 0,
- element: Element {
- format: Format::Rg32Float,
- offset: offset_of!(Vertex, pos) as _,
- },
- });
- pipeline_desc.attributes.push(AttributeDesc {
- location: 1,
- binding: 0,
- element: Element {
- format: Format::Rgb32Float,
- offset: offset_of!(Vertex, color) as _,
- },
- });
- let pipeline = device
- .create_graphics_pipeline(&pipeline_desc, None)
- .expect("Failed to create graphics pipeline");
- pipeline
- };
- device.destroy_shader_module(vert_shader);
- device.destroy_shader_module(frag_shader);
- let (mut frameviews, mut framebuffers) =
- expand_backbuffer(&device, backbuffer, format, &render_pass, extent);
- let mut command_pool = device
- .create_command_pool_typed(&queues, CommandPoolCreateFlags::empty(), 16)
- .expect("Failed to create command pool");
- let vertices = &[
- Vertex::new([-0.5, -0.5], [1.0, 0.0, 0.0]),
- Vertex::new([0.5, -0.5], [0.0, 1.0, 0.0]),
- Vertex::new([-0.5, 0.5], [0.0, 0.0, 1.0]),
- Vertex::new([-0.5, 0.5], [0.0, 0.0, 1.0]),
- Vertex::new([0.5, -0.5], [0.0, 1.0, 0.0]),
- Vertex::new([0.5, 0.5], [1.0, 1.0, 0.0]),
- ];
- let (vbuf, vbuf_memory) =
- create_vertex_buffer::<back::Backend, _>(&device, &memory_types, vertices, &mut command_pool, &mut queues.queues[0]);
- let mut viewport = Viewport {
- rect: Rect {
- x: 0,
- y: 0,
- w: extent.width as _,
- h: extent.height as _,
- },
- depth: 0.0..1.0,
- };
- let mut frame_semaphore = device
- .create_semaphore()
- .expect("Failed to create semaphore");
- let mut frame_fence = device.create_fence(false).expect("Failed to create fence");
- let mut running = true;
- let mut recreate_swapchain = false;
- let mut frames = 0;
- let mut instant = std::time::Instant::now();
- while running {
- events_loop.poll_events(|event| {
- if let winit::Event::WindowEvent { event, .. } = event {
- match event {
- winit::WindowEvent::CloseRequested => running = false,
- winit::WindowEvent::Resized(_) => recreate_swapchain = true,
- _ => {}
- }
- }
- });
- if recreate_swapchain {
- device.wait_idle().unwrap();
- let (caps, ..) = surface.compatibility(&mut adapter.physical_device);
- let mut swapchain_config = SwapchainConfig::from_caps(&caps, format);
- swapchain_config.present_mode = present_mode;
- let extent = swapchain_config.extent.to_extent();
- let (new_swapchain, new_backbuffer) = device
- .create_swapchain(&mut surface, swapchain_config, Some(swapchain))
- .expect("Failed to recreate swapchain");
- for framebuffer in framebuffers {
- device.destroy_framebuffer(framebuffer);
- }
- for view in frameviews {
- device.destroy_image_view(view);
- }
- swapchain = new_swapchain;
- backbuffer = new_backbuffer;
- let (new_frameviews, new_framebuffers) =
- expand_backbuffer(&device, backbuffer, format, &render_pass, extent);
- frameviews = new_frameviews;
- framebuffers = new_framebuffers;
- viewport.rect.w = extent.width as _;
- viewport.rect.h = extent.height as _;
- recreate_swapchain = false;
- }
- device.reset_fence(&frame_fence).unwrap();
- command_pool.reset();
- let frame = match swapchain.acquire_image(!0, FrameSync::Semaphore(&mut frame_semaphore)) {
- Ok(v) => v,
- Err(_) => {
- recreate_swapchain = true;
- continue;
- }
- };
- let mut command_buffer = command_pool.acquire_command_buffer(false);
- command_buffer.set_viewports(0, &[viewport.clone()]);
- command_buffer.set_scissors(0, &[viewport.rect]);
- command_buffer.bind_graphics_pipeline(&pipeline);
- command_buffer.bind_vertex_buffers(0, Some((&vbuf, 0)));
- {
- let mut encoder = command_buffer.begin_render_pass_inline(
- &render_pass,
- &framebuffers[frame as usize],
- viewport.rect,
- &[ClearValue::Color(ClearColor::Float([0.0, 0.0, 0.0, 1.0]))],
- );
- encoder.draw(0..6, 0..1);
- }
- let submit = command_buffer.finish();
- let submission = Submission::new()
- .wait_on(&[(&frame_semaphore, PipelineStage::BOTTOM_OF_PIPE)])
- .submit(Some(submit));
- queues.queues[0].submit(submission, Some(&mut frame_fence));
- device.wait_for_fence(&frame_fence, !0).unwrap();
- if swapchain.present(&mut queues.queues[0], frame, &[]).is_err() {
- recreate_swapchain = true;
- }
- frames += 1;
- if instant.elapsed() > std::time::Duration::from_secs(5) {
- let t = instant.elapsed();
- println!(
- "{} frames in {:?} @ {} fps",
- frames,
- t,
- frames as f32 / (t.as_secs() as f32 + t.subsec_nanos() as f32 / 1_000_000_000.0)
- );
- frames = 0;
- instant = std::time::Instant::now();
- }
- }
- device.wait_idle().unwrap();
- device.destroy_command_pool(command_pool.into_raw());
- for framebuffer in framebuffers {
- device.destroy_framebuffer(framebuffer);
- }
- for view in frameviews {
- device.destroy_image_view(view);
- }
- device.destroy_buffer(vbuf);
- device.free_memory(vbuf_memory);
- device.destroy_fence(frame_fence);
- device.destroy_semaphore(frame_semaphore);
- device.destroy_render_pass(render_pass);
- device.destroy_graphics_pipeline(pipeline);
- device.destroy_pipeline_layout(pipeline_layout);
- device.destroy_swapchain(swapchain);
- }
- fn expand_backbuffer<B: Backend>(
- device: &B::Device,
- backbuffer: Backbuffer<B>,
- format: Format,
- render_pass: &B::RenderPass,
- extent: Extent,
- ) -> (Vec<B::ImageView>, Vec<B::Framebuffer>) {
- match backbuffer {
- Backbuffer::Images(images) => {
- let range = SubresourceRange {
- aspects: Aspects::COLOR,
- levels: 0..1,
- layers: 0..1,
- };
- let views = images
- .iter()
- .map(|image| {
- device
- .create_image_view(&image, ViewKind::D2, format, Swizzle::NO, range.clone())
- .expect("Failed to create image view")
- })
- .collect::<Vec<_>>();
- let framebuffers = views
- .iter()
- .map(|view| {
- device
- .create_framebuffer(&render_pass, Some(view), extent)
- .expect("Failed to create framebuffer")
- })
- .collect::<Vec<_>>();
- (views, framebuffers)
- }
- Backbuffer::Framebuffer(framebuffer) => (vec![], vec![framebuffer]),
- }
- }
- fn load_shader<B: Backend, P: AsRef<Path>>(
- device: &B::Device,
- path: P,
- ty: ShaderType,
- ) -> B::ShaderModule {
- let source = std::fs::read_to_string(path).expect("Failed to read shader source");
- let code = glsl_to_spirv::compile(&source, ty)
- .expect("Failed to compile shader")
- .bytes()
- .map(|b| b.unwrap())
- .collect::<Vec<_>>();
- device
- .create_shader_module(&code)
- .expect("Failed to create shader module")
- }
- fn select_heap(types: &[MemoryType], mask: u64, props: Properties) -> MemoryTypeId {
- types
- .iter()
- .enumerate()
- .position(|(id, ty)| mask & (1 << id) != 0 && ty.properties.contains(props))
- .expect("No suitable memory heap")
- .into()
- }
- fn create_buffer<B: Backend>(
- device: &B::Device,
- types: &[MemoryType],
- size: u64,
- usage: buffer::Usage,
- props: Properties,
- ) -> (B::Buffer, B::Memory) {
- let unbounded = device
- .create_buffer(size, usage)
- .expect("Failed to create vertex buffer");
- let req = device.get_buffer_requirements(&unbounded);
- let heap = select_heap(&types, req.type_mask, props);
- let memory = device
- .allocate_memory(heap, req.size)
- .expect("Failed to allocate memory");
- let buffer = device
- .bind_buffer_memory(&memory, 0, unbounded)
- .expect("Failed to bind memory");
- (buffer, memory)
- }
- fn create_vertex_buffer<B: Backend, V: Copy>(
- device: &B::Device,
- types: &[MemoryType],
- vertices: &[V],
- command_pool: &mut CommandPool<B, Graphics>,
- queue: &mut CommandQueue<B, Graphics>
- ) -> (B::Buffer, B::Memory) {
- use buffer::Usage;
- let len = (vertices.len() * mem::size_of::<V>()) as _;
- let (vertex_buffer, vertex_memory) =
- create_buffer::<B>(device, types, len, Usage::VERTEX, Properties::DEVICE_LOCAL);
- let (staging_buffer, staging_memory) =
- create_buffer::<B>(device, types, len, Usage::VERTEX, Properties::CPU_VISIBLE);
- {
- let mut writer = device
- .acquire_mapping_writer(&staging_memory, 0..len)
- .expect("Failed to map memory for writing");
- writer.copy_from_slice(vertices);
- device.release_mapping_writer(writer).unwrap();
- }
- let mut command_buffer = command_pool.acquire_command_buffer(false);
- command_buffer.copy_buffer(
- &staging_buffer,
- &vertex_buffer,
- Some(BufferCopy {
- src: 0,
- dst: 0,
- size: len
- })
- );
- let submit = command_buffer.finish();
- let submission = Submission::new()
- .submit(Some(submit));
- queue.submit(submission, None);
- device.wait_idle().unwrap();
- device.destroy_buffer(staging_buffer);
- device.free_memory(staging_memory);
- (vertex_buffer, vertex_memory)
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement