1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
#![deny(unsafe_code)]
use crate::error::*;
use crate::graphics::Render;
use crate::linear_algebra::{ Vec3, Vec4, Transformation };
use crate::shader_data::{ Vertex, VertexPushBlock };
use std::f32::consts::{ TAU };
use vulkanalia::Device;
use vulkanalia::vk::{ self, HasBuilder, DeviceV1_0 };
#[allow(unsafe_code)]
pub fn generate_scene_commands<'a>(image_index: usize, time: f32,
render: &'a Render,
device: &Device, extent: &vk::Extent2D)
-> Result<&'a vk::CommandBuffer>
{
let frame = &render.per_frame[image_index];
let command_buffer = &frame.command_buffer;
let framebuffer = &frame.framebuffer;
let descriptor_set = &frame.descriptor_set;
let inheritance_info = vk::CommandBufferInheritanceInfo::builder();
let command_buffer_begin_info = vk::CommandBufferBeginInfo::builder()
.flags(vk::CommandBufferUsageFlags::empty())
.inheritance_info(&inheritance_info);
unsafe {
device.begin_command_buffer(*command_buffer, &command_buffer_begin_info)
}?;
let render_area = vk::Rect2D::builder()
.offset(vk::Offset2D::default())
.extent(*extent);
let color_clear_value = vk::ClearValue {
color: vk::ClearColorValue {
float32: [0.0, 0.0, 0.0, 1.0]
}
};
let depth_clear_value = vk::ClearValue {
depth_stencil: vk::ClearDepthStencilValue {
depth: 1.0,
stencil: 0,
}
};
let clear_values = [color_clear_value, depth_clear_value];
let begin_pass_info = vk::RenderPassBeginInfo::builder()
.render_pass(render.render_pass)
.framebuffer(*framebuffer)
.render_area(render_area)
.clear_values(&clear_values);
unsafe {
device.cmd_begin_render_pass(*command_buffer, &begin_pass_info,
vk::SubpassContents::INLINE)
};
unsafe {
device.cmd_bind_pipeline(*command_buffer,
vk::PipelineBindPoint::GRAPHICS,
render.pipeline)
};
// Please notice the magic constant 0. This is a zero-based index into
// the array of descriptor set layouts passed to create_pipeline_layout()
// in init_pipeline() in render.rs.
unsafe {
device.cmd_bind_descriptor_sets(*command_buffer,
vk::PipelineBindPoint::GRAPHICS,
render.pipeline_layout,
0,
&[*descriptor_set],
&[])
};
if let Some(texture) = &render.texture {
texture.make_active(device, render, command_buffer);
}
if let Some(model) = &render.model {
model.make_active(device, render, command_buffer);
let (scale, mut transformation) = demo_spin_transformation(time);
apply_model_transformation(device, render, command_buffer,
&scale, &transformation);
model.render(device, render, command_buffer);
transformation.translation = transformation.translation.add(
&Vec3::new(0.0, 4.0, 0.0));
apply_model_transformation(device, render, command_buffer,
&scale, &transformation);
model.render(device, render, command_buffer);
transformation.translation = transformation.translation.add(
&Vec3::new(0.0, -8.0, 0.0));
apply_model_transformation(device, render, command_buffer,
&scale, &transformation);
model.render(device, render, command_buffer);
}
unsafe { device.cmd_end_render_pass(*command_buffer) };
unsafe { device.end_command_buffer(*command_buffer) }?;
Ok(command_buffer)
}
fn demo_spin_transformation(time: f32) -> (Vec3<f32>, Transformation<f32>) {
let scale = Vec3::new(1.0, 1.0, 1.0);
let transformation = Transformation {
rotation: Vec4::rotation_quaternion(&Vec3::new(0.0, 1.0, 0.0),
time % TAU),
translation: Vec3::new(0.0, 0.0, 0.0),
};
(scale, transformation)
}
#[allow(unsafe_code)]
fn apply_model_transformation(device: &Device, render: &Render,
command_buffer: &vk::CommandBuffer,
scale: &Vec3<f32>,
transformation: &Transformation<f32>)
{
let push_block = VertexPushBlock::<f32> {
scale: scale.clone(),
model: transformation.clone(),
};
let size = size_of::<VertexPushBlock::<f32>>();
let push_block_bytes = unsafe {
std::slice::from_raw_parts(&push_block as *const VertexPushBlock<f32>
as *const u8,
size)
};
unsafe {
device.cmd_push_constants(*command_buffer, render.pipeline_layout,
vk::ShaderStageFlags::VERTEX,
0,
push_block_bytes)
};
}
|