diff --git a/.idea/vcs.xml b/.idea/vcs.xml index a875303..7d50221 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -3,6 +3,6 @@ - + \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index e0258f0..91b80a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1162,15 +1162,6 @@ dependencies = [ "windows", ] -[[package]] -name = "librashader-common" -version = "0.1.0-rc.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff30c28bf8007f8061a3e429378a5d3682e61d15fe81825c9e5076a3091e349" -dependencies = [ - "num-traits", -] - [[package]] name = "librashader-common" version = "0.1.0-rc.3" @@ -1181,6 +1172,15 @@ dependencies = [ "windows", ] +[[package]] +name = "librashader-common" +version = "0.1.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e22634fcfd3d0307db6d31366bb6bdd4422ec18a889a18ebe5572e47f366989" +dependencies = [ + "num-traits", +] + [[package]] name = "librashader-preprocess" version = "0.1.0-rc.3" @@ -1188,7 +1188,7 @@ dependencies = [ "encoding_rs", "glob", "librashader-common 0.1.0-rc.3", - "librashader-presets 0.1.0-rc.2", + "librashader-presets 0.1.0-rc.3 (registry+https://github.com/rust-lang/crates.io-index)", "nom", "rayon", "rustc-hash", @@ -1197,11 +1197,10 @@ dependencies = [ [[package]] name = "librashader-presets" -version = "0.1.0-rc.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de7bfd6903b4c52db1d220cb67d9e618ba87922300893586b2cf360b7591bde6" +version = "0.1.0-rc.3" dependencies = [ - "librashader-common 0.1.0-rc.2", + "glob", + "librashader-common 0.1.0-rc.3", "nom", "nom_locate", "num-traits", @@ -1211,9 +1210,10 @@ dependencies = [ [[package]] name = "librashader-presets" version = "0.1.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ba84e8b4fdb76114d56f0ad2118e2cfbdde0666dd95e657afa4803c6f19bfee" dependencies = [ - "glob", - "librashader-common 0.1.0-rc.3", + "librashader-common 0.1.0-rc.3 (registry+https://github.com/rust-lang/crates.io-index)", "nom", "nom_locate", "num-traits", diff --git a/librashader-cache/Cargo.toml b/librashader-cache/Cargo.toml index 006564e..a2d3cf9 100644 --- a/librashader-cache/Cargo.toml +++ b/librashader-cache/Cargo.toml @@ -12,8 +12,8 @@ description = "RetroArch shaders for all." [dependencies] serde = { version = "1.0" } -librashader-reflect = { path = "../librashader-reflect", version = "0.1.0-rc.2", features = ["serialize", "dxil"] } -librashader-preprocess = { path = "../librashader-preprocess", version = "0.1.0-rc.2" } +librashader-reflect = { path = "../librashader-reflect", version = "0.1.0-rc.3", features = ["serialize", "dxil"] } +librashader-preprocess = { path = "../librashader-preprocess", version = "0.1.0-rc.3" } platform-dirs = "0.3.0" blake3 = { version = "1.3.3", features = ["rayon"] } thiserror = "1.0.38" diff --git a/librashader-cache/src/cache.rs b/librashader-cache/src/cache.rs index d617366..65920b8 100644 --- a/librashader-cache/src/cache.rs +++ b/librashader-cache/src/cache.rs @@ -5,7 +5,7 @@ use rusqlite::{params, Connection, DatabaseName}; use std::error::Error; use std::path::PathBuf; -pub fn get_cache_dir() -> Result> { +pub(crate) fn get_cache_dir() -> Result> { let cache_dir = if let Some(cache_dir) = AppDirs::new(Some("librashader"), false).map(|a| a.cache_dir) { cache_dir @@ -20,7 +20,7 @@ pub fn get_cache_dir() -> Result> { Ok(cache_dir) } -pub fn get_cache() -> Result> { +pub(crate) fn get_cache() -> Result> { let cache_dir = get_cache_dir()?; let mut conn = Connection::open(&cache_dir.join("librashader.db"))?; @@ -62,55 +62,29 @@ pub(crate) fn set_blob(conn: &Connection, index: &str, key: &[u8], value: &[u8]) } } -pub fn get_cached_blob( - index: &str, - key: &[H; KEY_SIZE], - transform: impl FnOnce(Vec) -> T, -) -> Option -where - H: CacheKey, -{ - let cache = get_cache(); - - let Ok(cache) = cache else { - return None - }; - - let key = { - let mut hasher = blake3::Hasher::new(); - for subkeys in key { - hasher.update(subkeys.hash_bytes()); - } - let hash = hasher.finalize(); - hash - }; - - let Ok(blob) = get_blob(&cache, index, key.as_bytes()) else { - return None; - }; - - Some(transform(blob)) -} - -pub fn cache_object( +/// Cache a shader object (usually bytecode) created by the keyed objects. +/// +/// - `factory` is the function that compiles the values passed as keys to a shader object. +/// - `load` tries to load a compiled shader object to a driver-specialized result. +pub fn cache_shader_object( index: &str, keys: &[H; KEY_SIZE], factory: impl FnOnce(&[H; KEY_SIZE]) -> Result, - attempt: impl Fn(T) -> Result, - do_cache: bool, + load: impl Fn(T) -> Result, + bypass_cache: bool, ) -> Result where H: CacheKey, T: Cacheable, { - if !do_cache { - return Ok(attempt(factory(keys)?)?); + if bypass_cache { + return Ok(load(factory(keys)?)?); } let cache = get_cache(); let Ok(cache) = cache else { - return Ok(attempt(factory(keys)?)?); + return Ok(load(factory(keys)?)?); }; let hashkey = { @@ -124,7 +98,7 @@ where 'attempt: { if let Ok(blob) = get_blob(&cache, index, hashkey.as_bytes()) { - let cached = T::from_bytes(&blob).map(&attempt); + let cached = T::from_bytes(&blob).map(&load); match cached { None => break 'attempt, @@ -139,27 +113,34 @@ where if let Some(slice) = T::to_bytes(&blob) { set_blob(&cache, index, hashkey.as_bytes(), &slice); } - Ok(attempt(blob)?) + Ok(load(blob)?) } +/// Cache a pipeline state object. +/// +/// Keys are not used to create the object and are only used to uniquely identify the pipeline state. +/// +/// - `restore_pipeline` tries to restore the pipeline with either a cached binary pipeline state +/// cache, or create a new pipeline if no cached value is available. +/// - `fetch_pipeline_state` fetches the new pipeline state cache after the pipeline was created. pub fn cache_pipeline( index: &str, keys: &[&dyn CacheKey; KEY_SIZE], - attempt: impl Fn(Option>) -> Result, - factory: impl FnOnce(&R) -> Result, - do_cache: bool, + restore_pipeline: impl Fn(Option>) -> Result, + fetch_pipeline_state: impl FnOnce(&R) -> Result, + bypass_cache: bool, ) -> Result where T: Cacheable, { - if !do_cache { - return Ok(attempt(None)?); + if bypass_cache { + return Ok(restore_pipeline(None)?); } let cache = get_cache(); let Ok(cache) = cache else { - return Ok(attempt(None)?); + return Ok(restore_pipeline(None)?); }; let hashkey = { @@ -173,7 +154,7 @@ where let pipeline = 'attempt: { if let Ok(blob) = get_blob(&cache, index, hashkey.as_bytes()) { - let cached = attempt(Some(blob)); + let cached = restore_pipeline(Some(blob)); match cached { Ok(res) => { break 'attempt res; @@ -182,11 +163,11 @@ where } } - attempt(None)? + restore_pipeline(None)? }; // update the pso every time just in case. - if let Ok(state) = factory(&pipeline) { + if let Ok(state) = fetch_pipeline_state(&pipeline) { if let Some(slice) = T::to_bytes(&state) { set_blob(&cache, index, hashkey.as_bytes(), &slice); } diff --git a/librashader-cache/src/cacheable.rs b/librashader-cache/src/cacheable.rs index 55ca531..45acf53 100644 --- a/librashader-cache/src/cacheable.rs +++ b/librashader-cache/src/cacheable.rs @@ -1,3 +1,4 @@ +/// Trait for objects that are cacheable. pub trait Cacheable { fn from_bytes(bytes: &[u8]) -> Option where diff --git a/librashader-cache/src/compilation.rs b/librashader-cache/src/compilation.rs index 8247c24..65ea665 100644 --- a/librashader-cache/src/compilation.rs +++ b/librashader-cache/src/compilation.rs @@ -1,3 +1,4 @@ +//! Cache helpers for `ShaderCompilation` objects to cache compiled SPIRV. use crate::cache::{get_blob, get_cache, set_blob}; use librashader_preprocess::ShaderSource; use librashader_reflect::back::targets::{DXIL, GLSL, HLSL, SPIRV}; diff --git a/librashader-cache/src/error.rs b/librashader-cache/src/error.rs deleted file mode 100644 index 8d291c7..0000000 --- a/librashader-cache/src/error.rs +++ /dev/null @@ -1,10 +0,0 @@ -use std::error::Error; -use thiserror::Error; - -#[derive(Debug, Error)] -pub enum CacheError { - #[error("serde error")] - SerdeError, - #[error("unknown error")] - UnknownError(#[from] Box), -} diff --git a/librashader-cache/src/lib.rs b/librashader-cache/src/lib.rs index 3b61ba7..ff2c41c 100644 --- a/librashader-cache/src/lib.rs +++ b/librashader-cache/src/lib.rs @@ -2,20 +2,18 @@ //! //! This crate is exempt from semantic versioning guarantees and is an implementation //! detail of librashader runtimes. -#![feature(try_blocks)] -#![feature(once_cell)] -pub mod cache; -pub mod compilation; -pub mod error; +mod cache; +mod compilation; mod key; mod cacheable; -#[cfg(test)] -mod tests {} - pub use cacheable::Cacheable; pub use key::CacheKey; +pub use compilation::CachedCompilation; +pub use cache::cache_pipeline; +pub use cache::cache_shader_object; + #[cfg(all(target_os = "windows", feature = "d3d"))] mod d3d; diff --git a/librashader-preprocess/Cargo.toml b/librashader-preprocess/Cargo.toml index d1aab03..af13d32 100644 --- a/librashader-preprocess/Cargo.toml +++ b/librashader-preprocess/Cargo.toml @@ -23,6 +23,6 @@ default = [ "line_directives" ] line_directives = [] [dev-dependencies] -librashader-presets = "0.1.0-beta.16" +librashader-presets = "0.1.0-rc.3" glob = "0.3.1" rayon = "1.6.1" diff --git a/librashader-runtime-d3d11/src/filter_chain.rs b/librashader-runtime-d3d11/src/filter_chain.rs index 080d34c..912078f 100644 --- a/librashader-runtime-d3d11/src/filter_chain.rs +++ b/librashader-runtime-d3d11/src/filter_chain.rs @@ -22,8 +22,8 @@ use crate::options::{FilterChainOptionsD3D11, FrameOptionsD3D11}; use crate::samplers::SamplerSet; use crate::util::d3d11_compile_bound_shader; use crate::{error, util, D3D11OutputView}; -use librashader_cache::cache::cache_object; -use librashader_cache::compilation::CachedCompilation; +use librashader_cache::cache_shader_object; +use librashader_cache::CachedCompilation; use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact}; use librashader_runtime::binding::{BindingUtil, TextureInput}; use librashader_runtime::framebuffer::FramebufferInit; @@ -230,7 +230,7 @@ impl FilterChainD3D11 { let reflection = reflect.reflect(index, semantics)?; let hlsl = reflect.compile(None)?; - let (vs, vertex_dxbc) = cache_object( + let (vs, vertex_dxbc) = cache_shader_object( "dxbc", &[hlsl.vertex.as_bytes()], |&[bytes]| util::d3d_compile_shader(bytes, b"main\0", b"vs_5_0\0"), @@ -245,20 +245,20 @@ impl FilterChainD3D11 { blob, )) }, - !disable_cache, + disable_cache, )?; let ia_desc = DrawQuad::get_spirv_cross_vbo_desc(); let vao = util::d3d11_create_input_layout(device, &ia_desc, &vertex_dxbc)?; - let ps = cache_object( + let ps = cache_shader_object( "dxbc", &[hlsl.fragment.as_bytes()], |&[bytes]| util::d3d_compile_shader(bytes, b"main\0", b"ps_5_0\0"), |blob| { d3d11_compile_bound_shader(device, &blob, None, ID3D11Device::CreatePixelShader) }, - !disable_cache, + disable_cache, )?; let ubo_cbuffer = if let Some(ubo) = &reflection.ubo && ubo.size != 0 { diff --git a/librashader-runtime-d3d12/src/filter_chain.rs b/librashader-runtime-d3d12/src/filter_chain.rs index 89533f8..0d81a8c 100644 --- a/librashader-runtime-d3d12/src/filter_chain.rs +++ b/librashader-runtime-d3d12/src/filter_chain.rs @@ -46,7 +46,7 @@ use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_UNKNOWN; use windows::Win32::System::Threading::{CreateEventA, WaitForSingleObject}; use windows::Win32::System::WindowsProgramming::INFINITE; -use librashader_cache::compilation::CachedCompilation; +use librashader_cache::CachedCompilation; use librashader_runtime::framebuffer::FramebufferInit; use librashader_runtime::render_target::RenderTarget; use librashader_runtime::scaling::ScaleFramebuffer; diff --git a/librashader-runtime-d3d12/src/graphics_pipeline.rs b/librashader-runtime-d3d12/src/graphics_pipeline.rs index 908ae26..944a58e 100644 --- a/librashader-runtime-d3d12/src/graphics_pipeline.rs +++ b/librashader-runtime-d3d12/src/graphics_pipeline.rs @@ -2,7 +2,7 @@ use crate::error::assume_d3d12_init; use crate::error::FilterChainError::Direct3DOperationError; use crate::quad_render::DrawQuad; use crate::{error, util}; -use librashader_cache::cache::{cache_object, cache_pipeline}; +use librashader_cache::{cache_shader_object, cache_pipeline}; use librashader_reflect::back::cross::CrossHlslContext; use librashader_reflect::back::dxil::DxilObject; use librashader_reflect::back::ShaderCompilerOutput; @@ -248,7 +248,7 @@ impl D3D12GraphicsPipeline { let cached_pso = pso.GetCachedBlob()?; Ok(cached_pso) }, - !disable_cache, + disable_cache, )? }; @@ -324,20 +324,20 @@ impl D3D12GraphicsPipeline { )); } - let vertex_dxil = cache_object( + let vertex_dxil = cache_shader_object( "dxil", &[shader_assembly.vertex.deref()], |&[source]| util::dxc_validate_shader(library, validator, source), |f| Ok(f), - !disable_cache, + disable_cache, )?; - let fragment_dxil = cache_object( + let fragment_dxil = cache_shader_object( "dxil", &[shader_assembly.fragment.deref()], |&[source]| util::dxc_validate_shader(library, validator, source), |f| Ok(f), - !disable_cache, + disable_cache, )?; Self::new_from_blobs( @@ -359,20 +359,20 @@ impl D3D12GraphicsPipeline { render_format: DXGI_FORMAT, disable_cache: bool, ) -> error::Result { - let vertex_dxil = cache_object( + let vertex_dxil = cache_shader_object( "dxil", &[shader_assembly.vertex.as_bytes()], |&[source]| util::dxc_compile_shader(library, dxc, source, u16cstr!("vs_6_0")), |f| Ok(f), - !disable_cache, + disable_cache, )?; - let fragment_dxil = cache_object( + let fragment_dxil = cache_shader_object( "dxil", &[shader_assembly.fragment.as_bytes()], |&[source]| util::dxc_compile_shader(library, dxc, source, u16cstr!("ps_6_0")), |f| Ok(f), - !disable_cache, + disable_cache, )?; Self::new_from_blobs( diff --git a/librashader-runtime-gl/src/filter_chain/filter_impl.rs b/librashader-runtime-gl/src/filter_chain/filter_impl.rs index 6db4bfa..8ce15c0 100644 --- a/librashader-runtime-gl/src/filter_chain/filter_impl.rs +++ b/librashader-runtime-gl/src/filter_chain/filter_impl.rs @@ -19,7 +19,7 @@ use librashader_reflect::back::{CompileReflectShader, CompileShader}; use librashader_reflect::front::GlslangCompilation; use librashader_reflect::reflect::semantics::{ShaderSemantics, UniformMeta}; -use librashader_cache::compilation::CachedCompilation; +use librashader_cache::CachedCompilation; use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact}; use librashader_reflect::reflect::ReflectShader; use librashader_runtime::binding::BindingUtil; diff --git a/librashader-runtime-gl/src/gl/gl46/compile_program.rs b/librashader-runtime-gl/src/gl/gl46/compile_program.rs index 6ada90b..971c39c 100644 --- a/librashader-runtime-gl/src/gl/gl46/compile_program.rs +++ b/librashader-runtime-gl/src/gl/gl46/compile_program.rs @@ -47,7 +47,7 @@ impl CompileProgram for Gl4CompileProgram { ) -> crate::error::Result<(GLuint, UniformLocation)> { let vertex_resources = glsl.context.artifact.vertex.get_shader_resources()?; - let program = librashader_cache::cache::cache_object( + let program = librashader_cache::cache_shader_object( "opengl4", &[glsl.vertex.as_str(), glsl.fragment.as_str()], |&[vertex, fragment]| unsafe { @@ -120,7 +120,7 @@ impl CompileProgram for Gl4CompileProgram { } return Ok(program); }, - cache, + !cache, )?; let ubo_location = unsafe { diff --git a/librashader-runtime-gl/src/options.rs b/librashader-runtime-gl/src/options.rs index 4bf1e67..493f6f0 100644 --- a/librashader-runtime-gl/src/options.rs +++ b/librashader-runtime-gl/src/options.rs @@ -18,11 +18,10 @@ pub struct FilterChainOptionsGL { /// The GLSL version. Should be at least `330`. pub glsl_version: u16, /// Whether or not to use the Direct State Access APIs. Only available on OpenGL 4.5+. - /// This is required to use shader caching. + /// If this is off, compiled program caching will not be available. pub use_dsa: bool, /// Whether or not to explicitly disable mipmap generation regardless of shader preset settings. pub force_no_mipmaps: bool, - /// Disable the shader object cache. Shaders will be - /// recompiled rather than loaded from the cache. + /// Disable the shader object cache. Shaders will be recompiled rather than loaded from the cache. pub disable_cache: bool, } diff --git a/librashader-runtime-vk/src/filter_chain.rs b/librashader-runtime-vk/src/filter_chain.rs index c888e43..a4417ef 100644 --- a/librashader-runtime-vk/src/filter_chain.rs +++ b/librashader-runtime-vk/src/filter_chain.rs @@ -32,7 +32,7 @@ use std::convert::Infallible; use std::path::Path; use std::sync::Arc; -use librashader_cache::compilation::CachedCompilation; +use librashader_cache::CachedCompilation; use librashader_runtime::framebuffer::FramebufferInit; use librashader_runtime::render_target::RenderTarget; use librashader_runtime::scaling::ScaleFramebuffer; @@ -442,7 +442,7 @@ impl FilterChainVulkan { &reflection, frames_in_flight, render_pass_format, - !disable_cache, + disable_cache, )?; Ok(FilterPass { diff --git a/librashader-runtime-vk/src/graphics_pipeline.rs b/librashader-runtime-vk/src/graphics_pipeline.rs index 19fd93b..3e0b258 100644 --- a/librashader-runtime-vk/src/graphics_pipeline.rs +++ b/librashader-runtime-vk/src/graphics_pipeline.rs @@ -4,7 +4,7 @@ use ash::vk; use crate::error::FilterChainError; use crate::framebuffer::OutputImage; use crate::render_pass::VulkanRenderPass; -use librashader_cache::cache::cache_pipeline; +use librashader_cache::cache_pipeline; use librashader_reflect::back::ShaderCompilerOutput; use librashader_reflect::reflect::semantics::{TextureBinding, UboReflection}; use librashader_reflect::reflect::ShaderReflection; @@ -314,7 +314,7 @@ impl VulkanGraphicsPipeline { reflection: &ShaderReflection, replicas: u32, render_pass_format: vk::Format, - cache_objects: bool, + bypass_cache: bool, ) -> error::Result { let pipeline_layout = PipelineLayoutObjects::new(reflection, replicas, device)?; @@ -359,7 +359,7 @@ impl VulkanGraphicsPipeline { Ok::<_, FilterChainError>((pipeline, pipeline_cache)) }, |(_pipeline, cache)| unsafe { Ok(device.get_pipeline_cache_data(*cache)?) }, - cache_objects, + bypass_cache, )?; Ok(VulkanGraphicsPipeline {