From 075e9812d89c7384d7cc31a2284755dfc95122a0 Mon Sep 17 00:00:00 2001 From: Mai <63251610+interacsion@users.noreply.github.com> Date: Sun, 15 Sep 2024 19:15:18 +0300 Subject: [PATCH] Add `lang` option to `vulkano_shaders::shader!` and update documentation --- README.md | 2 +- vulkano-shaders/src/codegen.rs | 12 +++++++++--- vulkano-shaders/src/lib.rs | 35 +++++++++++++++++++++++++++------- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index b4b3957c..bbea361f 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,7 @@ of unreleased and breaking changes in `master` This repository contains four libraries: - `vulkano` is the main one. -- `vulkano-shaders` provides the `shader!` macro for compiling glsl shaders. +- `vulkano-shaders` provides the `shader!` macro for compiling shaders. - `vulkano-util` provides a variety of utility functions to streamline certain common operations such as device and swapchain creation. - `vulkano-win` provides a safe link between vulkano and the `winit` library which can create a window to render to. diff --git a/vulkano-shaders/src/codegen.rs b/vulkano-shaders/src/codegen.rs index e9722de9..af184c15 100644 --- a/vulkano-shaders/src/codegen.rs +++ b/vulkano-shaders/src/codegen.rs @@ -6,7 +6,7 @@ use heck::ToSnakeCase; use proc_macro2::TokenStream; use quote::{format_ident, quote}; pub use shaderc::{CompilationArtifact, IncludeType, ResolvedInclude, ShaderKind}; -use shaderc::{CompileOptions, Compiler, EnvVersion, TargetEnv}; +use shaderc::{CompileOptions, Compiler, EnvVersion, SourceLanguage, TargetEnv}; use std::{ cell::RefCell, fs, @@ -145,10 +145,13 @@ pub(super) fn compile( shader_kind: ShaderKind, ) -> Result<(CompilationArtifact, Vec), String> { let includes = RefCell::new(Vec::new()); - let compiler = Compiler::new().ok_or("failed to create GLSL compiler")?; + let compiler = Compiler::new().ok_or("failed to create shader compiler")?; let mut compile_options = CompileOptions::new().ok_or("failed to initialize compile options")?; + let source_language = input.source_language.unwrap_or(SourceLanguage::GLSL); + compile_options.set_source_language(source_language); + compile_options.set_target_env( TargetEnv::Vulkan, input.vulkan_version.unwrap_or(EnvVersion::Vulkan1_0) as u32, @@ -160,7 +163,10 @@ pub(super) fn compile( let root_source_path = path.as_deref().unwrap_or( // An arbitrary placeholder file name for embedded shaders. - "shader.glsl", + match source_language { + SourceLanguage::GLSL => "shader.glsl", + SourceLanguage::HLSL => "shader.hlsl", + }, ); // Specify the file resolution callback for the `#include` directive. diff --git a/vulkano-shaders/src/lib.rs b/vulkano-shaders/src/lib.rs index bcb808a4..961b7f9c 100644 --- a/vulkano-shaders/src/lib.rs +++ b/vulkano-shaders/src/lib.rs @@ -1,6 +1,6 @@ //! The procedural macro for vulkano's shader system. -//! Manages the compile-time compilation of GLSL into SPIR-V and generation of associated Rust -//! code. +//! Manages the compile-time compilation of shader code into SPIR-V and generation of associated +//! Rust code. //! //! # Basic usage //! @@ -89,8 +89,8 @@ //! //! ## `ty: "..."` //! -//! This defines what shader type the given GLSL source will be compiled into. The type can be any -//! of the following: +//! This defines what shader type the shader source will be compiled into. The type can be any of +//! the following: //! //! - `vertex` //! - `tess_ctrl` @@ -111,12 +111,12 @@ //! //! ## `src: "..."` //! -//! Provides the raw GLSL source to be compiled in the form of a string. Cannot be used in +//! Provides the raw shader source to be compiled in the form of a string. Cannot be used in //! conjunction with the `path` or `bytes` field. //! //! ## `path: "..."` //! -//! Provides the path to the GLSL source to be compiled, relative to your `Cargo.toml`. Cannot be +//! Provides the path to the shader source to be compiled, relative to your `Cargo.toml`. Cannot be //! used in conjunction with the `src` or `bytes` field. //! //! ## `bytes: "..."` @@ -163,6 +163,11 @@ //! Adds the given macro definitions to the pre-processor. This is equivalent to passing the //! `-DNAME=VALUE` argument on the command line. //! +//! ## `lang: "..."` +//! +//! Provides the language of the shader source. Must be either `glsl` or `hlsl` (defaults to +//! `glsl`). +//! //! ## `vulkan_version: "major.minor"` and `spirv_version: "major.minor"` //! //! Sets the Vulkan and SPIR-V versions to compile into, respectively. These map directly to the @@ -230,7 +235,7 @@ use crate::codegen::ShaderKind; use ahash::HashMap; use proc_macro2::{Span, TokenStream}; use quote::quote; -use shaderc::{EnvVersion, SpirvVersion}; +use shaderc::{EnvVersion, SourceLanguage, SpirvVersion}; use std::{ env, fs, mem, path::{Path, PathBuf}, @@ -380,6 +385,7 @@ struct MacroInput { include_directories: Vec, macro_defines: Vec<(String, String)>, shaders: HashMap, SourceKind)>, + source_language: Option, spirv_version: Option, vulkan_version: Option, generate_structs: bool, @@ -393,6 +399,7 @@ impl MacroInput { fn empty() -> Self { MacroInput { root_path_env: None, + source_language: None, include_directories: Vec::new(), macro_defines: Vec::new(), shaders: HashMap::default(), @@ -411,6 +418,7 @@ impl Parse for MacroInput { let root = env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); let mut root_path_env = None; + let mut source_language = None; let mut include_directories = Vec::new(); let mut macro_defines = Vec::new(); let mut shaders = HashMap::default(); @@ -619,6 +627,18 @@ impl Parse for MacroInput { } } } + "lang" => { + let lit = input.parse::()?; + if source_language.is_some() { + bail!(lit, "field `lang` is already defined"); + } + + source_language = Some(match lit.value().as_str() { + "glsl" => SourceLanguage::GLSL, + "hlsl" => SourceLanguage::HLSL, + lang => bail!(lit, "expected `glsl` or `hlsl`, found `{lang}`"), + }) + } "vulkan_version" => { let lit = input.parse::()?; if vulkan_version.is_some() { @@ -755,6 +775,7 @@ impl Parse for MacroInput { (key, (shader_kind, shader_source.unwrap())) }) .collect(), + source_language, vulkan_version, spirv_version, generate_structs: generate_structs.unwrap_or(true),