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 {
|
||||
// fn from(value: Size<u32>) -> Self {
|
||||
// vk::Extent3D {
|
||||
// width: value.width,
|
||||
// height: value.height,
|
||||
// depth: 1,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
impl From<Size<u32>> for wgpu_types::Extent3d {
|
||||
fn from(value: Size<u32>) -> Self {
|
||||
wgpu_types::Extent3d {
|
||||
width: value.width,
|
||||
height: value.height,
|
||||
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 {
|
||||
// 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> {
|
||||
// fn from(value: vk::Extent2D) -> Self {
|
||||
|
|
|
@ -3,13 +3,25 @@ use librashader_preprocess::ShaderSource;
|
|||
use librashader_presets::ShaderPassConfig;
|
||||
use librashader_reflect::back::wgsl::NagaWgslContext;
|
||||
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_runtime::uniforms::{NoUniformBinder, UniformStorage};
|
||||
use librashader_runtime::uniforms::{NoUniformBinder, UniformStorage, UniformStorageAccess};
|
||||
use rustc_hash::FxHashMap;
|
||||
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 device: Arc<wgpu::Device>,
|
||||
pub reflection: ShaderReflection,
|
||||
pub(crate) compiled: ShaderCompilerOutput<String, NagaWgslContext>,
|
||||
pub(crate) uniform_storage: UniformStorage,
|
||||
|
@ -20,3 +32,204 @@ pub struct FilterPass {
|
|||
// pub ubo_ring: VkUboRing,
|
||||
// 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;
|
||||
|
||||
pub struct WgpuGraphicsPipeline {
|
||||
layout: PipelineLayoutObjects,
|
||||
pub layout: PipelineLayoutObjects,
|
||||
render_pipeline: wgpu::RenderPipeline,
|
||||
}
|
||||
|
||||
pub struct PipelineLayoutObjects {
|
||||
layout: PipelineLayout,
|
||||
bind_group_layouts: Vec<BindGroupLayout>,
|
||||
pub main_bind_group_layout: BindGroupLayout,
|
||||
pub sampler_bind_group_layout: BindGroupLayout,
|
||||
fragment_entry_name: String,
|
||||
vertex_entry_name: String,
|
||||
vertex: ShaderModule,
|
||||
|
@ -39,8 +40,6 @@ impl PipelineLayoutObjects {
|
|||
source: ShaderSource::Wgsl(Cow::from(&shader_assembly.fragment)),
|
||||
});
|
||||
|
||||
let mut bind_group_layouts = Vec::new();
|
||||
|
||||
let mut main_bindings = Vec::new();
|
||||
let mut sampler_bindings = Vec::new();
|
||||
|
||||
|
@ -115,10 +114,7 @@ impl PipelineLayoutObjects {
|
|||
entries: &sampler_bindings,
|
||||
});
|
||||
|
||||
bind_group_layouts.push(main_bind_group);
|
||||
bind_group_layouts.push(sampler_bind_group);
|
||||
|
||||
let bind_group_layout_refs = bind_group_layouts.iter().collect::<Vec<_>>();
|
||||
let bind_group_layout_refs = [&main_bind_group, &sampler_bind_group];
|
||||
|
||||
let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("shader pipeline layout"),
|
||||
|
@ -128,7 +124,8 @@ impl PipelineLayoutObjects {
|
|||
|
||||
Self {
|
||||
layout,
|
||||
bind_group_layouts,
|
||||
main_bind_group_layout,
|
||||
sampler_bind_group_layout,
|
||||
fragment_entry_name: shader_assembly.context.fragment.entry_points[0]
|
||||
.name
|
||||
.clone(),
|
||||
|
@ -237,6 +234,13 @@ impl WgpuGraphicsPipeline {
|
|||
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(
|
||||
output.x,
|
||||
output.y,
|
||||
|
@ -248,4 +252,5 @@ impl WgpuGraphicsPipeline {
|
|||
|
||||
render_pass
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ pub struct OwnedImage {
|
|||
pub struct InputImage {
|
||||
/// A handle to the `VkImage`.
|
||||
pub image: wgpu::Texture,
|
||||
pub image_view: wgpu::TextureView,
|
||||
pub view: wgpu::TextureView,
|
||||
pub wrap_mode: WrapMode,
|
||||
pub filter_mode: FilterMode,
|
||||
pub mip_filter: FilterMode,
|
||||
|
@ -92,4 +92,16 @@ impl OwnedImage {
|
|||
}
|
||||
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