1use ash::vk;
2
3unsafe impl crate::util::transparent::Transparent for vk::PipelineShaderStageCreateInfoBuilder<'_> {
4 type Target = vk::PipelineShaderStageCreateInfo;
5}
6unsafe impl crate::util::transparent::Transparent
7 for vk::PipelineColorBlendAttachmentStateBuilder<'_>
8{
9 type Target = vk::PipelineColorBlendAttachmentState;
10}
11
12unsafe_enum_variants! {
13 #[derive(Debug, Copy, Clone)]
14 enum PolygonModeInner {
15 pub Point => {
16 (vk::PolygonMode::POINT, vk::CullModeFlags::NONE, vk::FrontFace::COUNTER_CLOCKWISE, 1.0)
17 },
18 pub Line { width: f32 } => {
19 (vk::PolygonMode::LINE, vk::CullModeFlags::NONE, vk::FrontFace::COUNTER_CLOCKWISE, width)
20 },
21 pub LineDynamic => {
22 (vk::PolygonMode::LINE, vk::CullModeFlags::NONE, vk::FrontFace::COUNTER_CLOCKWISE, f32::NAN)
23 },
24 pub Fill {
25 cull_mode: vk::CullModeFlags,
26 front_face: vk::FrontFace
27 } => {
28 (vk::PolygonMode::FILL, cull_mode, front_face, 1.0)
29 },
30
31 {unsafe} pub Custom {
32 polygon_mode: vk::PolygonMode,
33 cull_mode: vk::CullModeFlags,
34 front_face: vk::FrontFace,
35 line_width: f32
36 } => {
37 (polygon_mode, cull_mode, front_face, line_width)
38 }
39 } as pub PolygonMode impl Into<(vk::PolygonMode, vk::CullModeFlags, vk::FrontFace, f32)>
40}
41impl Default for PolygonMode {
42 fn default() -> Self {
43 PolygonMode::Fill(vk::CullModeFlags::NONE, vk::FrontFace::COUNTER_CLOCKWISE)
44 }
45}
46
47#[derive(Debug, Copy, Clone)]
48pub enum DepthBias {
49 Disabled,
50 Enabled {
51 constant_factor: f32,
52 clamp: f32,
53 slope_factor: f32
54 },
55 Dynamic
56}
57impl Default for DepthBias {
58 fn default() -> Self {
59 DepthBias::Disabled
60 }
61}
62impl Into<(bool, f32, f32, f32)> for DepthBias {
63 fn into(self) -> (bool, f32, f32, f32) {
64 match self {
65 DepthBias::Disabled => (false, 0.0, 0.0, 0.0),
66 DepthBias::Enabled {
67 constant_factor,
68 clamp,
69 slope_factor
70 } => (true, constant_factor, clamp, slope_factor),
71 DepthBias::Dynamic => (true, f32::NAN, f32::NAN, f32::NAN)
72 }
73 }
74}
75
76#[derive(Debug, Copy, Clone)]
77pub enum SampleShading {
78 Disabled,
79 Enabled { min_sample_shading: f32 }
80}
81impl Default for SampleShading {
82 fn default() -> Self {
83 SampleShading::Disabled
84 }
85}
86impl Into<(bool, f32)> for SampleShading {
87 fn into(self) -> (bool, f32) {
88 match self {
89 SampleShading::Disabled => (false, 1.0),
90 SampleShading::Enabled { min_sample_shading } => (true, min_sample_shading)
91 }
92 }
93}
94
95#[derive(Debug, Copy, Clone)]
96pub enum DepthTest {
97 Disabled,
98 Enabled(vk::CompareOp),
99 EnabledReadonly(vk::CompareOp)
100}
101impl Default for DepthTest {
102 fn default() -> Self {
103 DepthTest::Enabled(vk::CompareOp::LESS)
104 }
105}
106impl Into<(bool, bool, vk::CompareOp)> for DepthTest {
107 fn into(self) -> (bool, bool, vk::CompareOp) {
108 match self {
109 DepthTest::Disabled => (false, false, vk::CompareOp::NEVER),
110 DepthTest::Enabled(op) => (true, true, op),
111 DepthTest::EnabledReadonly(op) => (true, false, op)
112 }
113 }
114}
115
116#[derive(Debug, Copy, Clone)]
117pub enum DepthBoundsTest {
118 Disabled,
119 Enabled(f32, f32),
120 Dynamic
121}
122impl Default for DepthBoundsTest {
123 fn default() -> DepthBoundsTest {
124 DepthBoundsTest::Disabled
125 }
126}
127impl Into<(bool, f32, f32)> for DepthBoundsTest {
128 fn into(self) -> (bool, f32, f32) {
129 match self {
130 DepthBoundsTest::Disabled => (false, 0.0, 0.0),
131 DepthBoundsTest::Enabled(min, max) => (true, min, max),
132 DepthBoundsTest::Dynamic => (true, f32::NAN, f32::NAN)
133 }
134 }
135}
136
137#[derive(Debug, Copy, Clone)]
138pub enum StencilTest {
139 Disabled,
140 Enabled {
141 fail_op: [vk::StencilOp; 2],
142 pass_op: [vk::StencilOp; 2],
143 depth_fail_op: [vk::StencilOp; 2],
144 compare_op: [vk::CompareOp; 2],
145 compare_mask: Option<[u32; 2]>,
146 write_mask: Option<[u32; 2]>,
147 reference: Option<[u32; 2]>
148 }
149}
150impl Default for StencilTest {
151 fn default() -> StencilTest {
152 StencilTest::Disabled
153 }
154}
155impl
156 Into<(
157 bool,
158 vk::StencilOpState,
159 vk::StencilOpState,
160 bool,
161 bool,
162 bool
163 )> for StencilTest
164{
165 fn into(
166 self
167 ) -> (
168 bool,
169 vk::StencilOpState,
170 vk::StencilOpState,
171 bool,
172 bool,
173 bool
174 ) {
175 match self {
176 StencilTest::Disabled => (
177 false,
178 Default::default(),
179 Default::default(),
180 false,
181 false,
182 false
183 ),
184 StencilTest::Enabled {
185 fail_op,
186 pass_op,
187 depth_fail_op,
188 compare_op,
189 compare_mask,
190 write_mask,
191 reference
192 } => {
193 let cmp_mask = compare_mask.unwrap_or([0, 0]);
194 let wrt_mask = write_mask.unwrap_or([0, 0]);
195 let rfc = reference.unwrap_or([0, 0]);
196
197 (
198 true,
199 vk::StencilOpState {
200 fail_op: fail_op[0],
201 pass_op: pass_op[0],
202 depth_fail_op: depth_fail_op[0],
203 compare_op: compare_op[0],
204 compare_mask: cmp_mask[0],
205 write_mask: wrt_mask[0],
206 reference: rfc[0]
207 },
208 vk::StencilOpState {
209 fail_op: fail_op[1],
210 pass_op: pass_op[1],
211 depth_fail_op: depth_fail_op[1],
212 compare_op: compare_op[1],
213 compare_mask: cmp_mask[1],
214 write_mask: wrt_mask[1],
215 reference: rfc[1]
216 },
217 compare_mask.is_none(),
218 write_mask.is_none(),
219 reference.is_none()
220 )
221 }
222 }
223 }
224}
225
226#[derive(Debug, Copy, Clone)]
227pub enum BlendLogicOp {
228 Disabled,
229 Enabled(vk::LogicOp)
230}
231impl Default for BlendLogicOp {
232 fn default() -> BlendLogicOp {
233 BlendLogicOp::Disabled
234 }
235}
236impl Into<(bool, vk::LogicOp)> for BlendLogicOp {
237 fn into(self) -> (bool, vk::LogicOp) {
238 match self {
239 BlendLogicOp::Disabled => (false, Default::default()),
240 BlendLogicOp::Enabled(op) => (true, op)
241 }
242 }
243}
244
245#[macro_export]
261macro_rules! viewport_scissor_expr {
262 (
263 [
264 $(
265 dynamic @ [$sc_left: expr, $sc_top: expr, $sc_width: expr, $sc_height: expr]
266 ),+ $(,)?
267 ]
268 ) => {
269 {
270 let viewports = [
271 $(
272 {
273 let _ = $sc_left; $crate::ash::vk::Viewport::default()
275 }
276 ),+
277 ];
278
279 let scissors = [
280 $(
281 $crate::viewport_scissor_expr!([0.0, 0.0] @ [$sc_left, $sc_top, $sc_width, $sc_height]).1
282 ),+
283 ];
284
285 (viewports, scissors, true, false)
286 }
287 };
288
289 (
290 [
291 $(
292 [$width: expr, $height: expr] $(+ [$left: expr, $top: expr])? $(: [$near: expr, $far: expr])? @ dynamic
293 ),+ $(,)?
294 ]
295 ) => {
296 {
297 let viewports = [
298 $(
299 $crate::viewport_scissor_expr!(
300 [$width, $height] $(+ [$left, $top])? $(: [$near, $far])?
301 ).0
302 ),+
303 ];
304
305 let scissors = [
306 $(
307 {
308 let _ = $width; $crate::ash::vk::Rect2D::default()
310 }
311 ),+
312 ];
313
314 (viewports, scissors, false, true)
315 }
316 };
317
318 (
319 dynamic[$count: expr]
320 ) => {
321 {
322 let viewports = [$crate::ash::vk::Viewport::default(); $count];
323 let scissors = [$crate::ash::vk::Rect2D::default(); $count];
324
325 (viewports, scissors, true, true)
326 }
327 };
328
329 (
330 [
331 $(
332 [$width: expr, $height: expr]
333 $(+ [$left: expr, $top: expr])?
334 $(: [$near: expr, $far: expr])?
335 $(@ [$sc_left: expr, $sc_top: expr, $sc_width: expr, $sc_height: expr])?
336 ),* $(,)?
337 ]
338 ) => {
339 {
340 let viewports = [
341 $(
342 $crate::viewport_scissor_expr!(
343 [$width, $height] $(+ [$left, $top])? $(: [$near, $far])?
344 ).0
345 ),*
346 ];
347
348 let scissors = [
349 $(
350 $crate::viewport_scissor_expr!(
351 [$width, $height] $(+ [$left, $top])? $(: [$near, $far])? $(@ [$sc_left, $sc_top, $sc_width, $sc_height])?
352 ).1
353 ),*
354 ];
355
356 (viewports, scissors, false, false)
357 }
358 };
359
360 (
361 [$width: expr, $height: expr]
362 $(+ [$left: expr, $top: expr])?
363 $(: [$near: expr, $far: expr])?
364 $(@ [$sc_left: expr, $sc_top: expr, $sc_width: expr, $sc_height: expr])?
365 ) => {
366 {
367 let viewport = {
368 #[allow(unused_assignments, unused_mut)]
369 let mut x: f32 = 0.0;
370 #[allow(unused_assignments, unused_mut)]
371 let mut y: f32 = 0.0;
372 $(
373 x = $left;
374 y = $top;
375 )?
376
377 #[allow(unused_assignments)]
378 let width: f32 = $width;
379 #[allow(unused_assignments)]
380 let height: f32 = $height;
381
382 #[allow(unused_assignments, unused_mut)]
383 let mut min_depth: f32 = 0.0;
384 #[allow(unused_assignments, unused_mut)]
385 let mut max_depth: f32 = 1.0;
386 $(
387 min_depth = $near;
388 max_depth = $far;
389 )?
390
391 $crate::ash::vk::Viewport {
392 x,
393 y,
394 width,
395 height,
396 min_depth,
397 max_depth
398 }
399 };
400
401 let scissor = {
402 #[allow(unused_assignments, unused_mut)]
403 let mut x: i32 = 0;
404 #[allow(unused_assignments, unused_mut)]
405 let mut y: i32 = 0;
406
407 #[allow(unused_assignments, unused_mut)]
408 let mut width: u32 = i32::MAX as u32;
409 #[allow(unused_assignments, unused_mut)]
410 let mut height: u32 = i32::MAX as u32;
411
412 $(
413 x = $sc_left;
414 y = $sc_top;
415 width = $sc_width;
416 height = $sc_height;
417 )?
418
419 $crate::ash::vk::Rect2D {
420 offset: $crate::ash::vk::Offset2D {
421 x,
422 y
423 },
424 extent: $crate::ash::vk::Extent2D {
425 width,
426 height
427 }
428 }
429 };
430
431 (viewport, scissor)
432 }
433 };
434}
435
436#[macro_export]
467macro_rules! color_blend_state_expr {
468 (
469 disabled & $color_write_mask: expr
470 ) => {
471 $crate::ash::vk::PipelineColorBlendAttachmentState::builder().blend_enable(false)
472 .color_write_mask($color_write_mask)
473 };
474
475 (
476 (S * $src_color_blend_factor: ident) $color_blend_op: ident (D * $dst_color_blend_factor: ident)
477 : (S * $src_alpha_blend_factor: ident) $alpha_blend_op: ident (D * $dst_alpha_blend_factor: ident)
478 & $color_write_mask: expr
479 ) => {
480 {
481 use $crate::ash::vk::{BlendFactor, BlendOp};
482
483 $crate::color_blend_state_expr!(
484 (S * BlendFactor::$src_color_blend_factor) {BlendOp::$color_blend_op} (D * BlendFactor::$dst_color_blend_factor)
485 : (S * BlendFactor::$src_alpha_blend_factor) {BlendOp::$color_blend_op} (D * BlendFactor::$dst_alpha_blend_factor)
486 & $color_write_mask
487 )
488 }
489 };
490
491 (
492 (S * $src_color_blend_factor: expr) {$color_blend_op: expr} (D * $dst_color_blend_factor: expr)
493 : (S * $src_alpha_blend_factor: expr) {$alpha_blend_op: expr} (D * $dst_alpha_blend_factor: expr)
494 & $color_write_mask: expr
495 ) => {
496 $crate::ash::vk::PipelineColorBlendAttachmentState::builder().blend_enable(true)
497 .src_color_blend_factor($src_color_blend_factor)
498 .dst_color_blend_factor($dst_color_blend_factor)
499 .color_blend_op($color_blend_op)
500 .src_alpha_blend_factor($src_alpha_blend_factor)
501 .dst_alpha_blend_factor($dst_alpha_blend_factor)
502 .alpha_blend_op($alpha_blend_op)
503 .color_write_mask($color_write_mask)
504 };
505}
506
507#[macro_export]
561macro_rules! create_graphics_pipeline {
562 (
563 @Shaders($output_builder: expr)
564 stages: [
565 $(
566 $stage: expr $(, $entry_name: expr $(, $specialization: expr)?)? => $stage_type: expr
567 ),* $(,)?
568 ] $(,)?
569 input: {
570 $($input_tt: tt)*
571 } $(,)?
572 topology: $topology: expr
573 $(, primitive_restart: $primitive_restart: expr)?
574 $(,)?
575 ) => {
576 let specialization_infos = [
577 $(
578 {
579 let mut info = None::<$crate::ash::vk::SpecializationInfoBuilder>;
580 $(
581 $(
582 info = Some($specialization.specialization_info());
583 )?
584 )?
585
586 info
587 }
588 ),*
589 ];
590 let _: &[Option<$crate::ash::vk::SpecializationInfoBuilder>] = &specialization_infos;
591
592 #[allow(unused_variables, unused_mut)]
593 let mut counter: usize = 0;
594 let stages = [
595 $(
596 {
597 let mut entry_name: $crate::shader::params::ShaderEntryPoint = Default::default();
598 $(
599 entry_name = $entry_name;
600 )?
601
602 counter += 1;
603 $stage.stage_create_info(
604 $stage_type,
605 entry_name,
606 specialization_infos[counter - 1].as_ref()
607 )
608 }
609 ),*
610 ];
611 let _: &[$crate::ash::vk::PipelineShaderStageCreateInfoBuilder] = &stages;
612
613 let (shader_input_bindings, shader_input_attributes) = $crate::vertex_input_description!(
614 $($input_tt)*
615 );
616 let input_assembly = $crate::ash::vk::PipelineInputAssemblyStateCreateInfo::builder()
617 .topology($topology)
618 .primitive_restart_enable(
619 {
620 #[allow(unused_mut)]
621 let mut restart = false;
622 $(
623 restart = $primitive_restart;
624 )?
625
626 restart
627 }
628 )
629 ;
630
631 let input_state = $crate::ash::vk::PipelineVertexInputStateCreateInfo::builder()
632 .vertex_binding_descriptions(&shader_input_bindings)
633 .vertex_attribute_descriptions(&shader_input_attributes)
634 ;
635
636 $output_builder = $output_builder
637 .stages(
638 $crate::util::transparent::Transparent::transmute_slice(&stages)
639 )
640 .vertex_input_state(&input_state)
641 .input_assembly_state(&input_assembly)
642 ;
643 };
644
645 (
646 @Tessellation($output_builder: expr)
647 patch_control_points: $patch_control_points: expr
648 $(, domain_origin: $domain_origin: expr)?
649 ) => {
650 #[allow(unused_mut)]
651 let mut builder = $crate::ash::vk::PipelineTessellationStateCreateInfo::builder()
652 .patch_control_points($patch_control_points)
653 ;
654 $(
655 let mut domain_origin_info = $crate::ash::vk::PipelineTessellationDomainOriginStateCreateInfo::builder()
656 .domain_origin($domain_origin)
657 ;
658 builder = builder.push_next(&mut domain_origin_info);
659 )?
660
661 $output_builder = $output_builder
662 .tessellation_state(&builder)
663 ;
664 };
665
666 (
667 @Viewport($output_builder: expr, $dynamic_info: expr)
668 viewports: {
669 $($viewports_tt: tt)+
670 } $(,)?
671 ) => {
672 let (viewports, scissors, dynamic_viewport, dynamic_scissors) = $crate::viewport_scissor_expr!(
673 $($viewports_tt)+
674 );
675
676 let builder = $crate::ash::vk::PipelineViewportStateCreateInfo::builder()
677 .viewports(&viewports)
678 .scissors(&scissors)
679 ;
680
681 $output_builder = $output_builder.viewport_state(&builder);
682
683 if dynamic_viewport {
684 $dynamic_info.push($crate::ash::vk::DynamicState::VIEWPORT);
685 }
686 if dynamic_scissors {
687 $dynamic_info.push($crate::ash::vk::DynamicState::SCISSOR);
688 }
689 };
690
691 (
692 @Rasterization($output_builder: expr, $dynamic_info: expr)
693 $(depth_clamp: $depth_clamp: expr,)?
694 $(depth_clip: $depth_clip: expr,)?
695 $(discard: $discard: expr,)?
696 polygon_mode: $polygon_mode: expr
697 $(, depth_bias: $depth_bias: expr)?
698 $(,)?
699 ) => {
700 #[allow(unused_assignments, unused_mut)]
701 let mut builder = $crate::ash::vk::PipelineRasterizationStateCreateInfo::builder();
702 $(
703 let mut depth_clip = $crate::ash::vk::PipelineRasterizationDepthClipStateCreateInfoEXT::builder().depth_clip_enable($depth_clip);
704 builder = builder.push_next(&mut depth_clip);
705 )?
706
707 #[allow(unused_assignments, unused_mut)]
708 let mut depth_clamp = false;
709 $(
710 depth_clamp = $depth_clamp;
711 )?
712 #[allow(unused_assignments, unused_mut)]
713 let mut discard = false;
714 $(
715 discard = $discard;
716 )?
717
718 let polygon_info: $crate::pipeline::params::PolygonMode = $polygon_mode;
719 let (polygon_mode, cull_mode, front_face, line_width) = polygon_info.into();
720
721 #[allow(unused_assignments, unused_mut)]
722 let mut depth_bias: $crate::pipeline::params::DepthBias = Default::default();
723 $(
724 depth_bias = $depth_bias;
725 )?
726 let (depth_bias_enable, depth_bias_constant_factor, depth_bias_clamp, depth_bias_slope_factor) = depth_bias.into();
727
728 builder = builder
729 .depth_clamp_enable(depth_clamp)
730 .rasterizer_discard_enable(discard)
731 .polygon_mode(polygon_mode)
732 .cull_mode(cull_mode)
733 .front_face(front_face)
734 .depth_bias_enable(depth_bias_enable)
735 .depth_bias_constant_factor(depth_bias_constant_factor)
736 .depth_bias_clamp(depth_bias_clamp)
737 .depth_bias_slope_factor(depth_bias_slope_factor)
738 .line_width(line_width)
739 ;
740
741 $output_builder = $output_builder.rasterization_state(&builder);
742
743 if line_width.is_nan() {
744 $dynamic_info.push($crate::ash::vk::DynamicState::LINE_WIDTH);
745 }
746 if depth_bias_enable && (depth_bias_constant_factor.is_nan() || depth_bias_clamp.is_nan() || depth_bias_slope_factor.is_nan()) {
747 $dynamic_info.push($crate::ash::vk::DynamicState::DEPTH_BIAS);
748 }
749 };
750
751 (
752 @Multisampling($output_builder: expr)
753 samples: $samples: expr
754 $(, sample_shading: $sample_shading: expr)?
755 $(, sample_mask: $sample_mask: expr)?
756 $(, alpha_to_coverage: $alpha_to_coverage: expr)?
757 $(, alpha_to_one: $alpha_to_one: expr)?
758 $(,)?
759 ) => {
760 #[allow(unused_assignments, unused_mut)]
761 let mut sample_shading = $crate::pipeline::params::SampleShading::default();
762 $(
763 sample_shading = $sample_shading;
764 )?
765 let (sample_shading_enable, min_sample_shading) = sample_shading.into();
766
767 #[allow(unused_assignments, unused_mut)]
768 let mut alpha_to_coverage = false;
769 $(
770 alpha_to_coverage = $alpha_to_coverage;
771 )?
772 #[allow(unused_assignments, unused_mut)]
773 let mut alpha_to_one = false;
774 $(
775 alpha_to_one = $alpha_to_one;
776 )?
777
778 #[allow(unused_assignments, unused_mut)]
779 let mut builder = $crate::ash::vk::PipelineMultisampleStateCreateInfo::builder()
780 .rasterization_samples($samples)
781 .sample_shading_enable(sample_shading_enable)
782 .min_sample_shading(min_sample_shading)
783 .alpha_to_coverage_enable(alpha_to_coverage)
784 .alpha_to_one_enable(alpha_to_one)
785 ;
786
787 $(
788 let sample_mask_array = $sample_mask;
789 let sample_mask_array_slice: &[u32] = $sample_mask_array;
790 builder = builder.sample_mask(sample_mask_array_slice);
791 )?
792
793 $output_builder = $output_builder.multisample_state(&builder);
794 };
795
796 (
797 @DepthStencil($output_builder: expr, $dynamic_info: expr)
798 depth: $depth_test: expr
799 $(, depth_bounds: $depth_bounds_test: expr)?
800 $(, stencil: $stencil_test: expr)?
801 $(,)?
802 ) => {
803 let depth_test: $crate::pipeline::params::DepthTest = $depth_test;
804 let (depth_test_enable, depth_write_enable, depth_compare_op) = depth_test.into();
805
806 #[allow(unused_assignments, unused_mut)]
807 let mut depth_bounds_test = $crate::pipeline::params::DepthBoundsTest::default();
808 $(
809 depth_bounds_test = $depth_bounds_test;
810 )?
811 let (depth_bounds_test_enable, min_depth_bounds, max_depth_bounds) = depth_bounds_test.into();
812
813 #[allow(unused_assignments, unused_mut)]
814 let mut stencil_test = $crate::pipeline::params::StencilTest::default();
815 $(
816 stencil_test = $stencil_test;
817 )?
818 let (stencil_test_enable, front, back, stencil_comare_dynamic, stencil_write_dynamic, stencil_reference_dynamic) = stencil_test.into();
819
820 let builder = $crate::ash::vk::PipelineDepthStencilStateCreateInfo::builder()
821 .depth_test_enable(depth_test_enable)
822 .depth_write_enable(depth_write_enable)
823 .depth_compare_op(depth_compare_op)
824 .depth_bounds_test_enable(depth_bounds_test_enable)
825 .stencil_test_enable(stencil_test_enable)
826 .front(front)
827 .back(back)
828 .min_depth_bounds(min_depth_bounds)
829 .max_depth_bounds(max_depth_bounds)
830 ;
831
832 $output_builder = $output_builder
833 .depth_stencil_state(&builder)
834 ;
835
836 if depth_bounds_test_enable && (min_depth_bounds.is_nan() || max_depth_bounds.is_nan()) {
837 $dynamic_info.push($crate::ash::vk::DynamicState::DEPTH_BOUNDS);
838 }
839
840 if stencil_test_enable {
841 if stencil_comare_dynamic {
842 $dynamic_info.push($crate::ash::vk::DynamicState::STENCIL_COMPARE_MASK);
843 }
844 if stencil_write_dynamic {
845 $dynamic_info.push($crate::ash::vk::DynamicState::STENCIL_WRITE_MASK);
846 }
847 if stencil_reference_dynamic {
848 $dynamic_info.push($crate::ash::vk::DynamicState::STENCIL_REFERENCE);
849 }
850 }
851 };
852
853 (
854 @ColorBlend($output_builder: expr, $dynamic_info: expr)
855 $(logic_op: $logic_op: expr,)?
856 attachments: [
857 $(
858 { $($attachment_tt: tt)+ }
859 ),*
860 $(,)?
861 ]
862 $(, blend_constants: $blend_constants: expr)?
863 $(,)?
864 ) => {
865 let attachments = [
866 $(
867 $crate::color_blend_state_expr!($($attachment_tt)+)
868 ),*
869 ];
870
871 #[allow(unused_assignments, unused_mut)]
872 let mut logic_op: $crate::pipeline::params::BlendLogicOp = Default::default();
873 $(
874 logic_op = $logic_op;
875 )?
876 let (logic_op_enable, logic_op) = logic_op.into();
877
878 #[allow(unused_assignments, unused_mut)]
879 let mut blend_constants: Option<[f32; 4]> = Some([0.0; 4]);
880 $(
881 blend_constants = $blend_constants;
882 )?
883 let blend_constants_value = blend_constants.unwrap_or([0.0; 4]);
884
885 let builder = $crate::ash::vk::PipelineColorBlendStateCreateInfo::builder()
886 .logic_op_enable(logic_op_enable)
887 .logic_op(logic_op)
888 .attachments(
889 $crate::util::transparent::Transparent::transmute_slice(&attachments)
890 )
891 .blend_constants(blend_constants_value)
892 ;
893
894 $output_builder = $output_builder
895 .color_blend_state(&builder)
896 ;
897
898 if blend_constants.is_none() {
899 $dynamic_info.push($crate::ash::vk::DynamicState::BLEND_CONSTANTS);
900 }
901 };
902
903 (
904 @Deps($output_builder: expr)
905 layout: $layout: expr,
906 render_pass: $render_pass: expr
907 $(, subpass: $subpass: expr)?
908 $(,)?
909 ) => {
910 let layout: $crate::ash::vk::PipelineLayout = $layout.handle();
911 let render_pass: $crate::ash::vk::RenderPass = $render_pass.handle();
912
913 #[allow(unused_assignments, unused_mut)]
914 let mut subpass: u32 = 0;
915 $(
916 subpass = $subpass;
917 )?
918
919 $output_builder = $output_builder
920 .layout(layout)
921 .render_pass(render_pass)
922 .subpass(subpass)
923 ;
924 };
925
926 (
927 let $create_info_variable_name: ident;
928
929 Shaders {
930 $($shaders_tt: tt)+
931 }
932
933 $(
934 Tessellation {
935 $($tessellation_tt: tt)+
936 }
937 )?
938
939 $(
940 Viewport {
941 $($viewport_tt: tt)+
942 }
943 )?
944
945 Rasterization {
946 $($rasterization_tt: tt)+
947 }
948
949 $(
950 Multisampling {
951 $($multisampling_tt: tt)+
952 }
953 )?
954
955 $(
956 DepthStencil {
957 $($depth_stencil_tt: tt)+
958 }
959 )?
960
961 $(
962 ColorBlend {
963 $($color_blend_tt: tt)+
964 }
965 )?
966
967 Deps {
968 $($deps_tt: tt)+
969 }
970 ) => {
971 struct DynamicInfo {
972 index: usize,
973 array: [$crate::ash::vk::DynamicState; 9]
974 }
975 impl DynamicInfo {
976 pub fn new() -> Self {
977 DynamicInfo {
978 index: 0,
979 array: Default::default()
980 }
981 }
982
983 pub fn push(&mut self, value: $crate::ash::vk::DynamicState) {
984 debug_assert!(self.index < self.array.len());
985 self.array[self.index] = value;
986 self.index += 1;
987 }
988
989 pub fn as_slice(&self) -> &[$crate::ash::vk::DynamicState] {
990 &self.array[..self.index]
991 }
992 }
993
994 #[allow(unused_mut)]
995 let mut dynamic_info = DynamicInfo::new();
996 let mut builder = $crate::ash::vk::GraphicsPipelineCreateInfo::builder();
997
998 $crate::create_graphics_pipeline!(
999 @Shaders(builder)
1000 $($shaders_tt)+
1001 );
1002
1003 $(
1004 $crate::create_graphics_pipeline!(
1005 @Tessellation(builder)
1006 $($tessellation_tt)*
1007 );
1008 )?
1009
1010 $(
1011 $crate::create_graphics_pipeline!(
1012 @Viewport(builder, dynamic_info)
1013 $($viewport_tt)+
1014 );
1015 )?
1016
1017 $crate::create_graphics_pipeline!(
1018 @Rasterization(builder, dynamic_info)
1019 $($rasterization_tt)+
1020 );
1021
1022 $(
1023 $crate::create_graphics_pipeline!(
1024 @Multisampling(builder)
1025 $($multisampling_tt)+
1026 );
1027 )?
1028
1029 $(
1030 $crate::create_graphics_pipeline!(
1031 @DepthStencil(builder, dynamic_info)
1032 $($depth_stencil_tt)+
1033 );
1034 )?
1035
1036 $(
1037 $crate::create_graphics_pipeline!(
1038 @ColorBlend(builder, dynamic_info)
1039 $($color_blend_tt)+
1040 );
1041 )?
1042
1043 $crate::create_graphics_pipeline!(
1044 @Deps(builder)
1045 $($deps_tt)+
1046 );
1047
1048 let dynamic_state;
1049 if dynamic_info.as_slice().len() > 0 {
1050 dynamic_state = $crate::ash::vk::PipelineDynamicStateCreateInfo::builder()
1051 .dynamic_states(dynamic_info.as_slice())
1052 ;
1053 builder = builder.dynamic_state(&dynamic_state);
1054 }
1055
1056 let $create_info_variable_name = builder;
1058 }
1059}
1060
1061#[cfg(test)]
1062mod test {
1063 use ash::vk as vvk;
1064
1065 #[test]
1066 #[ignore]
1067 fn test_graphics_pipeline_params() {
1068 offsetable_struct! {
1069 pub struct Vertex {
1070 position: [f32; 3],
1071 color: u32
1072 } repr(C) as VertexOffsets
1073 }
1074 #[repr(C)]
1075 struct Normal {
1076 normal: [f32; 3]
1077 }
1078
1079 struct LayoutHandle;
1080 impl LayoutHandle {
1081 fn handle(&self) -> vvk::PipelineLayout {
1082 vvk::PipelineLayout::null()
1083 }
1084 }
1085
1086 struct RenderPassHandle;
1087 impl RenderPassHandle {
1088 fn handle(&self) -> vvk::RenderPass {
1089 vvk::RenderPass::null()
1090 }
1091 }
1092
1093 create_graphics_pipeline! {
1094 let create_info;
1095
1096 Shaders {
1097 stages: []
1098 input: {
1099 Vertex {
1100 .position => layout(location = 0) in vec3 position;
1101 .color => layout(location = 2) in int color;
1102 }
1103 Normal {
1104 => layout(location = 1) in vec3 normal;
1105 }
1106 }
1107 topology: vvk::PrimitiveTopology::TRIANGLE_LIST
1108 }
1109
1110 Tessellation {
1111 patch_control_points: 0
1112 }
1113
1114 Viewport {
1115 viewports: {
1116 [
1117 dynamic @ [0, 0, i32::MAX as u32, i32::MAX as u32]
1118 ]
1119 }
1120 }
1121
1122 Rasterization {
1123 polygon_mode: super::PolygonMode::LineDynamic(),
1124 depth_bias: super::DepthBias::Dynamic
1125 }
1126
1127 Multisampling {
1128 samples: vvk::SampleCountFlags::TYPE_1
1129 }
1130
1131 DepthStencil {
1132 depth: Default::default(),
1133 depth_bounds: super::DepthBoundsTest::Dynamic,
1134 stencil: super::StencilTest::Enabled {
1135 fail_op: Default::default(),
1136 pass_op: Default::default(),
1137 depth_fail_op: Default::default(),
1138 compare_op: Default::default(),
1139 compare_mask: None,
1140 write_mask: None,
1141 reference: None
1142 }
1143 }
1144
1145 ColorBlend {
1146 logic_op: super::BlendLogicOp::default(),
1147 attachments: [
1148 {
1149 (S * SRC_ALPHA) ADD (D * ONE_MINUS_SRC_ALPHA)
1150 : (S * ONE) SUBTRACT (D * ZERO)
1151 & vvk::ColorComponentFlags::all()
1152 },
1153 { disabled & vvk::ColorComponentFlags::all() }
1154 ],
1155 blend_constants: None
1156 }
1157
1158 Deps {
1159 layout: LayoutHandle,
1160 render_pass: RenderPassHandle
1161 }
1162 };
1163
1164 macro_rules! dbg_it {
1165 (
1166 $base: expr;
1167 $(
1168 $field: ident[$len: literal]$({ $($rec_tt: tt)+ })?
1169 ),+ $(,)?
1170 ) => {
1171 $(
1172 if $base.$field == std::ptr::null() {
1173 eprintln!(
1174 "{} = null",
1175 stringify!($field)
1176 );
1177 } else {
1178 #[allow(unused_unsafe)]
1179 unsafe {
1180 for x in 0 .. $len {
1181 let field = *($base.$field.add(x));
1182 eprintln!(
1183 "[{:?}] {}[{}] = {:#?}",
1184 $base.$field.add(x),
1185 stringify!($field), x,
1186 field
1187 );
1188 $(
1189 dbg_it!(
1190 field;
1191 $($rec_tt)+
1192 );
1193 )?
1194 }
1195 }
1196 eprintln!("");
1197 }
1198 )+
1199 }
1200 }
1201
1202 dbg!(create_info.flags);
1203 dbg_it!(
1204 create_info;
1205
1206 p_stages[0],
1207 p_vertex_input_state[1]{p_vertex_binding_descriptions[2],p_vertex_attribute_descriptions[3]},
1208 p_input_assembly_state[1],
1209
1210 p_tessellation_state[1],
1211
1212 p_viewport_state[1]{p_viewports[2],p_scissors[2]},
1213
1214 p_rasterization_state[1],
1215
1216 p_multisample_state[1],
1217
1218 p_depth_stencil_state[1],
1219
1220 p_color_blend_state[1]{p_attachments[2]},
1221
1222 p_dynamic_state[1]{p_dynamic_states[9]}
1223 );
1224 }
1225}