rt(wgpu): filter pass logic
This commit is contained in:
parent
555ff6f9fc
commit
32148cdff4
|
@ -86,15 +86,25 @@ impl From<Option<wgpu_types::TextureFormat>> for ImageFormat {
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// impl From<Size<u32>> for vk::Extent3D {
|
impl From<Size<u32>> for wgpu_types::Extent3d {
|
||||||
// fn from(value: Size<u32>) -> Self {
|
fn from(value: Size<u32>) -> Self {
|
||||||
// vk::Extent3D {
|
wgpu_types::Extent3d {
|
||||||
// width: value.width,
|
width: value.width,
|
||||||
// height: value.height,
|
height: value.height,
|
||||||
// depth: 1,
|
depth: 1,
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
impl From<wgpu_types::Extent3d> for Size<u32> {
|
||||||
|
fn from(value: wgpu_types::Extent3d) -> Self {
|
||||||
|
Size {
|
||||||
|
width: value.width,
|
||||||
|
height: value.height,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// impl From<Size<u32>> for vk::Extent2D {
|
// impl From<Size<u32>> for vk::Extent2D {
|
||||||
// fn from(value: Size<u32>) -> Self {
|
// fn from(value: Size<u32>) -> Self {
|
||||||
|
@ -105,14 +115,7 @@ impl From<Option<wgpu_types::TextureFormat>> for ImageFormat {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// impl From<vk::Extent3D> for Size<u32> {
|
|
||||||
// fn from(value: vk::Extent3D) -> Self {
|
|
||||||
// Size {
|
|
||||||
// width: value.width,
|
|
||||||
// height: value.height,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
//
|
||||||
// impl From<vk::Extent2D> for Size<u32> {
|
// impl From<vk::Extent2D> for Size<u32> {
|
||||||
// fn from(value: vk::Extent2D) -> Self {
|
// fn from(value: vk::Extent2D) -> Self {
|
||||||
|
|
|
@ -3,13 +3,25 @@ use librashader_preprocess::ShaderSource;
|
||||||
use librashader_presets::ShaderPassConfig;
|
use librashader_presets::ShaderPassConfig;
|
||||||
use librashader_reflect::back::wgsl::NagaWgslContext;
|
use librashader_reflect::back::wgsl::NagaWgslContext;
|
||||||
use librashader_reflect::back::ShaderCompilerOutput;
|
use librashader_reflect::back::ShaderCompilerOutput;
|
||||||
use librashader_reflect::reflect::semantics::{MemberOffset, UniformBinding};
|
use librashader_reflect::reflect::semantics::{BindingStage, MemberOffset, TextureBinding, UniformBinding};
|
||||||
use librashader_reflect::reflect::ShaderReflection;
|
use librashader_reflect::reflect::ShaderReflection;
|
||||||
use librashader_runtime::uniforms::{NoUniformBinder, UniformStorage};
|
use librashader_runtime::uniforms::{NoUniformBinder, UniformStorage, UniformStorageAccess};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use wgpu::{BindGroupDescriptor, BindGroupEntry, BindingResource, Buffer, BufferBinding, BufferUsages, RenderPass, ShaderStages, TextureView};
|
||||||
|
use wgpu::util::{BufferInitDescriptor, DeviceExt};
|
||||||
|
use librashader_common::{Size, Viewport};
|
||||||
|
use librashader_runtime::binding::{BindSemantics, TextureInput};
|
||||||
|
use librashader_runtime::quad::QuadType;
|
||||||
|
use librashader_runtime::render_target::RenderTarget;
|
||||||
|
use crate::error;
|
||||||
|
use crate::filter_chain::FilterCommon;
|
||||||
|
use crate::framebuffer::OutputImage;
|
||||||
|
use crate::samplers::SamplerSet;
|
||||||
|
use crate::texture::{InputImage, OwnedImage};
|
||||||
|
|
||||||
pub struct FilterPass {
|
pub struct FilterPass {
|
||||||
|
pub device: Arc<wgpu::Device>,
|
||||||
pub reflection: ShaderReflection,
|
pub reflection: ShaderReflection,
|
||||||
pub(crate) compiled: ShaderCompilerOutput<String, NagaWgslContext>,
|
pub(crate) compiled: ShaderCompilerOutput<String, NagaWgslContext>,
|
||||||
pub(crate) uniform_storage: UniformStorage,
|
pub(crate) uniform_storage: UniformStorage,
|
||||||
|
@ -20,3 +32,204 @@ pub struct FilterPass {
|
||||||
// pub ubo_ring: VkUboRing,
|
// pub ubo_ring: VkUboRing,
|
||||||
// pub frames_in_flight: u32,
|
// pub frames_in_flight: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TextureInput for InputImage {
|
||||||
|
fn size(&self) -> Size<u32> {
|
||||||
|
self.image.size().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BindSemantics<NoUniformBinder, Option<()>> for FilterPass {
|
||||||
|
type InputTexture = InputImage;
|
||||||
|
type SamplerSet = SamplerSet;
|
||||||
|
type DescriptorSet<'a> = (
|
||||||
|
&'a mut FxHashMap<u32, BindGroupEntry<'a>>,
|
||||||
|
&'a mut FxHashMap<u32, BindGroupEntry<'a>>,
|
||||||
|
);
|
||||||
|
type DeviceContext = Arc<wgpu::Device>;
|
||||||
|
type UniformOffset = MemberOffset;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn bind_texture<'a>(
|
||||||
|
descriptors: &mut Self::DescriptorSet<'a>,
|
||||||
|
samplers: &Self::SamplerSet,
|
||||||
|
binding: &TextureBinding,
|
||||||
|
texture: &Self::InputTexture,
|
||||||
|
_device: &Self::DeviceContext,
|
||||||
|
) {
|
||||||
|
let sampler = samplers.get(texture.wrap_mode, texture.filter_mode, texture.mip_filter);
|
||||||
|
|
||||||
|
let (texture_binding, sampler_binding) = descriptors;
|
||||||
|
texture_binding.insert(binding.binding, BindGroupEntry {
|
||||||
|
binding: binding.binding,
|
||||||
|
resource:BindingResource::TextureView(&texture.view)}
|
||||||
|
);
|
||||||
|
sampler_binding.insert(binding.binding, BindGroupEntry {
|
||||||
|
binding: binding.binding,
|
||||||
|
resource: BindingResource::Sampler(&sampler),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FilterPass {
|
||||||
|
pub(crate) fn draw(
|
||||||
|
&mut self,
|
||||||
|
cmd: &mut wgpu::CommandEncoder,
|
||||||
|
pass_index: usize,
|
||||||
|
parent: &FilterCommon,
|
||||||
|
frame_count: u32,
|
||||||
|
frame_direction: i32,
|
||||||
|
viewport: &Viewport<OwnedImage>,
|
||||||
|
original: &InputImage,
|
||||||
|
source: &InputImage,
|
||||||
|
output: &RenderTarget<OutputImage>,
|
||||||
|
vbo_type: QuadType,
|
||||||
|
) -> error::Result<RenderPass> {
|
||||||
|
|
||||||
|
let mut main_heap = FxHashMap::default();
|
||||||
|
let mut sampler_heap = FxHashMap::default();
|
||||||
|
|
||||||
|
self.build_semantics(
|
||||||
|
pass_index,
|
||||||
|
parent,
|
||||||
|
output.mvp,
|
||||||
|
frame_count,
|
||||||
|
frame_direction,
|
||||||
|
output.output.size,
|
||||||
|
viewport.output.size,
|
||||||
|
original,
|
||||||
|
source,
|
||||||
|
&mut main_heap,
|
||||||
|
&mut sampler_heap,
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
let main_buffer: Buffer;
|
||||||
|
let pcb_buffer: Buffer;
|
||||||
|
if let Some(ubo) = &self.reflection.ubo {
|
||||||
|
main_buffer = self.device
|
||||||
|
.create_buffer_init(&BufferInitDescriptor {
|
||||||
|
label: Some("ubo buffer"),
|
||||||
|
contents: self.uniform_storage.ubo_slice(),
|
||||||
|
usage: BufferUsages::UNIFORM,
|
||||||
|
});
|
||||||
|
|
||||||
|
main_heap.insert(ubo.binding, BindGroupEntry {
|
||||||
|
binding: ubo.binding,
|
||||||
|
resource: BindingResource::Buffer(BufferBinding {
|
||||||
|
buffer: &main_buffer,
|
||||||
|
offset: 0,
|
||||||
|
size: None,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut has_pcb_buffer = false;
|
||||||
|
if let Some(pcb) = &self.reflection.push_constant {
|
||||||
|
if let Some(binding) = pcb.binding {
|
||||||
|
pcb_buffer = self.device
|
||||||
|
.create_buffer_init(&BufferInitDescriptor {
|
||||||
|
label: Some("ubo buffer"),
|
||||||
|
contents: self.uniform_storage.push_slice(),
|
||||||
|
usage: BufferUsages::UNIFORM,
|
||||||
|
});
|
||||||
|
|
||||||
|
main_heap.insert(binding, BindGroupEntry {
|
||||||
|
binding,
|
||||||
|
resource: BindingResource::Buffer(BufferBinding {
|
||||||
|
buffer: &pcb_buffer,
|
||||||
|
offset: 0,
|
||||||
|
size: None,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
has_pcb_buffer = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let mut render_pass = self.graphics_pipeline
|
||||||
|
.begin_rendering(output, cmd);
|
||||||
|
|
||||||
|
let main_bind_group = self.device.create_bind_group(&BindGroupDescriptor {
|
||||||
|
label: Some("main bind group"),
|
||||||
|
layout: &self.graphics_pipeline.layout.main_bind_group_layout,
|
||||||
|
entries: &main_heap.into_values().collect::<Vec<_>>()
|
||||||
|
});
|
||||||
|
|
||||||
|
let sampler_bind_group = self.device.create_bind_group(&BindGroupDescriptor {
|
||||||
|
label: Some("sampler bind group"),
|
||||||
|
layout: &self.graphics_pipeline.layout.sampler_bind_group_layout,
|
||||||
|
entries: &sampler_heap.into_values().collect::<Vec<_>>()
|
||||||
|
});
|
||||||
|
|
||||||
|
render_pass.set_bind_group(
|
||||||
|
0,
|
||||||
|
&main_bind_group,
|
||||||
|
&[]
|
||||||
|
);
|
||||||
|
|
||||||
|
render_pass.set_bind_group(
|
||||||
|
1,
|
||||||
|
&sampler_bind_group,
|
||||||
|
&[]
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(push) = &self.reflection.push_constant && !has_pcb_buffer {
|
||||||
|
let mut stage_mask = ShaderStages::empty();
|
||||||
|
if push.stage_mask.contains(BindingStage::FRAGMENT) {
|
||||||
|
stage_mask |= ShaderStages::FRAGMENT;
|
||||||
|
}
|
||||||
|
if push.stage_mask.contains(BindingStage::VERTEX) {
|
||||||
|
stage_mask |= ShaderStages::VERTEX;
|
||||||
|
}
|
||||||
|
render_pass.set_push_constants(
|
||||||
|
stage_mask,
|
||||||
|
0,
|
||||||
|
self.uniform_storage.push_slice()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.draw_quad.draw_quad(&mut render_pass, vbo_type);
|
||||||
|
|
||||||
|
Ok(render_pass)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_semantics(
|
||||||
|
&mut self,
|
||||||
|
pass_index: usize,
|
||||||
|
parent: &FilterCommon,
|
||||||
|
mvp: &[f32; 16],
|
||||||
|
frame_count: u32,
|
||||||
|
frame_direction: i32,
|
||||||
|
fb_size: Size<u32>,
|
||||||
|
viewport_size: Size<u32>,
|
||||||
|
original: &InputImage,
|
||||||
|
source: &InputImage,
|
||||||
|
main_heap: &mut FxHashMap<u32, BindGroupEntry>
|
||||||
|
sampler_heap: &mut FxHashMap<u32, BindGroupEntry>
|
||||||
|
) {
|
||||||
|
Self::bind_semantics(
|
||||||
|
&self.device,
|
||||||
|
&parent.samplers,
|
||||||
|
&mut self.uniform_storage,
|
||||||
|
&mut (main_heap, sampler_heap),
|
||||||
|
mvp,
|
||||||
|
frame_count,
|
||||||
|
frame_direction,
|
||||||
|
fb_size,
|
||||||
|
viewport_size,
|
||||||
|
original,
|
||||||
|
source,
|
||||||
|
&self.uniform_bindings,
|
||||||
|
&self.reflection.meta.texture_meta,
|
||||||
|
parent.output_textures[0..pass_index]
|
||||||
|
.iter()
|
||||||
|
.map(|o| o.as_ref()),
|
||||||
|
parent.feedback_textures.iter().map(|o| o.as_ref()),
|
||||||
|
parent.history_textures.iter().map(|o| o.as_ref()),
|
||||||
|
parent.luts.iter().map(|(u, i)| (*u, i.as_ref())),
|
||||||
|
&self.source.parameters,
|
||||||
|
&parent.config.parameters,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -9,13 +9,14 @@ use librashader_runtime::render_target::RenderTarget;
|
||||||
use crate::framebuffer::OutputImage;
|
use crate::framebuffer::OutputImage;
|
||||||
|
|
||||||
pub struct WgpuGraphicsPipeline {
|
pub struct WgpuGraphicsPipeline {
|
||||||
layout: PipelineLayoutObjects,
|
pub layout: PipelineLayoutObjects,
|
||||||
render_pipeline: wgpu::RenderPipeline,
|
render_pipeline: wgpu::RenderPipeline,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PipelineLayoutObjects {
|
pub struct PipelineLayoutObjects {
|
||||||
layout: PipelineLayout,
|
layout: PipelineLayout,
|
||||||
bind_group_layouts: Vec<BindGroupLayout>,
|
pub main_bind_group_layout: BindGroupLayout,
|
||||||
|
pub sampler_bind_group_layout: BindGroupLayout,
|
||||||
fragment_entry_name: String,
|
fragment_entry_name: String,
|
||||||
vertex_entry_name: String,
|
vertex_entry_name: String,
|
||||||
vertex: ShaderModule,
|
vertex: ShaderModule,
|
||||||
|
@ -39,8 +40,6 @@ impl PipelineLayoutObjects {
|
||||||
source: ShaderSource::Wgsl(Cow::from(&shader_assembly.fragment)),
|
source: ShaderSource::Wgsl(Cow::from(&shader_assembly.fragment)),
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut bind_group_layouts = Vec::new();
|
|
||||||
|
|
||||||
let mut main_bindings = Vec::new();
|
let mut main_bindings = Vec::new();
|
||||||
let mut sampler_bindings = Vec::new();
|
let mut sampler_bindings = Vec::new();
|
||||||
|
|
||||||
|
@ -115,10 +114,7 @@ impl PipelineLayoutObjects {
|
||||||
entries: &sampler_bindings,
|
entries: &sampler_bindings,
|
||||||
});
|
});
|
||||||
|
|
||||||
bind_group_layouts.push(main_bind_group);
|
let bind_group_layout_refs = [&main_bind_group, &sampler_bind_group];
|
||||||
bind_group_layouts.push(sampler_bind_group);
|
|
||||||
|
|
||||||
let bind_group_layout_refs = bind_group_layouts.iter().collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
label: Some("shader pipeline layout"),
|
label: Some("shader pipeline layout"),
|
||||||
|
@ -128,7 +124,8 @@ impl PipelineLayoutObjects {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
layout,
|
layout,
|
||||||
bind_group_layouts,
|
main_bind_group_layout,
|
||||||
|
sampler_bind_group_layout,
|
||||||
fragment_entry_name: shader_assembly.context.fragment.entry_points[0]
|
fragment_entry_name: shader_assembly.context.fragment.entry_points[0]
|
||||||
.name
|
.name
|
||||||
.clone(),
|
.clone(),
|
||||||
|
@ -237,6 +234,13 @@ impl WgpuGraphicsPipeline {
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
render_pass.set_scissor_rect(
|
||||||
|
output.x as u32,
|
||||||
|
output.y as u32,
|
||||||
|
output.output.size.width,
|
||||||
|
output.output.size.height
|
||||||
|
);
|
||||||
|
|
||||||
render_pass.set_viewport(
|
render_pass.set_viewport(
|
||||||
output.x,
|
output.x,
|
||||||
output.y,
|
output.y,
|
||||||
|
@ -248,4 +252,5 @@ impl WgpuGraphicsPipeline {
|
||||||
|
|
||||||
render_pass
|
render_pass
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ pub struct OwnedImage {
|
||||||
pub struct InputImage {
|
pub struct InputImage {
|
||||||
/// A handle to the `VkImage`.
|
/// A handle to the `VkImage`.
|
||||||
pub image: wgpu::Texture,
|
pub image: wgpu::Texture,
|
||||||
pub image_view: wgpu::TextureView,
|
pub view: wgpu::TextureView,
|
||||||
pub wrap_mode: WrapMode,
|
pub wrap_mode: WrapMode,
|
||||||
pub filter_mode: FilterMode,
|
pub filter_mode: FilterMode,
|
||||||
pub mip_filter: FilterMode,
|
pub mip_filter: FilterMode,
|
||||||
|
@ -92,4 +92,16 @@ impl OwnedImage {
|
||||||
}
|
}
|
||||||
size
|
size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn as_input(&self, filter: FilterMode, wrap_mode: WrapMode) -> InputImage {
|
||||||
|
let image = self.clone();
|
||||||
|
InputImage {
|
||||||
|
image: self.image.clone(),
|
||||||
|
view: self.clone().,
|
||||||
|
wrap_mode,
|
||||||
|
filter_mode: filter,
|
||||||
|
mip_filter: filter,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue