api: fix feature flags to allow building a proper subset of librashader

This commit is contained in:
chyyran 2023-02-07 18:50:26 -05:00
parent 07b20fecdc
commit d1771a8b25
10 changed files with 115 additions and 73 deletions

5
Cargo.lock generated
View file

@ -751,7 +751,6 @@ dependencies = [
"librashader-runtime-d3d12", "librashader-runtime-d3d12",
"librashader-runtime-gl", "librashader-runtime-gl",
"librashader-runtime-vk", "librashader-runtime-vk",
"librashader-spirv-cross",
"windows", "windows",
] ]
@ -1014,9 +1013,9 @@ dependencies = [
[[package]] [[package]]
name = "naga" name = "naga"
version = "0.10.0" version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "262d2840e72dbe250e8cf2f522d080988dfca624c4112c096238a4845f591707" checksum = "5eafe22a23b797c9bc227c6c896419b26b5bb88fa903417a3adaed08778850d5"
dependencies = [ dependencies = [
"bit-set", "bit-set",
"bitflags", "bitflags",

View file

@ -33,7 +33,7 @@ librashader provides both a Rust API under the `librashader` crate, and a C API.
The C API is geared more towards integration with existing projects. The Rust `librashader` crate exposes more The C API is geared more towards integration with existing projects. The Rust `librashader` crate exposes more
of the internals if you wish to use parts of librashader piecemeal. of the internals if you wish to use parts of librashader piecemeal.
The librashader C API is best used by linking statically with `librashader_ld`, which implements a loader that dynamically The librashader C API is best used by including `librashader_ld.h` in your project, which implements a loader that dynamically
loads the librashader (`librashader.so` or `librashader.dll`) implementation in the search path. loads the librashader (`librashader.so` or `librashader.dll`) implementation in the search path.
### Building ### Building
@ -106,35 +106,62 @@ Please report an issue if you run into a shader that works in RetroArch, but not
* Unlike RetroArch, librashader does not have full knowledge of the entire rendering state and is designed to be pluggable * Unlike RetroArch, librashader does not have full knowledge of the entire rendering state and is designed to be pluggable
at any point in your render pipeline. Instead, filter chains terminate at a caller-provided output surface and viewport. at any point in your render pipeline. Instead, filter chains terminate at a caller-provided output surface and viewport.
It is the caller's responsibility to blit the surface back to the backbuffer. It is the caller's responsibility to blit the surface back to the backbuffer.
* Shaders are compiled in parallel where possible. This should noticeably decrease preset compile times. Note that parallel compilation * Shaders are compiled in parallel where possible. This should noticeably decrease preset compile times.
is not available to OpenGL. Parallel shader compilation is not available to OpenGL.
* Runtime-specific differences * HDR10 support is not part of any shader runtime and is not supported by librashader.
* OpenGL
* Copying of in-flight framebuffer contents to history is done via `glBlitFramebuffer` rather than drawing a quad into an intermediate FBO. ### Runtime specific differences
* Sampler objects are used rather than `glTexParameter`. * OpenGL
* Sampler inputs and outputs are not renamed. This is useful for debugging shaders in RenderDoc. * Copying of in-flight framebuffer contents to history is done via `glBlitFramebuffer` rather than drawing a quad into an intermediate FBO.
* UBO and Push Constant Buffer sizes are padded to 16-byte boundaries. * Sampler objects are used rather than `glTexParameter`.
* OpenGL 4.6+ * Sampler inputs and outputs are not renamed. This is useful for debugging shaders in RenderDoc.
* All caveats from the OpenGL 3.3+ section should be considered. * UBO and Push Constant Buffer sizes are padded to 16-byte boundaries.
* Should work on OpenGL 4.5 but this is not guaranteed. The OpenGL 4.6 runtime may eventually switch to using `ARB_spirv_extensions` for loading shaders, and this will not be marked as a breaking change. * OpenGL 4.6+
* The OpenGL 4.6 runtime uses Direct State Access to minimize changes to the OpenGL state. For GPUs released within the last 5 years, this may improve performance. * All caveats from the OpenGL 3.3+ section should be considered.
* Vulkan * Should work on OpenGL 4.5 but this is not guaranteed. The OpenGL 4.6 runtime may eventually switch to using `ARB_spirv_extensions` for loading shaders, and this will not be marked as a breaking change.
* The Vulkan runtime uses [`VK_KHR_dynamic_rendering`](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_dynamic_rendering.html) by default. * The OpenGL 4.6 runtime uses Direct State Access to minimize changes to the OpenGL state. For GPUs released within the last 5 years, this may improve performance.
This extension must be enabled at device creation. Explicit render passes can be used by configuring filter chain options, but may have reduced performance * Vulkan
compared to dynamic rendering. * The Vulkan runtime uses [`VK_KHR_dynamic_rendering`](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_dynamic_rendering.html) by default.
* UBOs use multiple discontiguous buffers. This may be improved in the future by switching to VMA rather than manually handling allocations. This extension must be enabled at device creation. Explicit render passes can be used by configuring filter chain options, but may have reduced performance
* Direct3D 11 compared to dynamic rendering.
* Framebuffer copies are done via `ID3D11DeviceContext::CopySubresourceRegion` rather than a CPU conversion + copy. * UBOs use multiple discontiguous buffers. This may be improved in the future by switching to VMA rather than manually handling allocations.
* HDR10 support is not part of the shader runtime and is not supported. * Direct3D 11
* Direct3D 12 * Framebuffer copies are done via `ID3D11DeviceContext::CopySubresourceRegion` rather than a CPU conversion + copy.
* The Direct3D 12 runtime uses [render passes](https://learn.microsoft.com/en-us/windows/win32/direct3d12/direct3d-12-render-passes). This feature has been available since Windows 10 version 1809, * Direct3D 12
which was released in late 2018. * The Direct3D 12 runtime uses [render passes](https://learn.microsoft.com/en-us/windows/win32/direct3d12/direct3d-12-render-passes). This feature has been available since Windows 10 version 1809,
* For maximum compatibility with shaders, a shader compile pipeline based on [`spirv-to-dxil`](https://github.com/SnowflakePowered/spirv-to-dxil-rs) is used, with the SPIRV-Cross HLSL pipeline used as a fallback. which was released in late 2018.
This brings shader compatibility beyond what the RetroArch Direct3D 12 runtime provides. The HLSL pipeline fallback may be removed in the future as `spirv-to-dxil` improves. * For maximum compatibility with shaders, a shader compile pipeline based on [`spirv-to-dxil`](https://github.com/SnowflakePowered/spirv-to-dxil-rs) is used, with the SPIRV-Cross HLSL pipeline used as a fallback.
This brings shader compatibility beyond what the RetroArch Direct3D 12 runtime provides. The HLSL pipeline fallback may be removed in the future as `spirv-to-dxil` improves.
Most, if not all shader presets should work fine on librashader. The runtime specific differences should not affect the output, Most, if not all shader presets should work fine on librashader. The runtime specific differences should not affect the output,
and are more a heads-up for integrating librashader into your project. and are more a heads-up for integrating librashader into your project.
### Quad vertices and rotations
All runtimes except OpenGL render with an identity matrix MVP and a VBO for with range `[-1, 1]`. The final pass uses a
Quad VBO with range `[0, 1]` and the following projection matrix by default.
```rust
static DEFAULT_MVP: &[f32; 16] = &[
2.0, 0.0, 0.0, 0.0,
0.0, 2.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
-1.0, -1.0, 0.0, 1.0,
];
```
As with RetroArch, a rotation on this MVP will be applied only on the final pass for these runtimes. This is the only way to
pass orientation information to shaders.
The OpenGL runtime uses a VBO for range `[0, 1]` for all passes and the following MVP for all passes.
```rust
static GL_DEFAULT_MVP: &[f32; 16] = &[
2.0, 0.0, 0.0, 0.0,
0.0, 2.0, 0.0, 0.0,
0.0, 0.0, 2.0, 0.0,
-1.0, -1.0, 0.0, 1.0,
];
```
### Writing a librashader Runtime ### Writing a librashader Runtime
If you wish to contribute a runtime implementation not already available, see the [librashader-runtime](https://docs.rs/librashader-runtime/latest/librashader_runtime/) If you wish to contribute a runtime implementation not already available, see the [librashader-runtime](https://docs.rs/librashader-runtime/latest/librashader_runtime/)

View file

@ -16,10 +16,10 @@ crate-type = [ "cdylib", "staticlib" ]
[features] [features]
default = ["runtime-opengl", "runtime-d3d11", "runtime-d3d12", "runtime-vulkan"] default = ["runtime-opengl", "runtime-d3d11", "runtime-d3d12", "runtime-vulkan"]
runtime-opengl = ["gl", "librashader/gl"] runtime-opengl = ["gl", "librashader/runtime-gl"]
runtime-d3d11 = ["windows", "librashader/d3d11", "windows/Win32_Graphics_Direct3D11"] runtime-d3d11 = ["windows", "librashader/runtime-d3d11", "windows/Win32_Graphics_Direct3D11"]
runtime-d3d12 = ["windows", "librashader/d3d12", "windows/Win32_Graphics_Direct3D12"] runtime-d3d12 = ["windows", "librashader/runtime-d3d12", "windows/Win32_Graphics_Direct3D12"]
runtime-vulkan = ["ash", "librashader/vk"] runtime-vulkan = ["ash", "librashader/runtime-vk"]
[dependencies] [dependencies]
librashader = { path = "../librashader", version = "0.1.0-beta.14", features = ["internal"] } librashader = { path = "../librashader", version = "0.1.0-beta.14", features = ["internal"] }

View file

@ -13,7 +13,7 @@ description = "RetroArch shaders for all."
[dependencies] [dependencies]
shaderc = { version = "0.8.2", features = [] } shaderc = { version = "0.8.2", features = [] }
spirv_cross = { package = "librashader-spirv-cross", version = "0.23", features = [ "glsl", "hlsl" ] } bytemuck = "1.13.0"
thiserror = "1.0.37" thiserror = "1.0.37"
bitflags = "1.3.2" bitflags = "1.3.2"
@ -23,14 +23,15 @@ librashader-common = { path = "../librashader-common", version = "0.1.0-beta.14"
librashader-preprocess = { path = "../librashader-preprocess", version = "0.1.0-beta.14" } librashader-preprocess = { path = "../librashader-preprocess", version = "0.1.0-beta.14" }
librashader-presets = { path = "../librashader-presets", version = "0.1.0-beta.14" } librashader-presets = { path = "../librashader-presets", version = "0.1.0-beta.14" }
spirv_cross = { package = "librashader-spirv-cross", version = "0.23", optional = true }
spirv-to-dxil = { version = "0.3", optional = true } spirv-to-dxil = { version = "0.3", optional = true }
naga = { version = "0.10.0", features = ["glsl-in", "spv-in", "spv-out", "glsl-out", "wgsl-out"], optional = true } naga = { version = "0.11.0", features = ["glsl-in", "spv-in", "spv-out", "glsl-out", "wgsl-out"], optional = true }
bytemuck = "1.13.0"
rspirv = { version = "0.11.0+1.5.4", optional = true } rspirv = { version = "0.11.0+1.5.4", optional = true }
[features] [features]
default = ["dxil"] default = ["cross", "dxil"]
unstable-naga = [ "naga", "rspirv" ] unstable-naga = [ "naga", "rspirv" ]
standalone = ["shaderc/build-from-source"] standalone = ["shaderc/build-from-source"]
dxil = ["spirv-to-dxil"] dxil = ["spirv-to-dxil"]
cross = [ "spirv_cross", "spirv_cross/glsl", "spirv_cross/hlsl" ]

View file

@ -5,11 +5,11 @@ use crate::front::GlslangCompilation;
use crate::reflect::cross::{CompiledProgram, GlslReflect, HlslReflect}; use crate::reflect::cross::{CompiledProgram, GlslReflect, HlslReflect};
use crate::reflect::ReflectShader; use crate::reflect::ReflectShader;
/// The GLSL version to use. /// The GLSL version to target.
pub type GlslVersion = spirv_cross::glsl::Version; pub use spirv_cross::glsl::Version as GlslVersion;
/// The HLSL shader model version to use /// The HLSL shader model version to target.
pub type HlslVersion = spirv_cross::hlsl::ShaderModel; pub use spirv_cross::hlsl::ShaderModel as HlslShaderModel;
/// The context for a GLSL compilation via spirv-cross. /// The context for a GLSL compilation via spirv-cross.
pub struct CrossGlslContext { pub struct CrossGlslContext {
@ -43,7 +43,7 @@ pub struct CrossHlslContext {
impl FromCompilation<GlslangCompilation> for HLSL { impl FromCompilation<GlslangCompilation> for HLSL {
type Target = HLSL; type Target = HLSL;
type Options = Option<HlslVersion>; type Options = Option<HlslShaderModel>;
type Context = CrossHlslContext; type Context = CrossHlslContext;
type Output = impl CompileShader<Self::Target, Options = Self::Options, Context = Self::Context> type Output = impl CompileShader<Self::Target, Options = Self::Options, Context = Self::Context>
+ ReflectShader; + ReflectShader;

View file

@ -9,11 +9,10 @@ use crate::reflect::semantics::{
use crate::reflect::{align_uniform_size, ReflectShader}; use crate::reflect::{align_uniform_size, ReflectShader};
use std::ops::Deref; use std::ops::Deref;
use spirv_cross::hlsl::ShaderModel;
use spirv_cross::spirv::{Ast, Decoration, Module, Resource, ShaderResources, Type}; use spirv_cross::spirv::{Ast, Decoration, Module, Resource, ShaderResources, Type};
use spirv_cross::{glsl, hlsl, ErrorCode}; use spirv_cross::{glsl, hlsl, ErrorCode};
use crate::back::cross::{CrossGlslContext, CrossHlslContext, HlslVersion}; use crate::back::cross::{CrossGlslContext, CrossHlslContext, HlslShaderModel};
use crate::back::targets::{GLSL, HLSL}; use crate::back::targets::{GLSL, HLSL};
use crate::back::{CompileShader, ShaderCompilerOutput}; use crate::back::{CompileShader, ShaderCompilerOutput};
use crate::reflect::helper::{SemanticErrorBlame, TextureData, UboData}; use crate::reflect::helper::{SemanticErrorBlame, TextureData, UboData};
@ -826,14 +825,14 @@ impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
} }
impl CompileShader<HLSL> for CrossReflect<hlsl::Target> { impl CompileShader<HLSL> for CrossReflect<hlsl::Target> {
type Options = Option<HlslVersion>; type Options = Option<HlslShaderModel>;
type Context = CrossHlslContext; type Context = CrossHlslContext;
fn compile( fn compile(
mut self, mut self,
options: Self::Options, options: Self::Options,
) -> Result<ShaderCompilerOutput<String, CrossHlslContext>, ShaderCompileError> { ) -> Result<ShaderCompilerOutput<String, CrossHlslContext>, ShaderCompileError> {
let sm = options.unwrap_or(ShaderModel::V5_0); let sm = options.unwrap_or(HlslShaderModel::V5_0);
let mut options = hlsl::CompilerOptions::default(); let mut options = hlsl::CompilerOptions::default();
options.shader_model = sm; options.shader_model = sm;

View file

@ -3,10 +3,10 @@ use gl::types::{GLsizei, GLsizeiptr, GLuint};
#[rustfmt::skip] #[rustfmt::skip]
static QUAD_VBO_DATA: &[f32; 16] = &[ static QUAD_VBO_DATA: &[f32; 16] = &[
0.0f32, 0.0f32, 0.0f32, 0.0f32, 0.0, 0.0, 0.0, 0.0,
1.0f32, 0.0f32, 1.0f32, 0.0f32, 1.0, 0.0, 1.0, 0.0,
0.0f32, 1.0f32, 0.0f32, 1.0f32, 0.0, 1.0, 0.0, 1.0,
1.0f32, 1.0f32, 1.0f32, 1.0f32, 1.0, 1.0, 1.0, 1.0,
]; ];
pub struct Gl3DrawQuad { pub struct Gl3DrawQuad {

View file

@ -3,10 +3,10 @@ use gl::types::{GLint, GLsizeiptr, GLuint};
#[rustfmt::skip] #[rustfmt::skip]
static QUAD_VBO_DATA: &[f32; 16] = &[ static QUAD_VBO_DATA: &[f32; 16] = &[
0.0f32, 0.0f32, 0.0f32, 0.0f32, 0.0, 0.0, 0.0, 0.0,
1.0f32, 0.0f32, 1.0f32, 0.0f32, 1.0, 0.0, 1.0, 0.0,
0.0f32, 1.0f32, 0.0f32, 1.0f32, 0.0, 1.0, 0.0, 1.0,
1.0f32, 1.0f32, 1.0f32, 1.0f32, 1.0, 1.0, 1.0, 1.0,
]; ];
pub struct Gl46DrawQuad { pub struct Gl46DrawQuad {

View file

@ -24,23 +24,33 @@ librashader-runtime-gl = { path = "../librashader-runtime-gl", version = "0.1.0-
librashader-runtime-vk = { path = "../librashader-runtime-vk", version = "0.1.0-beta.14", optional = true } librashader-runtime-vk = { path = "../librashader-runtime-vk", version = "0.1.0-beta.14", optional = true }
ash = { version = "0.37.1+1.3.235", optional = true } ash = { version = "0.37.1+1.3.235", optional = true }
spirv_cross = { package = "librashader-spirv-cross", version = "0.23", features = ["glsl", "hlsl"], optional = true }
[target.'cfg(windows)'.dependencies.windows] [target.'cfg(windows)'.dependencies.windows]
version = "0.44.0" version = "0.44.0"
optional = true optional = true
[features] [features]
default = ["gl", "d3d11", "d3d12", "vk", "reflect", "preprocess", "presets" ] # core features and definitions
gl = [ "runtime", "librashader-common/opengl", "librashader-runtime-gl", "spirv_cross" ]
d3d11 = [ "runtime", "librashader-common/d3d11", "librashader-runtime-d3d11", "windows/Win32_Graphics_Direct3D11" ]
d3d12 = [ "runtime", "librashader-reflect/dxil", "librashader-common/d3d12", "librashader-runtime-d3d12", "windows/Win32_Graphics_Direct3D12" ]
vk = ["runtime", "librashader-common/vulkan", "librashader-runtime-vk", "ash" ]
runtime = [] runtime = []
reflect = [] reflect = []
preprocess = [] preprocess = []
presets = [] presets = []
# runtimes
runtime-gl = [ "runtime", "reflect-cross", "librashader-common/opengl", "librashader-runtime-gl" ]
runtime-d3d11 = [ "runtime", "reflect-cross","librashader-common/d3d11", "librashader-runtime-d3d11", "windows/Win32_Graphics_Direct3D11" ]
runtime-d3d12 = [ "runtime", "reflect-cross", "reflect-dxil", "librashader-common/d3d12", "librashader-runtime-d3d12", "windows/Win32_Graphics_Direct3D12" ]
runtime-vk = ["runtime", "reflect-cross", "librashader-common/vulkan", "librashader-runtime-vk", "ash" ]
# reflection
reflect-cross = ["reflect", "librashader-reflect/cross"]
reflect-dxil = ["reflect", "librashader-reflect/dxil"]
runtime-all = ["runtime-gl", "runtime-d3d11", "runtime-d3d12", "runtime-vk"]
reflect-all = ["reflect-cross", "reflect-dxil"]
# enable all features by default
default = [ "runtime-all", "reflect-all", "preprocess", "presets" ]
internal = [] internal = []
[package.metadata.docs.rs] [package.metadata.docs.rs]

View file

@ -145,14 +145,18 @@ pub mod reflect {
}; };
/// Reflection via SPIRV-Cross. /// Reflection via SPIRV-Cross.
#[cfg(feature = "reflect-cross")]
#[doc(cfg(feature = "reflect-cross"))]
pub mod cross { pub mod cross {
pub use librashader_reflect::front::GlslangCompilation; pub use librashader_reflect::front::GlslangCompilation;
/// The version of GLSL to target. /// The version of GLSL to target.
pub use spirv_cross::glsl::Version as GlslVersion; ///
pub use librashader_reflect::back::cross::GlslVersion;
/// The HLSL Shader Model to target. /// The HLSL Shader Model to target.
pub use spirv_cross::hlsl::ShaderModel as HlslVersion; ///
pub use librashader_reflect::back::cross::HlslShaderModel;
pub use librashader_reflect::back::cross::CrossGlslContext; pub use librashader_reflect::back::cross::CrossGlslContext;
@ -164,6 +168,8 @@ pub mod reflect {
} }
/// DXIL reflection via spirv-to-dxil. /// DXIL reflection via spirv-to-dxil.
#[cfg(feature = "reflect-dxil")]
#[doc(cfg(feature = "reflect-dxil"))]
pub mod dxil { pub mod dxil {
/// The maximum shader model to use when compiling the DXIL blob. /// The maximum shader model to use when compiling the DXIL blob.
pub use librashader_reflect::back::dxil::ShaderModel; pub use librashader_reflect::back::dxil::ShaderModel;
@ -194,13 +200,13 @@ pub mod runtime {
pub use librashader_common::{Size, Viewport}; pub use librashader_common::{Size, Viewport};
pub use librashader_runtime::parameters::FilterChainParameters; pub use librashader_runtime::parameters::FilterChainParameters;
#[cfg(feature = "gl")] #[cfg(feature = "runtime-gl")]
#[doc(cfg(feature = "gl"))] #[doc(cfg(feature = "runtime-gl"))]
/// Shader runtime for OpenGL 3.3+. /// Shader runtime for OpenGL 3.3+.
/// ///
/// DSA support requires OpenGL 4.6. /// DSA support requires OpenGL 4.6.
/// ///
/// Note that the OpenGL runtime requires `gl` to be /// The OpenGL runtime requires `gl` to be
/// initialized with [`gl::load_with`](https://docs.rs/gl/0.14.0/gl/fn.load_with.html). /// initialized with [`gl::load_with`](https://docs.rs/gl/0.14.0/gl/fn.load_with.html).
pub mod gl { pub mod gl {
pub use librashader_runtime_gl::{ pub use librashader_runtime_gl::{
@ -219,8 +225,8 @@ pub mod runtime {
} }
} }
#[cfg(all(target_os = "windows", feature = "d3d11"))] #[cfg(all(target_os = "windows", feature = "runtime-d3d11"))]
#[doc(cfg(all(target_os = "windows", feature = "d3d11")))] #[doc(cfg(all(target_os = "windows", feature = "runtime-d3d11")))]
/// Shader runtime for Direct3D 11. /// Shader runtime for Direct3D 11.
pub mod d3d11 { pub mod d3d11 {
pub use librashader_runtime_d3d11::{ pub use librashader_runtime_d3d11::{
@ -241,8 +247,8 @@ pub mod runtime {
} }
} }
#[cfg(all(target_os = "windows", feature = "d3d12"))] #[cfg(all(target_os = "windows", feature = "runtime-d3d12"))]
#[doc(cfg(all(target_os = "windows", feature = "d3d12")))] #[doc(cfg(all(target_os = "windows", feature = "runtime-d3d12")))]
/// Shader runtime for Direct3D 12. /// Shader runtime for Direct3D 12.
pub mod d3d12 { pub mod d3d12 {
pub use librashader_runtime_d3d12::{ pub use librashader_runtime_d3d12::{
@ -263,8 +269,8 @@ pub mod runtime {
} }
} }
#[cfg(feature = "vk")] #[cfg(feature = "runtime-vk")]
#[doc(cfg(feature = "vk"))] #[doc(cfg(feature = "runtime-vk"))]
/// Shader runtime for Vulkan. /// Shader runtime for Vulkan.
pub mod vk { pub mod vk {
pub use librashader_runtime_vk::{ pub use librashader_runtime_vk::{