From 32c99d9f4a03d291746372d422d8b2c6979b3989 Mon Sep 17 00:00:00 2001 From: chyyran Date: Tue, 1 Oct 2024 02:04:58 -0400 Subject: [PATCH] rt: implement filter chain loading in terms of pack --- Cargo.lock | 10 ++- librashader-pack/Cargo.toml | 1 - librashader-pack/src/lib.rs | 1 - librashader-reflect/Cargo.toml | 1 + librashader-reflect/src/reflect/presets.rs | 30 ++++---- librashader-runtime-d3d11/Cargo.toml | 1 + librashader-runtime-d3d11/src/filter_chain.rs | 70 +++++++++++++---- librashader-runtime-d3d12/Cargo.toml | 1 + librashader-runtime-d3d12/src/filter_chain.rs | 73 +++++++++++++----- .../tests/hello_triangle/mod.rs | 6 +- librashader-runtime-d3d9/Cargo.toml | 3 +- librashader-runtime-d3d9/src/filter_chain.rs | 47 ++++++++---- librashader-runtime-gl/Cargo.toml | 1 + .../src/filter_chain/chain.rs | 18 +++-- .../src/filter_chain/mod.rs | 17 ++++- librashader-runtime-gl/src/gl/gl3/lut_load.rs | 50 ++++++------ .../src/gl/gl46/lut_load.rs | 24 +++--- librashader-runtime-gl/src/gl/mod.rs | 5 +- librashader-runtime-mtl/Cargo.toml | 1 + librashader-runtime-mtl/src/filter_chain.rs | 70 ++++++++++++----- librashader-runtime-mtl/src/luts.rs | 2 +- librashader-runtime-vk/Cargo.toml | 1 + librashader-runtime-vk/src/filter_chain.rs | 76 +++++++++++++------ librashader-runtime-wgpu/Cargo.toml | 1 + librashader-runtime-wgpu/src/filter_chain.rs | 76 ++++++++++++------- librashader-runtime/src/image.rs | 22 +++++- 26 files changed, 414 insertions(+), 194 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d4e33cd..0f627ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1641,7 +1641,6 @@ dependencies = [ "image", "librashader-preprocess", "librashader-presets", - "librashader-reflect", "rayon", "rmp-serde", "serde", @@ -1687,6 +1686,7 @@ dependencies = [ "bytemuck", "glslang", "librashader-common", + "librashader-pack", "librashader-preprocess", "librashader-presets", "naga", @@ -1724,6 +1724,7 @@ dependencies = [ "gfx-maths", "librashader-cache", "librashader-common", + "librashader-pack", "librashader-preprocess", "librashader-presets", "librashader-reflect", @@ -1746,6 +1747,7 @@ dependencies = [ "gpu-allocator 0.27.0", "librashader-cache", "librashader-common", + "librashader-pack", "librashader-preprocess", "librashader-presets", "librashader-reflect", @@ -1767,11 +1769,13 @@ dependencies = [ "gfx-maths", "librashader-cache", "librashader-common", + "librashader-pack", "librashader-preprocess", "librashader-presets", "librashader-reflect", "librashader-runtime", "num-traits", + "rayon", "thiserror", "windows 0.58.0", "windows-core 0.58.0", @@ -1787,6 +1791,7 @@ dependencies = [ "glow 0.14.1", "librashader-cache", "librashader-common", + "librashader-pack", "librashader-preprocess", "librashader-presets", "librashader-reflect", @@ -1803,6 +1808,7 @@ dependencies = [ "array-concat", "bytemuck", "librashader-common", + "librashader-pack", "librashader-preprocess", "librashader-presets", "librashader-reflect", @@ -1828,6 +1834,7 @@ dependencies = [ "gpu-allocator 0.27.0", "librashader-cache", "librashader-common", + "librashader-pack", "librashader-preprocess", "librashader-presets", "librashader-reflect", @@ -1850,6 +1857,7 @@ dependencies = [ "env_logger", "librashader-cache", "librashader-common", + "librashader-pack", "librashader-preprocess", "librashader-presets", "librashader-reflect", diff --git a/librashader-pack/Cargo.toml b/librashader-pack/Cargo.toml index c398150..c75bf1a 100644 --- a/librashader-pack/Cargo.toml +++ b/librashader-pack/Cargo.toml @@ -13,7 +13,6 @@ description = "RetroArch shaders for all." [dependencies] librashader-presets = { path = "../librashader-presets", version = "0.4.5", features = ["serde"] } librashader-preprocess = { path = "../librashader-preprocess", version = "0.4.5", features = ["serde"] } -librashader-reflect= { path = "../librashader-reflect", version = "0.4.5" } thiserror = "1.0.64" serde = { version = "1.0", features = ["derive"], optional = true } diff --git a/librashader-pack/src/lib.rs b/librashader-pack/src/lib.rs index 2ed22e6..10dd487 100644 --- a/librashader-pack/src/lib.rs +++ b/librashader-pack/src/lib.rs @@ -87,7 +87,6 @@ impl LoadableResource for TextureMeta { /// The configuration for a single shader pass. pub type ShaderPassData = ShaderPresetResource; pub type TextureData = ShaderPresetResource; - /// A shader preset, not reliant on disk, with all information needed. #[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] diff --git a/librashader-reflect/Cargo.toml b/librashader-reflect/Cargo.toml index bd1415e..7cec6e5 100644 --- a/librashader-reflect/Cargo.toml +++ b/librashader-reflect/Cargo.toml @@ -21,6 +21,7 @@ bitflags = "2.4.2" librashader-common = { path = "../librashader-common", version = "0.4.5" } librashader-preprocess = { path = "../librashader-preprocess", version = "0.4.5" } librashader-presets = { path = "../librashader-presets", version = "0.4.5" } +librashader-pack = { path = "../librashader-pack", version = "0.4.5" } spirv-cross2 = { workspace = true, optional = true } diff --git a/librashader-reflect/src/reflect/presets.rs b/librashader-reflect/src/reflect/presets.rs index 16c77f1..47605e1 100644 --- a/librashader-reflect/src/reflect/presets.rs +++ b/librashader-reflect/src/reflect/presets.rs @@ -6,8 +6,9 @@ use crate::reflect::semantics::{ Semantic, ShaderSemantics, TextureSemantics, UniformSemantic, UniqueSemantics, }; use librashader_common::map::{FastHashMap, ShortString}; +use librashader_pack::ShaderPassData; use librashader_preprocess::{PreprocessError, ShaderSource}; -use librashader_presets::{ShaderPassConfig, ShaderPassMeta, ShaderPreset, TextureConfig}; +use librashader_presets::{ShaderPassMeta, ShaderPreset, TextureMeta}; /// Artifacts of a reflected and compiled shader pass. /// @@ -36,9 +37,9 @@ impl CompilePresetTarget for T {} pub trait CompilePresetTarget: OutputTarget { /// Compile passes of a shader preset given the applicable /// shader output target, compilation type, and resulting error. - fn compile_preset_passes( - passes: Vec, - textures: &[TextureConfig], + fn compile_preset_passes<'a, I, R, E>( + passes: Vec, + textures: impl Iterator, ) -> Result< ( Vec>::Output>>, @@ -61,9 +62,9 @@ pub trait CompilePresetTarget: OutputTarget { /// Compile passes of a shader preset given the applicable /// shader output target, compilation type, and resulting error. -fn compile_preset_passes( - passes: Vec, - textures: &[TextureConfig], +fn compile_preset_passes<'a, T, I, R, E>( + passes: Vec, + textures: impl Iterator, ) -> Result< ( Vec>::Output>>, @@ -87,8 +88,7 @@ where let passes = passes .into_iter() .map(|shader| { - let source: ShaderSource = ShaderSource::load(&shader.path)?; - + let source = shader.data; let compiled = I::Compiler::compile(&source)?; let reflect = T::from_compilation(compiled)?; @@ -188,17 +188,17 @@ fn insert_pass_semantics( } /// Insert the available semantics for the input texture config into the provided semantic maps. -fn insert_lut_semantics( - textures: &[TextureConfig], +fn insert_lut_semantics<'a>( + textures: impl Iterator, uniform_semantics: &mut FastHashMap, texture_semantics: &mut FastHashMap>, ) { - for (index, texture) in textures.iter().enumerate() { - let mut size_semantic = texture.meta.name.clone(); + for (index, texture) in textures.enumerate() { + let mut size_semantic = texture.name.clone(); size_semantic.push_str("Size"); texture_semantics.insert( - texture.meta.name.clone(), + texture.name.clone(), Semantic { semantics: TextureSemantics::User, index, @@ -261,7 +261,7 @@ impl ShaderSemantics { config.meta.id as usize, ); insert_lut_semantics( - preset.textures.as_slice(), + preset.textures.iter().map(|t| &t.meta), &mut uniform_semantics, &mut texture_semantics, ); diff --git a/librashader-runtime-d3d11/Cargo.toml b/librashader-runtime-d3d11/Cargo.toml index 48057de..1fdeb65 100644 --- a/librashader-runtime-d3d11/Cargo.toml +++ b/librashader-runtime-d3d11/Cargo.toml @@ -15,6 +15,7 @@ description = "RetroArch shaders for all." librashader-common = { path = "../librashader-common", features = ["d3d11"], version = "0.4.5" } librashader-presets = { path = "../librashader-presets", version = "0.4.5" } librashader-preprocess = { path = "../librashader-preprocess", version = "0.4.5" } +librashader-pack = { path = "../librashader-pack", version = "0.4.5" } librashader-reflect = { path = "../librashader-reflect", version = "0.4.5" } librashader-runtime = { path = "../librashader-runtime", version = "0.4.5" } librashader-cache = { path = "../librashader-cache", version = "0.4.5", features = ["d3d"] } diff --git a/librashader-runtime-d3d11/src/filter_chain.rs b/librashader-runtime-d3d11/src/filter_chain.rs index 551bc8c..f3092b1 100644 --- a/librashader-runtime-d3d11/src/filter_chain.rs +++ b/librashader-runtime-d3d11/src/filter_chain.rs @@ -2,13 +2,13 @@ use crate::texture::InputTexture; use librashader_common::{ImageFormat, Size, Viewport}; use librashader_common::map::FastHashMap; -use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig}; +use librashader_presets::ShaderPreset; use librashader_reflect::back::targets::HLSL; use librashader_reflect::back::{CompileReflectShader, CompileShader}; use librashader_reflect::front::SpirvCompilation; use librashader_reflect::reflect::semantics::ShaderSemantics; use librashader_reflect::reflect::ReflectShader; -use librashader_runtime::image::{Image, ImageError, UVDirection}; +use librashader_runtime::image::{ImageError, LoadedTexture, UVDirection, RGBA8}; use std::collections::VecDeque; use std::path::Path; @@ -75,6 +75,7 @@ pub(crate) struct FilterCommon { mod compile { use super::*; + use librashader_pack::{ShaderPassData, TextureData}; #[cfg(not(feature = "stable"))] pub type ShaderPassMeta = @@ -86,8 +87,8 @@ mod compile { >; pub fn compile_passes( - shaders: Vec, - textures: &[TextureConfig], + shaders: Vec, + textures: &[TextureData], disable_cache: bool, ) -> Result<(Vec, ShaderSemantics), FilterChainError> { let (passes, semantics) = if !disable_cache { @@ -95,10 +96,11 @@ mod compile { CachedCompilation, SpirvCross, FilterChainError, - >(shaders, &textures)? + >(shaders, textures.iter().map(|t| &t.meta))? } else { HLSL::compile_preset_passes::( - shaders, &textures, + shaders, + textures.iter().map(|t| &t.meta), )? }; @@ -107,6 +109,7 @@ mod compile { } use compile::{compile_passes, ShaderPassMeta}; +use librashader_pack::{ShaderPresetPack, TextureData}; use librashader_runtime::parameters::RuntimeParameters; impl FilterChainD3D11 { @@ -132,6 +135,16 @@ impl FilterChainD3D11 { unsafe { Self::load_from_preset_deferred(preset, device, &immediate_context, options) } } + /// Load a filter chain from a pre-parsed and loaded `ShaderPresetPack`. + pub unsafe fn load_from_pack( + preset: ShaderPresetPack, + device: &ID3D11Device, + options: Option<&FilterChainOptionsD3D11>, + ) -> error::Result { + let immediate_context = unsafe { device.GetImmediateContext()? }; + unsafe { Self::load_from_pack_deferred(preset, device, &immediate_context, options) } + } + /// Load a filter chain from a pre-parsed `ShaderPreset`, deferring and GPU-side initialization /// to the caller. This function is therefore requires no external synchronization of the /// immediate context, as long as the immediate context is not used as the input context, @@ -152,6 +165,31 @@ impl FilterChainD3D11 { device: &ID3D11Device, ctx: &ID3D11DeviceContext, options: Option<&FilterChainOptionsD3D11>, + ) -> error::Result { + let preset = ShaderPresetPack::load_from_preset::(preset)?; + unsafe { Self::load_from_pack_deferred(preset, device, ctx, options) } + } + + /// Load a filter chain from a pre-parsed and loaded `ShaderPresetPack`, deferring and GPU-side initialization + /// to the caller. This function is therefore requires no external synchronization of the + /// immediate context, as long as the immediate context is not used as the input context, + /// nor of the device, as long as the device is not single-threaded only. + /// + /// ## Safety + /// The provided context must either be immediate, or immediately submitted after this function + /// returns, **before drawing frames**, or lookup textures will fail to load and the filter chain + /// will be in an invalid state. + /// + /// If the context is deferred, it must be ready for command recording, and have no prior commands + /// recorded. No commands shall be recorded after, the caller must immediately call [`FinishCommandList`](https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-finishcommandlist) + /// and execute the command list on the immediate context after this function returns. + /// + /// If the context is immediate, then access to the immediate context requires external synchronization. + pub unsafe fn load_from_pack_deferred( + preset: ShaderPresetPack, + device: &ID3D11Device, + ctx: &ID3D11DeviceContext, + options: Option<&FilterChainOptionsD3D11>, ) -> error::Result { let disable_cache = options.map_or(false, |o| o.disable_cache); @@ -165,7 +203,7 @@ impl FilterChainD3D11 { let immediate_context = unsafe { device.GetImmediateContext()? }; // load luts - let luts = FilterChainD3D11::load_luts(device, &ctx, &preset.textures)?; + let luts = FilterChainD3D11::load_luts(device, &ctx, preset.textures)?; let framebuffer_gen = || OwnedImage::new(device, Size::new(1, 1), ImageFormat::R8G8B8A8Unorm, false); @@ -361,21 +399,21 @@ impl FilterChainD3D11 { fn load_luts( device: &ID3D11Device, context: &ID3D11DeviceContext, - textures: &[TextureConfig], + textures: Vec, ) -> error::Result> { let mut luts = FastHashMap::default(); - let images = textures - .par_iter() - .map(|texture| Image::load(&texture.path, UVDirection::TopLeft)) - .collect::, ImageError>>()?; + let textures = textures + .into_par_iter() + .map(|texture| LoadedTexture::from_texture(texture, UVDirection::TopLeft)) + .collect::>, ImageError>>()?; - for (index, (texture, image)) in textures.iter().zip(images).enumerate() { + for (index, LoadedTexture { meta, image }) in textures.iter().enumerate() { let desc = D3D11_TEXTURE2D_DESC { Width: image.size.width, Height: image.size.height, Format: DXGI_FORMAT_R8G8B8A8_UNORM, Usage: D3D11_USAGE_DEFAULT, - MiscFlags: if texture.meta.mipmap { + MiscFlags: if meta.mipmap { D3D11_RESOURCE_MISC_GENERATE_MIPS.0 as u32 } else { 0 @@ -388,8 +426,8 @@ impl FilterChainD3D11 { context, &image, desc, - texture.meta.filter_mode, - texture.meta.wrap_mode, + meta.filter_mode, + meta.wrap_mode, )?; luts.insert(index, texture); } diff --git a/librashader-runtime-d3d12/Cargo.toml b/librashader-runtime-d3d12/Cargo.toml index 3dfb14a..b7e6105 100644 --- a/librashader-runtime-d3d12/Cargo.toml +++ b/librashader-runtime-d3d12/Cargo.toml @@ -16,6 +16,7 @@ librashader-common = { path = "../librashader-common", features = ["d3d12"], ver librashader-presets = { path = "../librashader-presets", version = "0.4.5" } librashader-preprocess = { path = "../librashader-preprocess", version = "0.4.5" } librashader-reflect = { path = "../librashader-reflect", version = "0.4.5", features = ["dxil"] } +librashader-pack = { path = "../librashader-pack", version = "0.4.5" } librashader-runtime = { path = "../librashader-runtime", version = "0.4.5" } librashader-cache = { path = "../librashader-cache", version = "0.4.5", features = ["d3d"] } diff --git a/librashader-runtime-d3d12/src/filter_chain.rs b/librashader-runtime-d3d12/src/filter_chain.rs index 5cc5d98..aaf202b 100644 --- a/librashader-runtime-d3d12/src/filter_chain.rs +++ b/librashader-runtime-d3d12/src/filter_chain.rs @@ -17,7 +17,7 @@ use d3d12_descriptor_heap::{ use gpu_allocator::d3d12::{Allocator, AllocatorCreateDesc, ID3D12DeviceVersion}; use librashader_common::map::FastHashMap; use librashader_common::{ImageFormat, Size, Viewport}; -use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig}; +use librashader_presets::ShaderPreset; use librashader_reflect::back::targets::{DXIL, HLSL}; use librashader_reflect::back::{CompileReflectShader, CompileShader}; use librashader_reflect::front::SpirvCompilation; @@ -25,7 +25,7 @@ use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtif use librashader_reflect::reflect::semantics::{ShaderSemantics, MAX_BINDINGS_COUNT}; use librashader_reflect::reflect::ReflectShader; use librashader_runtime::binding::{BindingUtil, TextureInput}; -use librashader_runtime::image::{Image, ImageError, UVDirection}; +use librashader_runtime::image::{ImageError, LoadedTexture, UVDirection}; use librashader_runtime::quad::QuadType; use librashader_runtime::uniforms::UniformStorage; use parking_lot::Mutex; @@ -175,6 +175,7 @@ impl Drop for FrameResiduals { mod compile { use super::*; + use librashader_pack::ShaderPassData; #[cfg(not(feature = "stable"))] pub type DxilShaderPassMeta = @@ -186,8 +187,8 @@ mod compile { >; pub fn compile_passes_dxil( - shaders: Vec, - textures: &[TextureConfig], + shaders: Vec, + textures: &[TextureData], disable_cache: bool, ) -> Result<(Vec, ShaderSemantics), FilterChainError> { let (passes, semantics) = if !disable_cache { @@ -195,10 +196,11 @@ mod compile { CachedCompilation, SpirvCross, FilterChainError, - >(shaders, &textures)? + >(shaders, textures.iter().map(|t| &t.meta))? } else { DXIL::compile_preset_passes::( - shaders, &textures, + shaders, + textures.iter().map(|t| &t.meta), )? }; @@ -215,8 +217,8 @@ mod compile { >; pub fn compile_passes_hlsl( - shaders: Vec, - textures: &[TextureConfig], + shaders: Vec, + textures: &[TextureData], disable_cache: bool, ) -> Result<(Vec, ShaderSemantics), FilterChainError> { let (passes, semantics) = if !disable_cache { @@ -224,10 +226,11 @@ mod compile { CachedCompilation, SpirvCross, FilterChainError, - >(shaders, &textures)? + >(shaders, textures.iter().map(|t| &t.meta))? } else { HLSL::compile_preset_passes::( - shaders, &textures, + shaders, + textures.iter().map(|t| &t.meta), )? }; @@ -237,6 +240,7 @@ mod compile { use crate::resource::OutlivesFrame; use compile::{compile_passes_dxil, compile_passes_hlsl, DxilShaderPassMeta, HlslShaderPassMeta}; +use librashader_pack::{ShaderPresetPack, TextureData}; use librashader_runtime::parameters::RuntimeParameters; impl FilterChainD3D12 { @@ -257,6 +261,16 @@ impl FilterChainD3D12 { preset: ShaderPreset, device: &ID3D12Device, options: Option<&FilterChainOptionsD3D12>, + ) -> error::Result { + let preset = ShaderPresetPack::load_from_preset::(preset)?; + unsafe { Self::load_from_pack(preset, device, options) } + } + + /// Load a filter chain from a pre-parsed `ShaderPreset`. + pub unsafe fn load_from_pack( + preset: ShaderPresetPack, + device: &ID3D12Device, + options: Option<&FilterChainOptionsD3D12>, ) -> error::Result { unsafe { // 1 time queue infrastructure for lut uploads @@ -275,7 +289,7 @@ impl FilterChainD3D12 { let fence_event = CreateEventA(None, false, false, None)?; let fence: ID3D12Fence = device.CreateFence(0, D3D12_FENCE_FLAG_NONE)?; - let filter_chain = Self::load_from_preset_deferred(preset, device, &cmd, options)?; + let filter_chain = Self::load_from_pack_deferred(preset, device, &cmd, options)?; cmd.Close()?; queue.ExecuteCommandLists(&[Some(cmd.cast()?)]); @@ -303,6 +317,23 @@ impl FilterChainD3D12 { device: &ID3D12Device, cmd: &ID3D12GraphicsCommandList, options: Option<&FilterChainOptionsD3D12>, + ) -> error::Result { + let preset = ShaderPresetPack::load_from_preset::(preset)?; + unsafe { Self::load_from_pack_deferred(preset, device, cmd, options) } + } + + /// Load a filter chain from a pre-parsed, loaded `ShaderPresetPack`, deferring and GPU-side initialization + /// to the caller. This function therefore requires no external synchronization of the device queue. + /// + /// ## Safety + /// The provided command list must be ready for recording and contain no prior commands. + /// The caller is responsible for ending the command list and immediately submitting it to a + /// graphics queue. The command list must be completely executed before calling [`frame`](Self::frame). + pub unsafe fn load_from_pack_deferred( + preset: ShaderPresetPack, + device: &ID3D12Device, + cmd: &ID3D12GraphicsCommandList, + options: Option<&FilterChainOptionsD3D12>, ) -> error::Result { let shader_count = preset.shaders.len(); let lut_count = preset.textures.len(); @@ -364,7 +395,7 @@ impl FilterChainD3D12 { &mut staging_heap, &mut mipmap_heap, &mut residuals, - &preset.textures, + preset.textures, )?; let framebuffer_gen = || { @@ -430,27 +461,27 @@ impl FilterChainD3D12 { staging_heap: &mut D3D12DescriptorHeap, mipmap_heap: &mut D3D12DescriptorHeap, gc: &mut FrameResiduals, - textures: &[TextureConfig], + textures: Vec, ) -> error::Result> { // use separate mipgen to load luts. let mipmap_gen = D3D12MipmapGen::new(device, true)?; let mut luts = FastHashMap::default(); - let images = textures - .par_iter() - .map(|texture| Image::load(&texture.path, UVDirection::TopLeft)) - .collect::, ImageError>>()?; + let textures = textures + .into_par_iter() + .map(|texture| LoadedTexture::from_texture(texture, UVDirection::TopLeft)) + .collect::, ImageError>>()?; - for (index, (texture, image)) in textures.iter().zip(images).enumerate() { + for (index, LoadedTexture { meta, image }) in textures.iter().enumerate() { let texture = LutTexture::new( device, allocator, staging_heap, cmd, &image, - texture.meta.filter_mode, - texture.meta.wrap_mode, - texture.meta.mipmap, + meta.filter_mode, + meta.wrap_mode, + meta.mipmap, gc, )?; luts.insert(index, texture); diff --git a/librashader-runtime-d3d12/tests/hello_triangle/mod.rs b/librashader-runtime-d3d12/tests/hello_triangle/mod.rs index 5d9fe56..e3f9fcf 100644 --- a/librashader-runtime-d3d12/tests/hello_triangle/mod.rs +++ b/librashader-runtime-d3d12/tests/hello_triangle/mod.rs @@ -619,9 +619,9 @@ pub mod d3d12_hello_triangle { filter .frame( command_list, - D3D12InputImage { - resource: resources.framebuffer.to_ref(), - descriptor: Some(framebuffer), + D3D12InputImage::External { + resource: resources.framebuffer.clone(), + descriptor: framebuffer, }, &Viewport { x: 0.0, diff --git a/librashader-runtime-d3d9/Cargo.toml b/librashader-runtime-d3d9/Cargo.toml index 9968aa9..c67c3fa 100644 --- a/librashader-runtime-d3d9/Cargo.toml +++ b/librashader-runtime-d3d9/Cargo.toml @@ -16,6 +16,7 @@ librashader-common = { path = "../librashader-common", features = ["d3d9", "d3d1 librashader-presets = { path = "../librashader-presets", version = "0.4.5" } librashader-preprocess = { path = "../librashader-preprocess", version = "0.4.5" } librashader-reflect = { path = "../librashader-reflect", version = "0.4.5" } +librashader-pack = { path = "../librashader-pack", version = "0.4.5" } librashader-runtime = { path = "../librashader-runtime", version = "0.4.5" } librashader-cache = { path = "../librashader-cache", version = "0.4.5", features = ["d3d"] } @@ -23,7 +24,7 @@ thiserror = "1.0.37" bytemuck = "1.12.3" array-concat = "0.5.2" num-traits = "0.2.18" - +rayon = "1.10.0" windows-core = "0.58.0" [features] diff --git a/librashader-runtime-d3d9/src/filter_chain.rs b/librashader-runtime-d3d9/src/filter_chain.rs index 0e1a76a..f6e06fb 100644 --- a/librashader-runtime-d3d9/src/filter_chain.rs +++ b/librashader-runtime-d3d9/src/filter_chain.rs @@ -12,7 +12,7 @@ use librashader_cache::{cache_shader_object, CachedCompilation}; use librashader_common::map::FastHashMap; use librashader_common::{ImageFormat, Size, Viewport}; use librashader_presets::context::VideoDriver; -use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig}; +use librashader_presets::ShaderPreset; use librashader_reflect::back::hlsl::HlslShaderModel; use librashader_reflect::back::targets::HLSL; use librashader_reflect::back::{CompileReflectShader, CompileShader}; @@ -23,16 +23,18 @@ use librashader_reflect::reflect::semantics::ShaderSemantics; use librashader_reflect::reflect::ReflectShader; use librashader_runtime::binding::{BindingUtil, TextureInput}; use librashader_runtime::framebuffer::FramebufferInit; -use librashader_runtime::image::{Image, ImageError, UVDirection, BGRA8}; +use librashader_runtime::image::{ImageError, LoadedTexture, UVDirection, BGRA8}; use librashader_runtime::quad::QuadType; use librashader_runtime::render_target::RenderTarget; use librashader_runtime::scaling::ScaleFramebuffer; use librashader_runtime::uniforms::UniformStorage; use std::collections::VecDeque; -use std::path::Path; - use librashader_common::GetSize; +use rayon::iter::IntoParallelIterator; +use rayon::iter::ParallelIterator; + +use std::path::Path; use windows::Win32::Graphics::Direct3D9::{IDirect3DDevice9, IDirect3DSurface9, IDirect3DTexture9}; @@ -61,6 +63,7 @@ pub struct FilterChainD3D9 { mod compile { use super::*; + use librashader_pack::{ShaderPassData, TextureData}; #[cfg(not(feature = "stable"))] pub type ShaderPassMeta = @@ -72,8 +75,8 @@ mod compile { >; pub fn compile_passes( - shaders: Vec, - textures: &[TextureConfig], + shaders: Vec, + textures: &[TextureData], disable_cache: bool, ) -> Result<(Vec, ShaderSemantics), FilterChainError> { let (passes, semantics) = if !disable_cache { @@ -81,10 +84,11 @@ mod compile { CachedCompilation, SpirvCross, FilterChainError, - >(shaders, &textures)? + >(shaders, textures.iter().map(|t| &t.meta))? } else { HLSL::compile_preset_passes::( - shaders, &textures, + shaders, + textures.iter().map(|t| &t.meta), )? }; @@ -93,6 +97,7 @@ mod compile { } use compile::{compile_passes, ShaderPassMeta}; +use librashader_pack::{ShaderPresetPack, TextureData}; use librashader_runtime::parameters::RuntimeParameters; impl FilterChainD3D9 { @@ -184,16 +189,16 @@ impl FilterChainD3D9 { fn load_luts( device: &IDirect3DDevice9, - textures: &[TextureConfig], + textures: Vec, ) -> error::Result> { let mut luts = FastHashMap::default(); let images = textures - .iter() - .map(|texture| Image::load(&texture.path, UVDirection::TopLeft)) - .collect::>, ImageError>>()?; + .into_par_iter() + .map(|texture| LoadedTexture::from_texture(texture, UVDirection::TopLeft)) + .collect::>, ImageError>>()?; - for (index, (texture, image)) in textures.iter().zip(images).enumerate() { - let texture = LutTexture::new(device, &image, &texture.meta)?; + for (index, LoadedTexture { meta, image }) in images.iter().enumerate() { + let texture = LutTexture::new(device, &image, &meta)?; luts.insert(index, texture); } Ok(luts) @@ -213,11 +218,21 @@ impl FilterChainD3D9 { unsafe { Self::load_from_preset(preset, device, options) } } - /// Load a filter chain from a pre-parsed `ShaderPreset`. + /// Load a filter chain from a pre-parsed and loaded `ShaderPresetPack`. pub unsafe fn load_from_preset( preset: ShaderPreset, device: &IDirect3DDevice9, options: Option<&FilterChainOptionsD3D9>, + ) -> error::Result { + let preset = ShaderPresetPack::load_from_preset::(preset)?; + unsafe { Self::load_from_pack(preset, device, options) } + } + + /// Load a filter chain from a pre-parsed `ShaderPreset`. + pub unsafe fn load_from_pack( + preset: ShaderPresetPack, + device: &IDirect3DDevice9, + options: Option<&FilterChainOptionsD3D9>, ) -> error::Result { let disable_cache = options.map_or(false, |o| o.disable_cache); @@ -229,7 +244,7 @@ impl FilterChainD3D9 { let filters = FilterChainD3D9::init_passes(device, passes, &semantics, disable_cache)?; // load luts - let luts = FilterChainD3D9::load_luts(device, &preset.textures)?; + let luts = FilterChainD3D9::load_luts(device, preset.textures)?; let framebuffer_gen = || D3D9Texture::new(device, Size::new(1, 1), ImageFormat::R8G8B8A8Unorm, false); diff --git a/librashader-runtime-gl/Cargo.toml b/librashader-runtime-gl/Cargo.toml index 44b6e3d..9258164 100644 --- a/librashader-runtime-gl/Cargo.toml +++ b/librashader-runtime-gl/Cargo.toml @@ -16,6 +16,7 @@ librashader-common = { path = "../librashader-common", features = ["opengl"], ve librashader-presets = { path = "../librashader-presets", version = "0.4.5" } librashader-preprocess = { path = "../librashader-preprocess", version = "0.4.5" } librashader-reflect = { path = "../librashader-reflect", version = "0.4.5" } +librashader-pack = { path = "../librashader-pack", version = "0.4.5" } librashader-runtime = { path = "../librashader-runtime" , version = "0.4.5" } librashader-cache = { path = "../librashader-cache", version = "0.4.5" } diff --git a/librashader-runtime-gl/src/filter_chain/chain.rs b/librashader-runtime-gl/src/filter_chain/chain.rs index 33fee52..567ce68 100644 --- a/librashader-runtime-gl/src/filter_chain/chain.rs +++ b/librashader-runtime-gl/src/filter_chain/chain.rs @@ -12,7 +12,6 @@ use crate::util::{gl_get_version, gl_u16_to_version}; use crate::{error, GLImage}; use librashader_common::Viewport; -use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig}; use librashader_reflect::back::glsl::GlslVersion; use librashader_reflect::back::targets::GLSL; use librashader_reflect::back::{CompileReflectShader, CompileShader}; @@ -22,6 +21,7 @@ use librashader_reflect::reflect::semantics::{ShaderSemantics, UniformMeta}; use glow::HasContext; use librashader_cache::CachedCompilation; use librashader_common::map::FastHashMap; +use librashader_pack::{ShaderPassData, ShaderPresetPack, TextureData}; use librashader_reflect::reflect::cross::SpirvCross; use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact}; use librashader_reflect::reflect::ReflectShader; @@ -30,6 +30,7 @@ use librashader_runtime::framebuffer::FramebufferInit; use librashader_runtime::quad::QuadType; use librashader_runtime::render_target::RenderTarget; use librashader_runtime::scaling::ScaleFramebuffer; + use std::collections::VecDeque; use std::sync::Arc; @@ -107,8 +108,8 @@ mod compile { >; pub fn compile_passes( - shaders: Vec, - textures: &[TextureConfig], + shaders: Vec, + textures: &[TextureData], disable_cache: bool, ) -> Result<(Vec, ShaderSemantics), FilterChainError> { let (passes, semantics) = if !disable_cache { @@ -116,10 +117,11 @@ mod compile { CachedCompilation, SpirvCross, FilterChainError, - >(shaders, &textures)? + >(shaders, textures.iter().map(|t| &t.meta))? } else { GLSL::compile_preset_passes::( - shaders, &textures, + shaders, + textures.iter().map(|t| &t.meta), )? }; @@ -132,8 +134,8 @@ use librashader_runtime::parameters::RuntimeParameters; impl FilterChainImpl { /// Load a filter chain from a pre-parsed `ShaderPreset`. - pub(crate) unsafe fn load_from_preset( - preset: ShaderPreset, + pub(crate) unsafe fn load_from_pack( + preset: ShaderPresetPack, context: Arc, options: Option<&FilterChainOptionsGL>, ) -> error::Result { @@ -156,7 +158,7 @@ impl FilterChainImpl { let samplers = SamplerSet::new(&context)?; // load luts - let luts = T::LoadLut::load_luts(&context, &preset.textures)?; + let luts = T::LoadLut::load_luts(&context, preset.textures)?; let framebuffer_gen = || T::FramebufferInterface::new(&context, 1); let input_gen = || InputTexture { diff --git a/librashader-runtime-gl/src/filter_chain/mod.rs b/librashader-runtime-gl/src/filter_chain/mod.rs index 3a87095..bc787bb 100644 --- a/librashader-runtime-gl/src/filter_chain/mod.rs +++ b/librashader-runtime-gl/src/filter_chain/mod.rs @@ -14,6 +14,7 @@ mod parameters; pub(crate) use chain::FilterCommon; use librashader_common::Viewport; +use librashader_pack::ShaderPresetPack; use librashader_presets::context::VideoDriver; /// An OpenGL filter chain. @@ -22,23 +23,33 @@ pub struct FilterChainGL { } impl FilterChainGL { - /// Load a filter chain from a pre-parsed `ShaderPreset`. + /// Load a filter chain from a pre-parsed and loaded `ShaderPresetPack`. pub unsafe fn load_from_preset( preset: ShaderPreset, ctx: Arc, options: Option<&FilterChainOptionsGL>, + ) -> Result { + let preset = ShaderPresetPack::load_from_preset::(preset)?; + unsafe { Self::load_from_pack(preset, ctx, options) } + } + + /// Load a filter chain from a pre-parsed and loaded `ShaderPresetPack`. + pub unsafe fn load_from_pack( + preset: ShaderPresetPack, + ctx: Arc, + options: Option<&FilterChainOptionsGL>, ) -> Result { let result = catch_unwind(|| { if options.is_some_and(|options| options.use_dsa) { return Ok(Self { filter: FilterChainDispatch::DirectStateAccess(unsafe { - FilterChainImpl::load_from_preset(preset, ctx, options)? + FilterChainImpl::load_from_pack(preset, ctx, options)? }), }); } Ok(Self { filter: FilterChainDispatch::Compatibility(unsafe { - FilterChainImpl::load_from_preset(preset, ctx, options)? + FilterChainImpl::load_from_pack(preset, ctx, options)? }), }) }); diff --git a/librashader-runtime-gl/src/gl/gl3/lut_load.rs b/librashader-runtime-gl/src/gl/gl3/lut_load.rs index 780b126..3408f0d 100644 --- a/librashader-runtime-gl/src/gl/gl3/lut_load.rs +++ b/librashader-runtime-gl/src/gl/gl3/lut_load.rs @@ -4,8 +4,8 @@ use crate::gl::LoadLut; use crate::texture::InputTexture; use glow::{HasContext, PixelUnpackData}; use librashader_common::map::FastHashMap; -use librashader_presets::TextureConfig; -use librashader_runtime::image::{Image, ImageError, UVDirection}; +use librashader_pack::TextureData; +use librashader_runtime::image::{ImageError, LoadedTexture, UVDirection}; use librashader_runtime::scaling::MipmapSize; use rayon::prelude::*; use std::num::NonZeroU32; @@ -13,29 +13,31 @@ use std::num::NonZeroU32; pub struct Gl3LutLoad; impl LoadLut for Gl3LutLoad { fn load_luts( - ctx: &glow::Context, - textures: &[TextureConfig], + context: &glow::Context, + textures: Vec, ) -> Result> { let mut luts = FastHashMap::default(); - let pixel_unpack = unsafe { ctx.get_parameter_i32(glow::PIXEL_UNPACK_BUFFER_BINDING) }; + let pixel_unpack = unsafe { context.get_parameter_i32(glow::PIXEL_UNPACK_BUFFER_BINDING) }; - let images = textures - .par_iter() - .map(|texture| Image::load(&texture.path, UVDirection::TopLeft)) - .collect::, ImageError>>()?; + let textures = textures + .into_par_iter() + .map(|texture| LoadedTexture::from_texture(texture, UVDirection::TopLeft)) + .collect::, ImageError>>()?; - for (index, (texture, image)) in textures.iter().zip(images).enumerate() { - let levels = if texture.meta.mipmap { + for (index, LoadedTexture { meta, image }) in textures.iter().enumerate() { + let levels = if meta.mipmap { image.size.calculate_miplevels() } else { 1u32 }; let handle = unsafe { - let handle = ctx.create_texture().map_err(FilterChainError::GlError)?; + let handle = context + .create_texture() + .map_err(FilterChainError::GlError)?; - ctx.bind_texture(glow::TEXTURE_2D, Some(handle)); - ctx.tex_storage_2d( + context.bind_texture(glow::TEXTURE_2D, Some(handle)); + context.tex_storage_2d( glow::TEXTURE_2D, levels as i32, glow::RGBA8, @@ -43,11 +45,11 @@ impl LoadLut for Gl3LutLoad { image.size.height as i32, ); - ctx.pixel_store_i32(glow::UNPACK_ROW_LENGTH, 0); - ctx.pixel_store_i32(glow::UNPACK_ALIGNMENT, 4); - ctx.bind_buffer(glow::PIXEL_UNPACK_BUFFER, None); + context.pixel_store_i32(glow::UNPACK_ROW_LENGTH, 0); + context.pixel_store_i32(glow::UNPACK_ALIGNMENT, 4); + context.bind_buffer(glow::PIXEL_UNPACK_BUFFER, None); - ctx.tex_sub_image_2d( + context.tex_sub_image_2d( glow::TEXTURE_2D, 0, 0, @@ -61,10 +63,10 @@ impl LoadLut for Gl3LutLoad { let mipmap = levels > 1; if mipmap { - ctx.generate_mipmap(glow::TEXTURE_2D); + context.generate_mipmap(glow::TEXTURE_2D); } - ctx.bind_texture(glow::TEXTURE_2D, None); + context.bind_texture(glow::TEXTURE_2D, None); handle }; @@ -76,9 +78,9 @@ impl LoadLut for Gl3LutLoad { format: glow::RGBA8, size: image.size, }, - filter: texture.meta.filter_mode, - mip_filter: texture.meta.filter_mode, - wrap_mode: texture.meta.wrap_mode, + filter: meta.filter_mode, + mip_filter: meta.filter_mode, + wrap_mode: meta.wrap_mode, }, ); } @@ -89,7 +91,7 @@ impl LoadLut for Gl3LutLoad { .ok() .map(glow::NativeBuffer); - ctx.bind_buffer(glow::PIXEL_UNPACK_BUFFER, pixel_unpack); + context.bind_buffer(glow::PIXEL_UNPACK_BUFFER, pixel_unpack); }; Ok(luts) } diff --git a/librashader-runtime-gl/src/gl/gl46/lut_load.rs b/librashader-runtime-gl/src/gl/gl46/lut_load.rs index 97489d8..f852f98 100644 --- a/librashader-runtime-gl/src/gl/gl46/lut_load.rs +++ b/librashader-runtime-gl/src/gl/gl46/lut_load.rs @@ -4,8 +4,8 @@ use crate::gl::LoadLut; use crate::texture::InputTexture; use glow::{HasContext, PixelUnpackData}; use librashader_common::map::FastHashMap; -use librashader_presets::TextureConfig; -use librashader_runtime::image::{Image, ImageError, UVDirection}; +use librashader_pack::TextureData; +use librashader_runtime::image::{ImageError, LoadedTexture, UVDirection}; use librashader_runtime::scaling::MipmapSize; use rayon::prelude::*; @@ -13,19 +13,19 @@ pub struct Gl46LutLoad; impl LoadLut for Gl46LutLoad { fn load_luts( context: &glow::Context, - textures: &[TextureConfig], + textures: Vec, ) -> Result> { let mut luts = FastHashMap::default(); // don't need this for texture DSA api. - let images = textures - .par_iter() - .map(|texture| Image::load(&texture.path, UVDirection::TopLeft)) - .collect::, ImageError>>()?; + let textures = textures + .into_par_iter() + .map(|texture| LoadedTexture::from_texture(texture, UVDirection::TopLeft)) + .collect::, ImageError>>()?; - for (index, (texture, image)) in textures.iter().zip(images).enumerate() { - let levels = if texture.meta.mipmap { + for (index, LoadedTexture { meta, image }) in textures.iter().enumerate() { + let levels = if meta.mipmap { image.size.calculate_miplevels() } else { 1u32 @@ -75,9 +75,9 @@ impl LoadLut for Gl46LutLoad { format: glow::RGBA8, size: image.size, }, - filter: texture.meta.filter_mode, - mip_filter: texture.meta.filter_mode, - wrap_mode: texture.meta.wrap_mode, + filter: meta.filter_mode, + mip_filter: meta.filter_mode, + wrap_mode: meta.wrap_mode, }, ); } diff --git a/librashader-runtime-gl/src/gl/mod.rs b/librashader-runtime-gl/src/gl/mod.rs index c339685..0313840 100644 --- a/librashader-runtime-gl/src/gl/mod.rs +++ b/librashader-runtime-gl/src/gl/mod.rs @@ -10,7 +10,7 @@ use crate::texture::InputTexture; pub use framebuffer::GLFramebuffer; use librashader_common::map::FastHashMap; use librashader_common::{ImageFormat, Size}; -use librashader_presets::{Scale2D, TextureConfig}; +use librashader_presets::Scale2D; use librashader_reflect::back::glsl::CrossGlslContext; use librashader_reflect::back::ShaderCompilerOutput; use librashader_reflect::reflect::semantics::{BufferReflection, TextureBinding}; @@ -60,7 +60,7 @@ static FINAL_VBO_DATA: &[VertexInput; 4] = &[ pub(crate) trait LoadLut { fn load_luts( context: &glow::Context, - textures: &[TextureConfig], + textures: Vec, ) -> Result>; } @@ -172,3 +172,4 @@ pub(crate) trait GLInterface { } pub(crate) use framebuffer::OutputFramebuffer; +use librashader_pack::TextureData; diff --git a/librashader-runtime-mtl/Cargo.toml b/librashader-runtime-mtl/Cargo.toml index 33cbbf8..7b04052 100644 --- a/librashader-runtime-mtl/Cargo.toml +++ b/librashader-runtime-mtl/Cargo.toml @@ -17,6 +17,7 @@ description = "RetroArch shaders for all." librashader-common = { path = "../librashader-common", features = ["metal"], version = "0.4.5" } librashader-presets = { path = "../librashader-presets", version = "0.4.5" } librashader-preprocess = { path = "../librashader-preprocess", version = "0.4.5" } +librashader-pack = { path = "../librashader-pack", version = "0.4.5" } librashader-reflect = { path = "../librashader-reflect", version = "0.4.5" } librashader-runtime = { path = "../librashader-runtime" , version = "0.4.5" } diff --git a/librashader-runtime-mtl/src/filter_chain.rs b/librashader-runtime-mtl/src/filter_chain.rs index 35f6ab6..85ed24f 100644 --- a/librashader-runtime-mtl/src/filter_chain.rs +++ b/librashader-runtime-mtl/src/filter_chain.rs @@ -11,7 +11,7 @@ use crate::texture::{get_texture_size, InputTexture, MetalTextureRef, OwnedTextu use librashader_common::map::FastHashMap; use librashader_common::{ImageFormat, Size, Viewport}; use librashader_presets::context::VideoDriver; -use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig}; +use librashader_presets::ShaderPreset; use librashader_reflect::back::msl::MslVersion; use librashader_reflect::back::targets::MSL; use librashader_reflect::back::{CompileReflectShader, CompileShader}; @@ -22,7 +22,7 @@ use librashader_reflect::reflect::semantics::ShaderSemantics; use librashader_reflect::reflect::ReflectShader; use librashader_runtime::binding::BindingUtil; use librashader_runtime::framebuffer::FramebufferInit; -use librashader_runtime::image::{Image, ImageError, UVDirection, BGRA8}; +use librashader_runtime::image::{ImageError, LoadedTexture, UVDirection, BGRA8}; use librashader_runtime::quad::QuadType; use librashader_runtime::render_target::RenderTarget; use librashader_runtime::scaling::ScaleFramebuffer; @@ -41,6 +41,7 @@ use std::path::Path; mod compile { use super::*; + use librashader_pack::{ShaderPassData, TextureData}; #[cfg(not(feature = "stable"))] pub type ShaderPassMeta = @@ -51,18 +52,20 @@ mod compile { ShaderPassArtifact + Send>>; pub fn compile_passes( - shaders: Vec, - textures: &[TextureConfig], + shaders: Vec, + textures: &[TextureData], ) -> Result<(Vec, ShaderSemantics), FilterChainError> { - let (passes, semantics) = - MSL::compile_preset_passes::( - shaders, &textures, - )?; + let (passes, semantics) = MSL::compile_preset_passes::< + SpirvCompilation, + SpirvCross, + FilterChainError, + >(shaders, textures.iter().map(|t| &t.meta))?; Ok((passes, semantics)) } } use compile::{compile_passes, ShaderPassMeta}; +use librashader_pack::{ShaderPresetPack, TextureData}; use librashader_runtime::parameters::RuntimeParameters; /// A Metal filter chain. @@ -119,13 +122,23 @@ impl FilterChainMetal { preset: ShaderPreset, queue: &ProtocolObject, options: Option<&FilterChainOptionsMetal>, + ) -> error::Result { + let preset = ShaderPresetPack::load_from_preset::(preset)?; + Self::load_from_pack(preset, queue, options) + } + + /// Load a filter chain from a pre-parsed `ShaderPreset`. + pub fn load_from_pack( + preset: ShaderPresetPack, + queue: &ProtocolObject, + options: Option<&FilterChainOptionsMetal>, ) -> error::Result { let cmd = queue .commandBuffer() .ok_or(FilterChainError::FailedToCreateCommandBuffer)?; let filter_chain = - Self::load_from_preset_deferred_internal(preset, queue.device(), &cmd, options)?; + Self::load_from_pack_deferred_internal(preset, queue.device(), &cmd, options)?; cmd.commit(); unsafe { cmd.waitUntilCompleted() }; @@ -136,7 +149,7 @@ impl FilterChainMetal { fn load_luts( device: &ProtocolObject, cmd: &ProtocolObject, - textures: &[TextureConfig], + textures: Vec, ) -> error::Result> { let mut luts = FastHashMap::default(); @@ -144,12 +157,12 @@ impl FilterChainMetal { .blitCommandEncoder() .ok_or(FilterChainError::FailedToCreateCommandBuffer)?; - let images = textures - .par_iter() - .map(|texture| Image::::load(&texture.path, UVDirection::TopLeft)) - .collect::>, ImageError>>()?; - for (index, (texture, image)) in textures.iter().zip(images).enumerate() { - let texture = LutTexture::new(device, image, &texture.meta, &mipmapper)?; + let textures = textures + .into_par_iter() + .map(|texture| LoadedTexture::::from_texture(texture, UVDirection::TopLeft)) + .collect::>, ImageError>>()?; + for (index, LoadedTexture { meta, image }) in textures.into_iter().enumerate() { + let texture = LutTexture::new(device, image, &meta, &mipmapper)?; luts.insert(index, texture); } @@ -269,7 +282,8 @@ impl FilterChainMetal { cmd: &ProtocolObject, options: Option<&FilterChainOptionsMetal>, ) -> error::Result { - Self::load_from_preset_deferred_internal(preset, queue.device(), &cmd, options) + let preset = ShaderPresetPack::load_from_preset::(preset)?; + Self::load_from_pack_deferred(preset, queue, cmd, options) } /// Load a filter chain from a pre-parsed `ShaderPreset`, deferring and GPU-side initialization @@ -279,8 +293,24 @@ impl FilterChainMetal { /// The provided command buffer must be ready for recording. /// The caller is responsible for ending the command buffer and immediately submitting it to a /// graphics queue. The command buffer must be completely executed before calling [`frame`](Self::frame). - fn load_from_preset_deferred_internal( - preset: ShaderPreset, + pub fn load_from_pack_deferred( + preset: ShaderPresetPack, + queue: &ProtocolObject, + cmd: &ProtocolObject, + options: Option<&FilterChainOptionsMetal>, + ) -> error::Result { + Self::load_from_pack_deferred_internal(preset, queue.device(), &cmd, options) + } + + /// Load a filter chain from a pre-parsed `ShaderPreset`, deferring and GPU-side initialization + /// to the caller. This function therefore requires no external synchronization of the device queue. + /// + /// ## Safety + /// The provided command buffer must be ready for recording. + /// The caller is responsible for ending the command buffer and immediately submitting it to a + /// graphics queue. The command buffer must be completely executed before calling [`frame`](Self::frame). + fn load_from_pack_deferred_internal( + preset: ShaderPresetPack, device: Id>, cmd: &ProtocolObject, options: Option<&FilterChainOptionsMetal>, @@ -290,7 +320,7 @@ impl FilterChainMetal { let filters = Self::init_passes(&device, passes, &semantics)?; let samplers = SamplerSet::new(&device)?; - let luts = FilterChainMetal::load_luts(&device, &cmd, &preset.textures)?; + let luts = FilterChainMetal::load_luts(&device, &cmd, preset.textures)?; let framebuffer_gen = || { Ok::<_, error::FilterChainError>(OwnedTexture::new( &device, diff --git a/librashader-runtime-mtl/src/luts.rs b/librashader-runtime-mtl/src/luts.rs index 2c27012..98737fc 100644 --- a/librashader-runtime-mtl/src/luts.rs +++ b/librashader-runtime-mtl/src/luts.rs @@ -1,6 +1,6 @@ use crate::error::{FilterChainError, Result}; use crate::texture::InputTexture; -use librashader_presets::{TextureConfig, TextureMeta}; +use librashader_presets::TextureMeta; use librashader_runtime::image::{Image, BGRA8}; use librashader_runtime::scaling::MipmapSize; use objc2::runtime::ProtocolObject; diff --git a/librashader-runtime-vk/Cargo.toml b/librashader-runtime-vk/Cargo.toml index 2123ed9..d6520f3 100644 --- a/librashader-runtime-vk/Cargo.toml +++ b/librashader-runtime-vk/Cargo.toml @@ -16,6 +16,7 @@ description = "RetroArch shaders for all." [dependencies] librashader-common = { path = "../librashader-common", features = ["vulkan"], version = "0.4.5" } librashader-presets = { path = "../librashader-presets", version = "0.4.5" } +librashader-pack = { path = "../librashader-pack", version = "0.4.5" } librashader-preprocess = { path = "../librashader-preprocess", version = "0.4.5" } librashader-reflect = { path = "../librashader-reflect", version = "0.4.5" } librashader-runtime = { path = "../librashader-runtime" , version = "0.4.5" } diff --git a/librashader-runtime-vk/src/filter_chain.rs b/librashader-runtime-vk/src/filter_chain.rs index 8677e1a..af42f9c 100644 --- a/librashader-runtime-vk/src/filter_chain.rs +++ b/librashader-runtime-vk/src/filter_chain.rs @@ -18,7 +18,7 @@ use gpu_allocator::vulkan::Allocator; use librashader_cache::CachedCompilation; use librashader_common::map::FastHashMap; use librashader_presets::context::VideoDriver; -use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig}; +use librashader_presets::ShaderPreset; use librashader_reflect::back::targets::SPIRV; use librashader_reflect::back::{CompileReflectShader, CompileShader}; use librashader_reflect::front::SpirvCompilation; @@ -28,7 +28,7 @@ use librashader_reflect::reflect::semantics::ShaderSemantics; use librashader_reflect::reflect::ReflectShader; use librashader_runtime::binding::BindingUtil; use librashader_runtime::framebuffer::FramebufferInit; -use librashader_runtime::image::{Image, ImageError, UVDirection, BGRA8}; +use librashader_runtime::image::{ImageError, LoadedTexture, UVDirection, BGRA8}; use librashader_runtime::quad::QuadType; use librashader_runtime::render_target::RenderTarget; use librashader_runtime::scaling::ScaleFramebuffer; @@ -250,6 +250,7 @@ impl Drop for FrameResiduals { mod compile { use super::*; + use librashader_pack::ShaderPassData; #[cfg(not(feature = "stable"))] pub type ShaderPassMeta = @@ -261,8 +262,8 @@ mod compile { >; pub fn compile_passes( - shaders: Vec, - textures: &[TextureConfig], + shaders: Vec, + textures: &[TextureData], disable_cache: bool, ) -> Result<(Vec, ShaderSemantics), FilterChainError> { let (passes, semantics) = if !disable_cache { @@ -270,10 +271,11 @@ mod compile { CachedCompilation, SpirvCross, FilterChainError, - >(shaders, &textures)? + >(shaders, textures.iter().map(|t| &t.meta))? } else { SPIRV::compile_preset_passes::( - shaders, &textures, + shaders, + textures.iter().map(|t| &t.meta), )? }; @@ -282,6 +284,7 @@ mod compile { } use compile::{compile_passes, ShaderPassMeta}; +use librashader_pack::{ShaderPresetPack, TextureData}; use librashader_runtime::parameters::RuntimeParameters; impl FilterChainVulkan { @@ -297,8 +300,7 @@ impl FilterChainVulkan { { // load passes from preset let preset = ShaderPreset::try_parse_with_driver_context(path, VideoDriver::Vulkan)?; - - unsafe { Self::load_from_preset(preset, vulkan, options) } + unsafe { Self::load_from_preset::(preset, vulkan, options) } } /// Load a filter chain from a pre-parsed `ShaderPreset`. @@ -307,6 +309,20 @@ impl FilterChainVulkan { vulkan: V, options: Option<&FilterChainOptionsVulkan>, ) -> error::Result + where + V: TryInto, + FilterChainError: From, + { + let pack = ShaderPresetPack::load_from_preset::(preset)?; + unsafe { Self::load_from_pack(pack, vulkan, options) } + } + + /// Load a filter chain from a pre-parsed and loaded `ShaderPresetPack`. + pub unsafe fn load_from_pack( + preset: ShaderPresetPack, + vulkan: V, + options: Option<&FilterChainOptionsVulkan>, + ) -> error::Result where V: TryInto, FilterChainError: From, @@ -342,12 +358,7 @@ impl FilterChainVulkan { } let filter_chain = unsafe { - Self::load_from_preset_deferred::<_, Infallible>( - preset, - vulkan, - command_buffer, - options, - )? + Self::load_from_pack_deferred::<_, Infallible>(preset, vulkan, command_buffer, options)? }; unsafe { @@ -378,6 +389,27 @@ impl FilterChainVulkan { cmd: vk::CommandBuffer, options: Option<&FilterChainOptionsVulkan>, ) -> error::Result + where + V: TryInto, + FilterChainError: From, + { + let pack = ShaderPresetPack::load_from_preset::(preset)?; + unsafe { Self::load_from_pack_deferred(pack, vulkan, cmd, options) } + } + + /// Load a filter chain from a pre-parsed, loaded `ShaderPresetPack`, deferring and GPU-side initialization + /// to the caller. This function therefore requires no external synchronization of the device queue. + /// + /// ## Safety + /// The provided command buffer must be ready for recording and contain no prior commands. + /// The caller is responsible for ending the command buffer and immediately submitting it to a + /// graphics queue. The command buffer must be completely executed before calling [`frame`](Self::frame). + pub unsafe fn load_from_pack_deferred( + preset: ShaderPresetPack, + vulkan: V, + cmd: vk::CommandBuffer, + options: Option<&FilterChainOptionsVulkan>, + ) -> error::Result where V: TryInto, FilterChainError: From, @@ -402,7 +434,7 @@ impl FilterChainVulkan { disable_cache, )?; - let luts = FilterChainVulkan::load_luts(&device, cmd, &preset.textures)?; + let luts = FilterChainVulkan::load_luts(&device, cmd, preset.textures)?; let samplers = SamplerSet::new(&device.device)?; let framebuffer_gen = @@ -527,15 +559,15 @@ impl FilterChainVulkan { fn load_luts( vulkan: &VulkanObjects, command_buffer: vk::CommandBuffer, - textures: &[TextureConfig], + textures: Vec, ) -> error::Result> { let mut luts = FastHashMap::default(); - let images = textures - .par_iter() - .map(|texture| Image::load(&texture.path, UVDirection::TopLeft)) - .collect::>, ImageError>>()?; - for (index, (texture, image)) in textures.iter().zip(images).enumerate() { - let texture = LutTexture::new(vulkan, command_buffer, image, &texture.meta)?; + let textures = textures + .into_par_iter() + .map(|texture| LoadedTexture::from_texture(texture, UVDirection::TopLeft)) + .collect::>, ImageError>>()?; + for (index, LoadedTexture { meta, image }) in textures.into_iter().enumerate() { + let texture = LutTexture::new(vulkan, command_buffer, image, &meta)?; luts.insert(index, texture); } Ok(luts) diff --git a/librashader-runtime-wgpu/Cargo.toml b/librashader-runtime-wgpu/Cargo.toml index 7f99e97..b66c799 100644 --- a/librashader-runtime-wgpu/Cargo.toml +++ b/librashader-runtime-wgpu/Cargo.toml @@ -17,6 +17,7 @@ description = "RetroArch shaders for all." librashader-common = { path = "../librashader-common", features = ["wgpu"], version = "0.4.5" } librashader-presets = { path = "../librashader-presets", version = "0.4.5" } librashader-preprocess = { path = "../librashader-preprocess", version = "0.4.5" } +librashader-pack = { path = "../librashader-pack", version = "0.4.5" } librashader-reflect = { path = "../librashader-reflect", version = "0.4.5", features = ["wgsl"], default-features = false } librashader-runtime = { path = "../librashader-runtime" , version = "0.4.5" } librashader-cache = { path = "../librashader-cache", version = "0.4.5" } diff --git a/librashader-runtime-wgpu/src/filter_chain.rs b/librashader-runtime-wgpu/src/filter_chain.rs index 9491453..9022d84 100644 --- a/librashader-runtime-wgpu/src/filter_chain.rs +++ b/librashader-runtime-wgpu/src/filter_chain.rs @@ -1,5 +1,5 @@ use librashader_common::map::FastHashMap; -use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig}; +use librashader_presets::ShaderPreset; use librashader_reflect::back::targets::WGSL; use librashader_reflect::back::{CompileReflectShader, CompileShader}; use librashader_reflect::front::SpirvCompilation; @@ -7,7 +7,7 @@ use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtif use librashader_reflect::reflect::semantics::ShaderSemantics; use librashader_reflect::reflect::ReflectShader; use librashader_runtime::binding::BindingUtil; -use librashader_runtime::image::{Image, ImageError, UVDirection}; +use librashader_runtime::image::{ImageError, LoadedTexture, UVDirection}; use librashader_runtime::quad::QuadType; use librashader_runtime::uniforms::UniformStorage; #[cfg(not(target_arch = "wasm32"))] @@ -40,6 +40,7 @@ use crate::texture::{InputImage, OwnedImage}; mod compile { use super::*; + use librashader_pack::{ShaderPassData, TextureData}; #[cfg(not(feature = "stable"))] pub type ShaderPassMeta = @@ -50,18 +51,20 @@ mod compile { ShaderPassArtifact + Send>>; pub fn compile_passes( - shaders: Vec, - textures: &[TextureConfig], + shaders: Vec, + textures: &[TextureData], ) -> Result<(Vec, ShaderSemantics), FilterChainError> { - let (passes, semantics) = - WGSL::compile_preset_passes::( - shaders, &textures, - )?; + let (passes, semantics) = WGSL::compile_preset_passes::< + SpirvCompilation, + Naga, + FilterChainError, + >(shaders, textures.iter().map(|t| &t.meta))?; Ok((passes, semantics)) } } use compile::{compile_passes, ShaderPassMeta}; +use librashader_pack::{ShaderPresetPack, TextureData}; use librashader_runtime::parameters::RuntimeParameters; /// A wgpu filter chain. @@ -109,11 +112,22 @@ impl FilterChainWgpu { device: Arc, queue: Arc, options: Option<&FilterChainOptionsWgpu>, + ) -> error::Result { + let preset = ShaderPresetPack::load_from_preset::(preset)?; + Self::load_from_pack(preset, device, queue, options) + } + + /// Load a filter chain from a pre-parsed and loaded `ShaderPresetPack`. + pub fn load_from_pack( + preset: ShaderPresetPack, + device: Arc, + queue: Arc, + options: Option<&FilterChainOptionsWgpu>, ) -> error::Result { let mut cmd = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: Some("librashader load cmd"), }); - let filter_chain = Self::load_from_preset_deferred( + let filter_chain = Self::load_from_pack_deferred( preset, Arc::clone(&device), Arc::clone(&queue), @@ -143,6 +157,24 @@ impl FilterChainWgpu { queue: Arc, cmd: &mut wgpu::CommandEncoder, options: Option<&FilterChainOptionsWgpu>, + ) -> error::Result { + let preset = ShaderPresetPack::load_from_preset::(preset)?; + Self::load_from_pack_deferred(preset, device, queue, cmd, options) + } + + /// Load a filter chain from a pre-parsed `ShaderPreset`, deferring and GPU-side initialization + /// to the caller. This function therefore requires no external synchronization of the device queue. + /// + /// ## Safety + /// The provided command buffer must be ready for recording and contain no prior commands. + /// The caller is responsible for ending the command buffer and immediately submitting it to a + /// graphics queue. The command buffer must be completely executed before calling [`frame`](Self::frame). + pub fn load_from_pack_deferred( + preset: ShaderPresetPack, + device: Arc, + queue: Arc, + cmd: &mut wgpu::CommandEncoder, + options: Option<&FilterChainOptionsWgpu>, ) -> error::Result { let (passes, semantics) = compile_passes(preset.shaders, &preset.textures)?; @@ -166,7 +198,7 @@ impl FilterChainWgpu { cmd, &mut mipmapper, &samplers, - &preset.textures, + preset.textures, )?; // let framebuffer_gen = || { @@ -226,29 +258,21 @@ impl FilterChainWgpu { cmd: &mut wgpu::CommandEncoder, mipmapper: &mut MipmapGen, sampler_set: &SamplerSet, - textures: &[TextureConfig], + textures: Vec, ) -> error::Result> { let mut luts = FastHashMap::default(); #[cfg(not(target_arch = "wasm32"))] - let images_iter = textures.par_iter(); + let images_iter = textures.into_par_iter(); #[cfg(target_arch = "wasm32")] - let images_iter = textures.iter(); + let images_iter = textures.into_iter(); - let images = images_iter - .map(|texture| Image::load(&texture.path, UVDirection::TopLeft)) - .collect::, ImageError>>()?; - for (index, (texture, image)) in textures.iter().zip(images).enumerate() { - let texture = LutTexture::new( - device, - queue, - cmd, - image, - &texture.meta, - mipmapper, - sampler_set, - ); + let textures = images_iter + .map(|texture| LoadedTexture::from_texture(texture, UVDirection::TopLeft)) + .collect::, ImageError>>()?; + for (index, LoadedTexture { meta, image }) in textures.into_iter().enumerate() { + let texture = LutTexture::new(device, queue, cmd, image, &meta, mipmapper, sampler_set); luts.insert(index, texture); } Ok(luts) diff --git a/librashader-runtime/src/image.rs b/librashader-runtime/src/image.rs index 656c387..996ea64 100644 --- a/librashader-runtime/src/image.rs +++ b/librashader-runtime/src/image.rs @@ -4,8 +4,9 @@ use std::marker::PhantomData; use image::error::{LimitError, LimitErrorKind}; use image::DynamicImage; -use librashader_pack::TextureBuffer; +use librashader_pack::{TextureBuffer, TextureData}; use std::path::Path; +use librashader_presets::TextureMeta; /// An uncompressed raw image ready to upload to GPU buffers. pub struct Image { @@ -116,6 +117,25 @@ impl Image

{ } } +/// Loaded texture data in the proper pixel format from a [`TextureData`]. +pub struct LoadedTexture { + /// The loaded image data + pub image: Image

, + /// Meta information about the texture + pub meta: TextureMeta +} + +impl LoadedTexture

{ + /// Load the texture with the given UV direction and subpixel ordering. + pub fn from_texture(texture: TextureData, direction: UVDirection) -> Result { + Ok(LoadedTexture { + meta: texture.meta, + image: Image::load_from_buffer(texture.data, direction)?, + }) + } +} + + // load-bearing #[inline(always)], without it llvm will not vectorize. #[inline(always)] fn swizzle_pixels(pixels: &mut Vec, swizzle: &'static [usize; 32]) {