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
151
152
//! # nobs-vkpipes
//! Compiles shaders from glsl and generates rust code from spv.
//!
//! This crate provides builder pattern implementations for vulkan pipeline creation and descriptor set updating.
//!
//! ## Example
//! This is a simple example that sets up a compute pipeline.
//!
//! All the magic happens in `vk::pipes::pipeline!` macro!
//! We define the pipeline with several comma separated fields, paths are always specified relative to the compilied crate's cargo.toml:
//!
//! See the reexported macros [pipeline](../nobs_vkpipes_macro/macro.pipeline.html) and [shader](../nobs_vkpipes_macro/macro.shader.html) for a list of configurable options.
//! ```rust,compile_fail
//! extern crate nobs_vulkanism as vk;
//! // IMPORTANT import these two crates with their original name
//! // (e.g. not extern crate nobs_vk as vk)
//! // Otherwise the code generation will genertate code
//! // that does not find symbols defined there
//! // You can still use this...
//!
//! // declare the module that will contain our pipeline
//! mod make_sequence {
//!   vk::pipes::pipeline!{
//!     dset_name[0] = "Dset",
//!     stage = {
//!       ty = "comp",
//!       glsl = "
//! #version 450
//! #extension GL_ARB_separate_shader_objects : enable
//!
//! const uint GROUP_SIZE = 512;
//!
//! layout(binding = 0) uniform ub {
//!   uint num_elems;
//!   uint i_first;
//!   uint i_step;
//! };
//!
//! layout(binding = 1) buffer b_out {
//!   uint bout[];
//! };
//!
//! layout(local_size_x = GROUP_SIZE) in;
//! void main() {
//!   // copy input values for group in shared memory
//!   uint gid = gl_GlobalInvocationID.x;
//!
//!   if (gid < num_elems) {
//!     bout[gid] = i_first + gid * i_step;
//!   }
//! }
//!         ",
//!     }
//!   }
//!
//!   // The code generation will not create types for e.g. the uniform buffer
//!   // If we want this, we need to do it our selves
//!   pub struct ub {
//!     pub num_elems: u32,
//!     pub i_first: u32,
//!     pub i_step: u32,
//!   }
//! }
//!
//! // create an instance of the pipeline
//! // uses the nobs_vk::DeviceExtensions to build the pipeline
//! let p = make_sequence::build(device.handle).new().unwrap();
//!
//! // update the descriptor set
//! make_sequence::dset::write(device.handle, ds)
//!   .ub(|b| b.buffer(buf_ub))
//!   .b_out(|b| b.buffer(buf_out))
//!   .update();
//! ```

#[macro_use]
extern crate nobs_vk as vk;
extern crate nobs_vkpipes_macro;

// Codegeneration macros
pub use nobs_vkpipes_macro::pipeline;
pub use nobs_vkpipes_macro::shader;

pub mod pipeline;
pub use pipeline::builder::compute::Compute as ComputeBuilder;
pub use pipeline::builder::graphics::blend::AttachmentBuilder as BlendAttachment;
pub use pipeline::builder::graphics::blend::Builder as Blend;
pub use pipeline::builder::graphics::depth_stencil::Builder as DepthStencil;
pub use pipeline::builder::graphics::dynamic::Builder as Dynamic;
pub use pipeline::builder::graphics::input_assembly::Builder as InputAssembly;
pub use pipeline::builder::graphics::multisample::Builder as Multisample;
pub use pipeline::builder::graphics::raster::Builder as Raster;
pub use pipeline::builder::graphics::tesselation::Builder as Tesselation;
pub use pipeline::builder::graphics::vertex_input::Builder as VertexInput;
pub use pipeline::builder::graphics::viewport::Builder as Viewport;
pub use pipeline::builder::graphics::Graphics as GraphicsBuilder;

pub mod descriptor;
pub use descriptor::pool::Pool as DescriptorPool;

/// For usage in build.rs to automatically detect changes in glsl/spv files and force the recompilation of the rust source that references the shader.
///
/// ## Expample
/// An example build.rs. Every time src/my_shader.comp changes src/main.rs is flagged to recompile as well.
/// ```
/// extern crate nobs_vkpipes as vkpipes;
/// use vkpipes::build::ShaderUsage;
/// fn main() {
///   ShaderUsage::new().uses("src/my_shader.comp").depends("src/main.rs");
/// }
/// ```
pub mod build {
  /// Creates a dependency between a shader source and rust source
  pub struct ShaderUsage {}

  impl ShaderUsage {
    /// Creates a new mapping
    pub fn new() -> ShaderUsage {
      ShaderUsage {}
    }

    /// Specify a filename of a shader, that if changed triggers the recompilation of all dependent rust sources
    pub fn uses(&self, filename: &str) -> &Self {
      if std::path::Path::new(filename).exists() {
        println!("cargo:rerun-if-changed={}", filename);
      } else {
        println!(
          "cargo:warning=The file {} does not exists, but is listed as used shader resource",
          filename
        );
      }
      &self
    }

    /// Specify a filename of a rust source, that is recompiled if any of used shaders was changed
    pub fn depends(&self, filename: &str) -> &Self {
      if std::path::Path::new(filename).exists() {
        std::process::Command::new("sh")
          .arg("-c")
          .arg(format!("touch {}", filename))
          .output()
          .unwrap();
      } else {
        println!(
          "cargo:warning=The file {} does not exists, but is listed as shader usage dependency",
          filename
        );
      }
      &self
    }
  }
}