1 // Copyright (c) 2016 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9
10 //! This module contains the unit tests of `GraphicsPipeline`.
11
12 #![cfg(test)]
13
14 use format::Format;
15 use framebuffer::Subpass;
16 use pipeline::blend::Blend;
17 use pipeline::depth_stencil::DepthStencil;
18 use pipeline::input_assembly::InputAssembly;
19 use pipeline::input_assembly::PrimitiveTopology;
20 use pipeline::layout::PipelineLayoutDesc;
21 use pipeline::multisample::Multisample;
22 use pipeline::shader::ShaderInterface;
23 use pipeline::shader::ShaderModule;
24 use pipeline::vertex::SingleBufferDefinition;
25 use pipeline::viewport::ViewportsState;
26 use pipeline::GraphicsPipeline;
27 use pipeline::GraphicsPipelineCreationError;
28 use pipeline::GraphicsPipelineParams;
29 use std::ffi::CString;
30
31 #[test]
create()32 fn create() {
33 let (device, _) = gfx_dev_and_queue!();
34
35 let vs = unsafe { ShaderModule::new(device.clone(), &BASIC_VS).unwrap() };
36 let fs = unsafe { ShaderModule::new(device.clone(), &BASIC_FS).unwrap() };
37
38 let _ = GraphicsPipeline::new(
39 &device,
40 GraphicsPipelineParams {
41 vertex_input: SingleBufferDefinition::<()>::new(),
42 vertex_shader: unsafe {
43 vs.vertex_shader_entry_point::<(), _, _, _>(
44 &CString::new("main").unwrap(),
45 ShaderInterface::empty(),
46 ShaderInterface::empty(),
47 PipelineLayoutDesc::empty(),
48 )
49 },
50 input_assembly: InputAssembly::triangle_list(),
51 tessellation: None,
52 geometry_shader: None,
53 viewport: ViewportsState::Dynamic { num: 1 },
54 raster: Default::default(),
55 multisample: Multisample::disabled(),
56 fragment_shader: unsafe {
57 fs.fragment_shader_entry_point::<(), _, _, _>(
58 &CString::new("main").unwrap(),
59 ShaderInterface::empty(),
60 ShaderInterface::empty(),
61 PipelineLayoutDesc::empty(),
62 )
63 },
64 depth_stencil: DepthStencil::disabled(),
65 blend: Blend::pass_through(),
66 render_pass: Subpass::from(
67 simple_rp::CustomRenderPass::new(&device, &{
68 simple_rp::Formats {
69 color: (Format::R8G8B8A8_UNORM, 1),
70 }
71 })
72 .unwrap(),
73 0,
74 )
75 .unwrap(),
76 },
77 )
78 .unwrap();
79 }
80
81 #[test]
bad_primitive_restart()82 fn bad_primitive_restart() {
83 let (device, _) = gfx_dev_and_queue!();
84
85 let vs = unsafe { ShaderModule::new(device.clone(), &BASIC_VS).unwrap() };
86 let fs = unsafe { ShaderModule::new(device.clone(), &BASIC_FS).unwrap() };
87
88 let result = GraphicsPipeline::new(
89 &device,
90 GraphicsPipelineParams {
91 vertex_input: SingleBufferDefinition::<()>::new(),
92 vertex_shader: unsafe {
93 vs.vertex_shader_entry_point::<(), _, _, _>(
94 &CString::new("main").unwrap(),
95 ShaderInterface::empty(),
96 ShaderInterface::empty(),
97 PipelineLayoutDesc::empty(),
98 )
99 },
100 input_assembly: InputAssembly {
101 topology: PrimitiveTopology::TriangleList,
102 primitive_restart_enable: true,
103 },
104 tessellation: None,
105 geometry_shader: None,
106 viewport: ViewportsState::Dynamic { num: 1 },
107 raster: Default::default(),
108 multisample: Multisample::disabled(),
109 fragment_shader: unsafe {
110 fs.fragment_shader_entry_point::<(), _, _, _>(
111 &CString::new("main").unwrap(),
112 ShaderInterface::empty(),
113 ShaderInterface::empty(),
114 PipelineLayoutDesc::empty(),
115 )
116 },
117 depth_stencil: DepthStencil::disabled(),
118 blend: Blend::pass_through(),
119 render_pass: Subpass::from(
120 simple_rp::CustomRenderPass::new(&device, &{
121 simple_rp::Formats {
122 color: (Format::R8G8B8A8_UNORM, 1),
123 }
124 })
125 .unwrap(),
126 0,
127 )
128 .unwrap(),
129 },
130 );
131
132 match result {
133 Err(GraphicsPipelineCreationError::RequirementNotMet { .. }) => (),
134 _ => panic!(),
135 }
136 }
137
138 #[test]
multi_viewport_feature()139 fn multi_viewport_feature() {
140 let (device, _) = gfx_dev_and_queue!();
141
142 let vs = unsafe { ShaderModule::new(device.clone(), &BASIC_VS).unwrap() };
143 let fs = unsafe { ShaderModule::new(device.clone(), &BASIC_FS).unwrap() };
144
145 let result = GraphicsPipeline::new(
146 &device,
147 GraphicsPipelineParams {
148 vertex_input: SingleBufferDefinition::<()>::new(),
149 vertex_shader: unsafe {
150 vs.vertex_shader_entry_point::<(), _, _, _>(
151 &CString::new("main").unwrap(),
152 ShaderInterface::empty(),
153 ShaderInterface::empty(),
154 PipelineLayoutDesc::empty(),
155 )
156 },
157 input_assembly: InputAssembly::triangle_list(),
158 tessellation: None,
159 geometry_shader: None,
160 viewport: ViewportsState::Dynamic { num: 2 },
161 raster: Default::default(),
162 multisample: Multisample::disabled(),
163 fragment_shader: unsafe {
164 fs.fragment_shader_entry_point::<(), _, _, _>(
165 &CString::new("main").unwrap(),
166 ShaderInterface::empty(),
167 ShaderInterface::empty(),
168 PipelineLayoutDesc::empty(),
169 )
170 },
171 depth_stencil: DepthStencil::disabled(),
172 blend: Blend::pass_through(),
173 render_pass: Subpass::from(
174 simple_rp::CustomRenderPass::new(&device, &{
175 simple_rp::Formats {
176 color: (Format::R8G8B8A8_UNORM, 1),
177 }
178 })
179 .unwrap(),
180 0,
181 )
182 .unwrap(),
183 },
184 );
185
186 match result {
187 Err(GraphicsPipelineCreationError::MultiViewportFeatureNotEnabled) => (),
188 _ => panic!(),
189 }
190 }
191
192 #[test]
max_viewports()193 fn max_viewports() {
194 let (device, _) = gfx_dev_and_queue!(multi_viewport);
195
196 let vs = unsafe { ShaderModule::new(device.clone(), &BASIC_VS).unwrap() };
197 let fs = unsafe { ShaderModule::new(device.clone(), &BASIC_FS).unwrap() };
198
199 let result = GraphicsPipeline::new(
200 &device,
201 GraphicsPipelineParams {
202 vertex_input: SingleBufferDefinition::<()>::new(),
203 vertex_shader: unsafe {
204 vs.vertex_shader_entry_point::<(), _, _, _>(
205 &CString::new("main").unwrap(),
206 ShaderInterface::empty(),
207 ShaderInterface::empty(),
208 PipelineLayoutDesc::empty(),
209 )
210 },
211 input_assembly: InputAssembly::triangle_list(),
212 tessellation: None,
213 geometry_shader: None,
214 viewport: ViewportsState::Dynamic { num: !0 },
215 raster: Default::default(),
216 multisample: Multisample::disabled(),
217 fragment_shader: unsafe {
218 fs.fragment_shader_entry_point::<(), _, _, _>(
219 &CString::new("main").unwrap(),
220 ShaderInterface::empty(),
221 ShaderInterface::empty(),
222 PipelineLayoutDesc::empty(),
223 )
224 },
225 depth_stencil: DepthStencil::disabled(),
226 blend: Blend::pass_through(),
227 render_pass: Subpass::from(
228 simple_rp::CustomRenderPass::new(&device, &{
229 simple_rp::Formats {
230 color: (Format::R8G8B8A8_UNORM, 1),
231 }
232 })
233 .unwrap(),
234 0,
235 )
236 .unwrap(),
237 },
238 );
239
240 match result {
241 Err(GraphicsPipelineCreationError::MaxViewportsExceeded { .. }) => (),
242 _ => panic!(),
243 }
244 }
245
246 #[test]
no_depth_attachment()247 fn no_depth_attachment() {
248 let (device, _) = gfx_dev_and_queue!();
249
250 let vs = unsafe { ShaderModule::new(device.clone(), &BASIC_VS).unwrap() };
251 let fs = unsafe { ShaderModule::new(device.clone(), &BASIC_FS).unwrap() };
252
253 let result = GraphicsPipeline::new(
254 &device,
255 GraphicsPipelineParams {
256 vertex_input: SingleBufferDefinition::<()>::new(),
257 vertex_shader: unsafe {
258 vs.vertex_shader_entry_point::<(), _, _, _>(
259 &CString::new("main").unwrap(),
260 ShaderInterface::empty(),
261 ShaderInterface::empty(),
262 PipelineLayoutDesc::empty(),
263 )
264 },
265 input_assembly: InputAssembly::triangle_list(),
266 tessellation: None,
267 geometry_shader: None,
268 viewport: ViewportsState::Dynamic { num: 1 },
269 raster: Default::default(),
270 multisample: Multisample::disabled(),
271 fragment_shader: unsafe {
272 fs.fragment_shader_entry_point::<(), _, _, _>(
273 &CString::new("main").unwrap(),
274 ShaderInterface::empty(),
275 ShaderInterface::empty(),
276 PipelineLayoutDesc::empty(),
277 )
278 },
279 depth_stencil: DepthStencil::simple_depth_test(),
280 blend: Blend::pass_through(),
281 render_pass: Subpass::from(
282 simple_rp::CustomRenderPass::new(&device, &{
283 simple_rp::Formats {
284 color: (Format::R8G8B8A8_UNORM, 1),
285 }
286 })
287 .unwrap(),
288 0,
289 )
290 .unwrap(),
291 },
292 );
293
294 match result {
295 Err(GraphicsPipelineCreationError::NoDepthAttachment) => (),
296 _ => panic!(),
297 }
298 }
299
300 mod simple_rp {
301 use format::Format;
302
303 single_pass_renderpass! {
304 attachments: {
305 color: {
306 load: Clear,
307 store: Store,
308 format: Format,
309 },
310 },
311 pass: {
312 color: [color],
313 depth_stencil: {},
314 },
315 }
316 }
317
318 /*
319 #version 450
320
321 #extension GL_ARB_separate_shader_objects : enable
322 #extension GL_ARB_shading_language_420pack : enable
323
324 layout(location = 0) in vec2 position;
325
326 void main() {
327 gl_Position = vec4(position, 0.0, 1.0);
328 }
329 */
330 const BASIC_VS: [u8; 912] = [
331 3, 2, 35, 7, 0, 0, 1, 0, 1, 0, 8, 0, 27, 0, 0, 0, 0, 0, 0, 0, 17, 0, 2, 0, 1, 0, 0, 0, 17, 0,
332 2, 0, 32, 0, 0, 0, 17, 0, 2, 0, 33, 0, 0, 0, 11, 0, 6, 0, 1, 0, 0, 0, 71, 76, 83, 76, 46, 115,
333 116, 100, 46, 52, 53, 48, 0, 0, 0, 0, 14, 0, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 15, 0, 7, 0, 0, 0,
334 0, 0, 4, 0, 0, 0, 109, 97, 105, 110, 0, 0, 0, 0, 13, 0, 0, 0, 18, 0, 0, 0, 3, 0, 3, 0, 2, 0, 0,
335 0, 194, 1, 0, 0, 4, 0, 9, 0, 71, 76, 95, 65, 82, 66, 95, 115, 101, 112, 97, 114, 97, 116, 101,
336 95, 115, 104, 97, 100, 101, 114, 95, 111, 98, 106, 101, 99, 116, 115, 0, 0, 4, 0, 9, 0, 71, 76,
337 95, 65, 82, 66, 95, 115, 104, 97, 100, 105, 110, 103, 95, 108, 97, 110, 103, 117, 97, 103, 101,
338 95, 52, 50, 48, 112, 97, 99, 107, 0, 5, 0, 4, 0, 4, 0, 0, 0, 109, 97, 105, 110, 0, 0, 0, 0, 5,
339 0, 6, 0, 11, 0, 0, 0, 103, 108, 95, 80, 101, 114, 86, 101, 114, 116, 101, 120, 0, 0, 0, 0, 6,
340 0, 6, 0, 11, 0, 0, 0, 0, 0, 0, 0, 103, 108, 95, 80, 111, 115, 105, 116, 105, 111, 110, 0, 6, 0,
341 7, 0, 11, 0, 0, 0, 1, 0, 0, 0, 103, 108, 95, 80, 111, 105, 110, 116, 83, 105, 122, 101, 0, 0,
342 0, 0, 6, 0, 7, 0, 11, 0, 0, 0, 2, 0, 0, 0, 103, 108, 95, 67, 108, 105, 112, 68, 105, 115, 116,
343 97, 110, 99, 101, 0, 6, 0, 7, 0, 11, 0, 0, 0, 3, 0, 0, 0, 103, 108, 95, 67, 117, 108, 108, 68,
344 105, 115, 116, 97, 110, 99, 101, 0, 5, 0, 3, 0, 13, 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 18, 0, 0,
345 0, 112, 111, 115, 105, 116, 105, 111, 110, 0, 0, 0, 0, 72, 0, 5, 0, 11, 0, 0, 0, 0, 0, 0, 0,
346 11, 0, 0, 0, 0, 0, 0, 0, 72, 0, 5, 0, 11, 0, 0, 0, 1, 0, 0, 0, 11, 0, 0, 0, 1, 0, 0, 0, 72, 0,
347 5, 0, 11, 0, 0, 0, 2, 0, 0, 0, 11, 0, 0, 0, 3, 0, 0, 0, 72, 0, 5, 0, 11, 0, 0, 0, 3, 0, 0, 0,
348 11, 0, 0, 0, 4, 0, 0, 0, 71, 0, 3, 0, 11, 0, 0, 0, 2, 0, 0, 0, 71, 0, 4, 0, 18, 0, 0, 0, 30, 0,
349 0, 0, 0, 0, 0, 0, 19, 0, 2, 0, 2, 0, 0, 0, 33, 0, 3, 0, 3, 0, 0, 0, 2, 0, 0, 0, 22, 0, 3, 0, 6,
350 0, 0, 0, 32, 0, 0, 0, 23, 0, 4, 0, 7, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0, 21, 0, 4, 0, 8, 0, 0, 0,
351 32, 0, 0, 0, 0, 0, 0, 0, 43, 0, 4, 0, 8, 0, 0, 0, 9, 0, 0, 0, 1, 0, 0, 0, 28, 0, 4, 0, 10, 0,
352 0, 0, 6, 0, 0, 0, 9, 0, 0, 0, 30, 0, 6, 0, 11, 0, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 10, 0, 0, 0,
353 10, 0, 0, 0, 32, 0, 4, 0, 12, 0, 0, 0, 3, 0, 0, 0, 11, 0, 0, 0, 59, 0, 4, 0, 12, 0, 0, 0, 13,
354 0, 0, 0, 3, 0, 0, 0, 21, 0, 4, 0, 14, 0, 0, 0, 32, 0, 0, 0, 1, 0, 0, 0, 43, 0, 4, 0, 14, 0, 0,
355 0, 15, 0, 0, 0, 0, 0, 0, 0, 23, 0, 4, 0, 16, 0, 0, 0, 6, 0, 0, 0, 2, 0, 0, 0, 32, 0, 4, 0, 17,
356 0, 0, 0, 1, 0, 0, 0, 16, 0, 0, 0, 59, 0, 4, 0, 17, 0, 0, 0, 18, 0, 0, 0, 1, 0, 0, 0, 43, 0, 4,
357 0, 6, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 43, 0, 4, 0, 6, 0, 0, 0, 21, 0, 0, 0, 0, 0, 128, 63,
358 32, 0, 4, 0, 25, 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0, 54, 0, 5, 0, 2, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0,
359 0, 3, 0, 0, 0, 248, 0, 2, 0, 5, 0, 0, 0, 61, 0, 4, 0, 16, 0, 0, 0, 19, 0, 0, 0, 18, 0, 0, 0,
360 81, 0, 5, 0, 6, 0, 0, 0, 22, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 81, 0, 5, 0, 6, 0, 0, 0, 23, 0,
361 0, 0, 19, 0, 0, 0, 1, 0, 0, 0, 80, 0, 7, 0, 7, 0, 0, 0, 24, 0, 0, 0, 22, 0, 0, 0, 23, 0, 0, 0,
362 20, 0, 0, 0, 21, 0, 0, 0, 65, 0, 5, 0, 25, 0, 0, 0, 26, 0, 0, 0, 13, 0, 0, 0, 15, 0, 0, 0, 62,
363 0, 3, 0, 26, 0, 0, 0, 24, 0, 0, 0, 253, 0, 1, 0, 56, 0, 1, 0,
364 ];
365
366 /*
367 #version 450
368
369 #extension GL_ARB_separate_shader_objects : enable
370 #extension GL_ARB_shading_language_420pack : enable
371
372 layout(location = 0) out vec4 f_color;
373
374 void main() {
375 f_color = vec4(1.0, 0.0, 0.0, 1.0);
376 }
377 */
378 const BASIC_FS: [u8; 420] = [
379 3, 2, 35, 7, 0, 0, 1, 0, 1, 0, 8, 0, 13, 0, 0, 0, 0, 0, 0, 0, 17, 0, 2, 0, 1, 0, 0, 0, 11, 0,
380 6, 0, 1, 0, 0, 0, 71, 76, 83, 76, 46, 115, 116, 100, 46, 52, 53, 48, 0, 0, 0, 0, 14, 0, 3, 0,
381 0, 0, 0, 0, 1, 0, 0, 0, 15, 0, 6, 0, 4, 0, 0, 0, 4, 0, 0, 0, 109, 97, 105, 110, 0, 0, 0, 0, 9,
382 0, 0, 0, 16, 0, 3, 0, 4, 0, 0, 0, 7, 0, 0, 0, 3, 0, 3, 0, 2, 0, 0, 0, 194, 1, 0, 0, 4, 0, 9, 0,
383 71, 76, 95, 65, 82, 66, 95, 115, 101, 112, 97, 114, 97, 116, 101, 95, 115, 104, 97, 100, 101,
384 114, 95, 111, 98, 106, 101, 99, 116, 115, 0, 0, 4, 0, 9, 0, 71, 76, 95, 65, 82, 66, 95, 115,
385 104, 97, 100, 105, 110, 103, 95, 108, 97, 110, 103, 117, 97, 103, 101, 95, 52, 50, 48, 112, 97,
386 99, 107, 0, 5, 0, 4, 0, 4, 0, 0, 0, 109, 97, 105, 110, 0, 0, 0, 0, 5, 0, 4, 0, 9, 0, 0, 0, 102,
387 95, 99, 111, 108, 111, 114, 0, 71, 0, 4, 0, 9, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 19, 0, 2, 0,
388 2, 0, 0, 0, 33, 0, 3, 0, 3, 0, 0, 0, 2, 0, 0, 0, 22, 0, 3, 0, 6, 0, 0, 0, 32, 0, 0, 0, 23, 0,
389 4, 0, 7, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0, 32, 0, 4, 0, 8, 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0, 59,
390 0, 4, 0, 8, 0, 0, 0, 9, 0, 0, 0, 3, 0, 0, 0, 43, 0, 4, 0, 6, 0, 0, 0, 10, 0, 0, 0, 0, 0, 128,
391 63, 43, 0, 4, 0, 6, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 44, 0, 7, 0, 7, 0, 0, 0, 12, 0, 0, 0, 10,
392 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 10, 0, 0, 0, 54, 0, 5, 0, 2, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0,
393 0, 3, 0, 0, 0, 248, 0, 2, 0, 5, 0, 0, 0, 62, 0, 3, 0, 9, 0, 0, 0, 12, 0, 0, 0, 253, 0, 1, 0,
394 56, 0, 1, 0,
395 ];
396