cache: clean up cache api
This commit is contained in:
parent
83422de1f7
commit
2ca6aecfe4
|
@ -3,6 +3,6 @@
|
|||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/test/slang-shaders" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/test/shaders_slang" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
32
Cargo.lock
generated
32
Cargo.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -5,7 +5,7 @@ use rusqlite::{params, Connection, DatabaseName};
|
|||
use std::error::Error;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn get_cache_dir() -> Result<PathBuf, Box<dyn Error>> {
|
||||
pub(crate) fn get_cache_dir() -> Result<PathBuf, Box<dyn Error>> {
|
||||
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<PathBuf, Box<dyn Error>> {
|
|||
Ok(cache_dir)
|
||||
}
|
||||
|
||||
pub fn get_cache() -> Result<Connection, Box<dyn Error>> {
|
||||
pub(crate) fn get_cache() -> Result<Connection, Box<dyn Error>> {
|
||||
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<T, H, const KEY_SIZE: usize>(
|
||||
index: &str,
|
||||
key: &[H; KEY_SIZE],
|
||||
transform: impl FnOnce(Vec<u8>) -> T,
|
||||
) -> Option<T>
|
||||
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<E, T, R, H, const KEY_SIZE: usize>(
|
||||
/// 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<E, T, R, H, const KEY_SIZE: usize>(
|
||||
index: &str,
|
||||
keys: &[H; KEY_SIZE],
|
||||
factory: impl FnOnce(&[H; KEY_SIZE]) -> Result<T, E>,
|
||||
attempt: impl Fn(T) -> Result<R, E>,
|
||||
do_cache: bool,
|
||||
load: impl Fn(T) -> Result<R, E>,
|
||||
bypass_cache: bool,
|
||||
) -> Result<R, E>
|
||||
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<E, T, R, const KEY_SIZE: usize>(
|
||||
index: &str,
|
||||
keys: &[&dyn CacheKey; KEY_SIZE],
|
||||
attempt: impl Fn(Option<Vec<u8>>) -> Result<R, E>,
|
||||
factory: impl FnOnce(&R) -> Result<T, E>,
|
||||
do_cache: bool,
|
||||
restore_pipeline: impl Fn(Option<Vec<u8>>) -> Result<R, E>,
|
||||
fetch_pipeline_state: impl FnOnce(&R) -> Result<T, E>,
|
||||
bypass_cache: bool,
|
||||
) -> Result<R, E>
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/// Trait for objects that are cacheable.
|
||||
pub trait Cacheable {
|
||||
fn from_bytes(bytes: &[u8]) -> Option<Self>
|
||||
where
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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<dyn Error>),
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<D3D12GraphicsPipeline> {
|
||||
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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -47,7 +47,7 @@ impl CompileProgram for Gl4CompileProgram {
|
|||
) -> crate::error::Result<(GLuint, UniformLocation<GLuint>)> {
|
||||
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 {
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<VulkanGraphicsPipeline> {
|
||||
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 {
|
||||
|
|
Loading…
Reference in a new issue