Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor triangle and texture examples to use better practices #356

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ authors = ["maik klein <maikklein@googlemail.com>"]
edition = "2018"

[dependencies]
winit = "0.19.5"
winit = "0.24.0"
image = "0.10.4"
ash = { path = "../ash" }
ash-window = { path = "../ash-window" }
320 changes: 109 additions & 211 deletions examples/src/bin/texture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,18 @@ use std::os::raw::c_void;
use ash::util::*;
use ash::vk;

use winit::{
dpi::{LogicalSize, PhysicalSize},
event::{Event, KeyboardInput, VirtualKeyCode, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder
};

use examples::*;

const APP_NAME: &str = "Ash - Example";
const WINDOW_SIZE: [u32; 2] = [1024, 792];

#[derive(Clone, Debug, Copy)]
struct Vertex {
pos: [f32; 4],
Expand All @@ -25,76 +35,30 @@ pub struct Vector3 {

fn main() {
unsafe {
let base = ExampleBase::new(1920, 1080);

let renderpass_attachments = [
vk::AttachmentDescription {
format: base.surface_format.format,
samples: vk::SampleCountFlags::TYPE_1,
load_op: vk::AttachmentLoadOp::CLEAR,
store_op: vk::AttachmentStoreOp::STORE,
final_layout: vk::ImageLayout::PRESENT_SRC_KHR,
..Default::default()
},
vk::AttachmentDescription {
format: vk::Format::D16_UNORM,
samples: vk::SampleCountFlags::TYPE_1,
load_op: vk::AttachmentLoadOp::CLEAR,
initial_layout: vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
final_layout: vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
..Default::default()
},
];
let color_attachment_refs = [vk::AttachmentReference {
attachment: 0,
layout: vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
}];
let depth_attachment_ref = vk::AttachmentReference {
attachment: 1,
layout: vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
};
let dependencies = [vk::SubpassDependency {
src_subpass: vk::SUBPASS_EXTERNAL,
src_stage_mask: vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT,
dst_access_mask: vk::AccessFlags::COLOR_ATTACHMENT_READ
| vk::AccessFlags::COLOR_ATTACHMENT_WRITE,
dst_stage_mask: vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT,
..Default::default()
}];

let subpasses = [vk::SubpassDescription::builder()
.color_attachments(&color_attachment_refs)
.depth_stencil_attachment(&depth_attachment_ref)
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS)
.build()];
let event_loop = EventLoop::new();
let (logical_window_size, physical_window_size) = {
let dpi = event_loop.primary_monitor().unwrap().scale_factor();
let logical: LogicalSize<u32> = WINDOW_SIZE.into();
let physical: PhysicalSize<u32> = logical.to_physical(dpi);

let renderpass_create_info = vk::RenderPassCreateInfo::builder()
.attachments(&renderpass_attachments)
.subpasses(&subpasses)
.dependencies(&dependencies);
(logical, physical)
};

let renderpass = base
.device
.create_render_pass(&renderpass_create_info, None)
.unwrap();
let surface_resolution = vk::Extent2D {
width: physical_window_size.width,
height: physical_window_size.height,
};
let window = WindowBuilder::new()
.with_title(APP_NAME)
.with_inner_size(logical_window_size)
.build(&event_loop)
.expect("Failed to create window");

let mut base = ExampleBase::new(
&window,
surface_resolution
);

let framebuffers: Vec<vk::Framebuffer> = base
.present_image_views
.iter()
.map(|&present_image_view| {
let framebuffer_attachments = [present_image_view, base.depth_image_view];
let frame_buffer_create_info = vk::FramebufferCreateInfo::builder()
.render_pass(renderpass)
.attachments(&framebuffer_attachments)
.width(base.surface_resolution.width)
.height(base.surface_resolution.height)
.layers(1);

base.device
.create_framebuffer(&frame_buffer_create_info, None)
.unwrap()
})
.collect();
let index_buffer_data = [0u32, 1, 2, 2, 3, 0];
let index_buffer_info = vk::BufferCreateInfo {
size: std::mem::size_of_val(&index_buffer_data) as u64,
Expand Down Expand Up @@ -575,7 +539,7 @@ fn main() {
.unwrap();

let shader_entry_name = CString::new("main").unwrap();
let shader_stage_create_infos = [
let shader_stage_create_info = [
vk::PipelineShaderStageCreateInfo {
module: vertex_shader_module,
p_name: shader_entry_name.as_ptr(),
Expand Down Expand Up @@ -616,20 +580,9 @@ fn main() {
topology: vk::PrimitiveTopology::TRIANGLE_LIST,
..Default::default()
};
let viewports = [vk::Viewport {
x: 0.0,
y: 0.0,
width: base.surface_resolution.width as f32,
height: base.surface_resolution.height as f32,
min_depth: 0.0,
max_depth: 1.0,
}];
let scissors = [vk::Rect2D {
extent: base.surface_resolution,
..Default::default()
}];
let viewports = [base.viewports];
let viewport_state_info = vk::PipelineViewportStateCreateInfo::builder()
.scissors(&scissors)
.scissors(&base.scissors)
.viewports(&viewports);

let rasterization_info = vk::PipelineRasterizationStateCreateInfo {
Expand Down Expand Up @@ -677,8 +630,8 @@ fn main() {
let dynamic_state_info =
vk::PipelineDynamicStateCreateInfo::builder().dynamic_states(&dynamic_state);

let graphic_pipeline_infos = vk::GraphicsPipelineCreateInfo::builder()
.stages(&shader_stage_create_infos)
let graphics_pipeline_info = vk::GraphicsPipelineCreateInfo::builder()
.stages(&shader_stage_create_info)
.vertex_input_state(&vertex_input_state_info)
.input_assembly_state(&vertex_input_assembly_state_info)
.viewport_state(&viewport_state_info)
Expand All @@ -688,149 +641,94 @@ fn main() {
.color_blend_state(&color_blend_state)
.dynamic_state(&dynamic_state_info)
.layout(pipeline_layout)
.render_pass(renderpass);
.render_pass(base.renderpass);

let graphics_pipelines = base
.device
.create_graphics_pipelines(
vk::PipelineCache::null(),
&[graphic_pipeline_infos.build()],
&[graphics_pipeline_info.build()],
None,
)
.unwrap();

let graphic_pipeline = graphics_pipelines[0];

base.render_loop(|| {
let (present_index, _) = base
.swapchain_loader
.acquire_next_image(
base.swapchain,
std::u64::MAX,
base.present_complete_semaphore,
vk::Fence::null(),
)
.unwrap();
let clear_values = [
vk::ClearValue {
color: vk::ClearColorValue {
float32: [0.0, 0.0, 0.0, 0.0],
let graphics_pipeline = graphics_pipelines[0];

event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
match event {
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => {
*control_flow = ControlFlow::Exit;
},
},
vk::ClearValue {
depth_stencil: vk::ClearDepthStencilValue {
depth: 1.0,
stencil: 0,
WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(VirtualKeyCode::Escape),
..
},
..
} => {
*control_flow = ControlFlow::Exit
},
WindowEvent::Resized(dimensions) => {
base.screen_resolution = vk::Extent2D {
width: dimensions.width,
height: dimensions.height
};

base.recreate_swapchain();
},
_ => (),
},
];

let render_pass_begin_info = vk::RenderPassBeginInfo::builder()
.render_pass(renderpass)
.framebuffer(framebuffers[present_index as usize])
.render_area(vk::Rect2D {
offset: vk::Offset2D { x: 0, y: 0 },
extent: base.surface_resolution,
})
.clear_values(&clear_values);

record_submit_commandbuffer(
&base.device,
base.draw_command_buffer,
base.draw_commands_reuse_fence,
base.present_queue,
&[vk::PipelineStageFlags::BOTTOM_OF_PIPE],
&[base.present_complete_semaphore],
&[base.rendering_complete_semaphore],
|device, draw_command_buffer| {
device.cmd_begin_render_pass(
draw_command_buffer,
&render_pass_begin_info,
vk::SubpassContents::INLINE,
);
device.cmd_bind_descriptor_sets(
draw_command_buffer,
vk::PipelineBindPoint::GRAPHICS,
pipeline_layout,
0,
&descriptor_sets[..],
&[],
);
device.cmd_bind_pipeline(
draw_command_buffer,
vk::PipelineBindPoint::GRAPHICS,
graphic_pipeline,
);
device.cmd_set_viewport(draw_command_buffer, 0, &viewports);
device.cmd_set_scissor(draw_command_buffer, 0, &scissors);
device.cmd_bind_vertex_buffers(
draw_command_buffer,
0,
&[vertex_input_buffer],
&[0],
);
device.cmd_bind_index_buffer(
draw_command_buffer,
Event::MainEventsCleared => {
base.render_texture(
&descriptor_sets,
graphics_pipeline,
index_buffer,
0,
vk::IndexType::UINT32,
);
device.cmd_draw_indexed(
draw_command_buffer,
index_buffer_data.len() as u32,
1,
0,
0,
1,
index_buffer_data,
pipeline_layout,
vertex_input_buffer
);
// Or draw without the index buffer
// device.cmd_draw(draw_command_buffer, 3, 1, 0, 0);
device.cmd_end_render_pass(draw_command_buffer);

},
);
//let mut present_info_err = mem::zeroed();
let present_info = vk::PresentInfoKHR {
wait_semaphore_count: 1,
p_wait_semaphores: &base.rendering_complete_semaphore,
swapchain_count: 1,
p_swapchains: &base.swapchain,
p_image_indices: &present_index,
..Default::default()
};
base.swapchain_loader
.queue_present(base.present_queue, &present_info)
.unwrap();
Event::LoopDestroyed => {
base.device.device_wait_idle().unwrap();

for &pipeline in graphics_pipelines.iter() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably best practice to drain the Vec here even though it doesn't actually change behavior here that much.

base.device.destroy_pipeline(pipeline, None);
}
base.device.destroy_pipeline_layout(pipeline_layout, None);

base.device
.destroy_shader_module(vertex_shader_module, None);
base.device
.destroy_shader_module(fragment_shader_module, None);

base.device.destroy_buffer(image_buffer, None);
base.device.free_memory(image_buffer_memory, None);

base.device.destroy_image_view(tex_image_view, None);
base.device.destroy_image(texture_image, None);
base.device.free_memory(texture_memory, None);

base.device.destroy_buffer(index_buffer, None);
base.device.free_memory(index_buffer_memory, None);

base.device.destroy_buffer(uniform_color_buffer, None);
base.device.free_memory(uniform_color_buffer_memory, None);

base.device.destroy_buffer(vertex_input_buffer, None);
base.device.free_memory(vertex_input_buffer_memory, None);
for &descriptor_set_layout in desc_set_layouts.iter() {
base.device
.destroy_descriptor_set_layout(descriptor_set_layout, None);
}
base.device.destroy_descriptor_pool(descriptor_pool, None);
base.device.destroy_sampler(sampler, None);
}
_ => (),
}
});
base.device.device_wait_idle().unwrap();

for pipeline in graphics_pipelines {
base.device.destroy_pipeline(pipeline, None);
}
base.device.destroy_pipeline_layout(pipeline_layout, None);
base.device
.destroy_shader_module(vertex_shader_module, None);
base.device
.destroy_shader_module(fragment_shader_module, None);
base.device.free_memory(image_buffer_memory, None);
base.device.destroy_buffer(image_buffer, None);
base.device.free_memory(texture_memory, None);
base.device.destroy_image_view(tex_image_view, None);
base.device.destroy_image(texture_image, None);
base.device.free_memory(index_buffer_memory, None);
base.device.destroy_buffer(index_buffer, None);
base.device.free_memory(uniform_color_buffer_memory, None);
base.device.destroy_buffer(uniform_color_buffer, None);
base.device.free_memory(vertex_input_buffer_memory, None);
base.device.destroy_buffer(vertex_input_buffer, None);
for &descriptor_set_layout in desc_set_layouts.iter() {
base.device
.destroy_descriptor_set_layout(descriptor_set_layout, None);
}
base.device.destroy_descriptor_pool(descriptor_pool, None);
base.device.destroy_sampler(sampler, None);
for framebuffer in framebuffers {
base.device.destroy_framebuffer(framebuffer, None);
}
base.device.destroy_render_pass(renderpass, None);
}
}
Loading