rt(wgpu): fix enough stuff to get it to draw a frame
This commit is contained in:
parent
e39834547c
commit
31891e414f
|
@ -1,26 +1,27 @@
|
|||
use std::ops::{Deref, DerefMut};
|
||||
use std::sync::Arc;
|
||||
use parking_lot::RwLock;
|
||||
|
||||
pub struct WgpuMappedBuffer {
|
||||
pub struct WgpuStagedBuffer {
|
||||
buffer: wgpu::Buffer,
|
||||
shadow: Box<[u8]>,
|
||||
}
|
||||
|
||||
impl WgpuMappedBuffer {
|
||||
impl WgpuStagedBuffer {
|
||||
pub fn new(
|
||||
device: &Arc<wgpu::Device>,
|
||||
usage: wgpu::BufferUsages,
|
||||
size: wgpu::BufferAddress,
|
||||
label: wgpu::Label<'static>
|
||||
) -> WgpuMappedBuffer {
|
||||
label: wgpu::Label<'static>,
|
||||
) -> WgpuStagedBuffer {
|
||||
let buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label,
|
||||
size,
|
||||
usage,
|
||||
mapped_at_creation: true,
|
||||
usage: usage | wgpu::BufferUsages::COPY_DST,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
|
||||
WgpuMappedBuffer {
|
||||
WgpuStagedBuffer {
|
||||
buffer,
|
||||
shadow: vec![0u8; size as usize].into_boxed_slice(),
|
||||
}
|
||||
|
@ -31,13 +32,12 @@ impl WgpuMappedBuffer {
|
|||
}
|
||||
|
||||
/// Write the contents of the backing buffer to the device buffer.
|
||||
pub fn flush(&self) {
|
||||
self.buffer.slice(..)
|
||||
.get_mapped_range_mut().copy_from_slice(&self.shadow)
|
||||
pub fn flush(&self, queue: &wgpu::Queue) {
|
||||
queue.write_buffer(&self.buffer, 0, &self.shadow);
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for WgpuMappedBuffer {
|
||||
impl Deref for WgpuStagedBuffer {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
|
@ -45,8 +45,8 @@ impl Deref for WgpuMappedBuffer {
|
|||
}
|
||||
}
|
||||
|
||||
impl DerefMut for WgpuMappedBuffer {
|
||||
impl DerefMut for WgpuStagedBuffer {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.shadow.deref_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ pub struct DrawQuad {
|
|||
}
|
||||
|
||||
impl DrawQuad {
|
||||
pub fn new(device: &Device, queue: &mut Queue) -> DrawQuad {
|
||||
pub fn new(device: &Device) -> DrawQuad {
|
||||
let buffer = device.create_buffer_init(&BufferInitDescriptor {
|
||||
label: Some("librashader vbo"),
|
||||
contents: bytemuck::cast_slice(&VBO_DATA),
|
||||
|
@ -38,14 +38,12 @@ impl DrawQuad {
|
|||
DrawQuad { buffer }
|
||||
}
|
||||
|
||||
pub fn bind_vbo_for_frame<'a, 'b: 'a>(&'b self, cmd: &mut RenderPass<'a>) {
|
||||
cmd.set_vertex_buffer(0, self.buffer.slice(0..));
|
||||
}
|
||||
|
||||
pub fn draw_quad<'a, 'b: 'a>(&'b self, cmd: &mut RenderPass<'a>, vbo: QuadType) {
|
||||
cmd.set_vertex_buffer(0, self.buffer.slice(0..));
|
||||
|
||||
let offset = match vbo {
|
||||
QuadType::Offscreen => 0..3,
|
||||
QuadType::Final => 1..4,
|
||||
QuadType::Offscreen => 0..4,
|
||||
QuadType::Final => 4..8,
|
||||
};
|
||||
|
||||
cmd.draw(offset, 0..1)
|
||||
|
|
|
@ -16,20 +16,22 @@ use std::convert::Infallible;
|
|||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::buffer::WgpuStagedBuffer;
|
||||
use crate::draw_quad::DrawQuad;
|
||||
use librashader_common::{ImageFormat, Size, Viewport};
|
||||
use librashader_reflect::back::wgsl::WgslCompileOptions;
|
||||
use librashader_runtime::framebuffer::FramebufferInit;
|
||||
use librashader_runtime::render_target::RenderTarget;
|
||||
use librashader_runtime::scaling::ScaleFramebuffer;
|
||||
use rayon::prelude::*;
|
||||
use wgpu::{BindGroupEntry, CommandBuffer, CommandEncoder, Device, Queue, TextureAspect, TextureFormat};
|
||||
use crate::buffer::WgpuMappedBuffer;
|
||||
use crate::draw_quad::DrawQuad;
|
||||
use wgpu::{
|
||||
BindGroupEntry, CommandBuffer, CommandEncoder, Device, Queue, TextureAspect, TextureFormat,
|
||||
};
|
||||
|
||||
use crate::error;
|
||||
use crate::error::FilterChainError;
|
||||
use crate::filter_pass::FilterPass;
|
||||
use crate::framebuffer::OutputImage;
|
||||
use crate::framebuffer::OutputView;
|
||||
use crate::graphics_pipeline::WgpuGraphicsPipeline;
|
||||
use crate::luts::LutTexture;
|
||||
use crate::options::FrameOptionsWGPU;
|
||||
|
@ -73,6 +75,7 @@ pub(crate) struct FilterCommon {
|
|||
pub internal_frame_count: i32,
|
||||
pub(crate) draw_quad: DrawQuad,
|
||||
device: Arc<Device>,
|
||||
pub(crate) queue: Arc<wgpu::Queue>
|
||||
}
|
||||
|
||||
impl FilterChainWGPU {
|
||||
|
@ -85,7 +88,7 @@ impl FilterChainWGPU {
|
|||
/// graphics queue. The command buffer must be completely executed before calling [`frame`](Self::frame).
|
||||
pub fn load_from_preset_deferred(
|
||||
device: Arc<Device>,
|
||||
queue: &mut wgpu::Queue,
|
||||
queue: Arc<wgpu::Queue>,
|
||||
cmd: &mut wgpu::CommandEncoder,
|
||||
preset: ShaderPreset,
|
||||
) -> error::Result<FilterChainWGPU> {
|
||||
|
@ -94,11 +97,17 @@ impl FilterChainWGPU {
|
|||
// // initialize passes
|
||||
let filters = Self::init_passes(Arc::clone(&device), passes, &semantics)?;
|
||||
//
|
||||
let luts = FilterChainWGPU::load_luts(&device, queue, cmd, &preset.textures)?;
|
||||
let luts = FilterChainWGPU::load_luts(&device, &queue, cmd, &preset.textures)?;
|
||||
let samplers = SamplerSet::new(&device);
|
||||
//
|
||||
let framebuffer_gen =
|
||||
|| Ok::<_, error::FilterChainError>(OwnedImage::new(Arc::clone(&device), Size::new(1, 1), 1, ImageFormat::R8G8B8A8Unorm));
|
||||
let framebuffer_gen = || {
|
||||
Ok::<_, error::FilterChainError>(OwnedImage::new(
|
||||
Arc::clone(&device),
|
||||
Size::new(1, 1),
|
||||
1,
|
||||
ImageFormat::R8G8B8A8Unorm,
|
||||
))
|
||||
};
|
||||
let input_gen = || None;
|
||||
let framebuffer_init = FramebufferInit::new(
|
||||
filters.iter().map(|f| &f.reflection.meta),
|
||||
|
@ -122,39 +131,39 @@ impl FilterChainWGPU {
|
|||
// FrameResiduals::new(&device.device)
|
||||
// });
|
||||
|
||||
let draw_quad = DrawQuad::new(&device, queue);
|
||||
let draw_quad = DrawQuad::new(&device);
|
||||
|
||||
Ok(FilterChainWGPU {
|
||||
common: FilterCommon {
|
||||
luts,
|
||||
samplers,
|
||||
config: FilterMutable {
|
||||
passes_enabled: preset.shader_count as usize,
|
||||
parameters: preset
|
||||
.parameters
|
||||
.into_iter()
|
||||
.map(|param| (param.name, param.value))
|
||||
.collect(),
|
||||
},
|
||||
draw_quad,
|
||||
device,
|
||||
output_textures,
|
||||
feedback_textures,
|
||||
history_textures,
|
||||
internal_frame_count: 0,
|
||||
|
||||
config: FilterMutable {
|
||||
passes_enabled: preset.shader_count as usize,
|
||||
parameters: preset
|
||||
.parameters
|
||||
.into_iter()
|
||||
.map(|param| (param.name, param.value))
|
||||
.collect(),
|
||||
},
|
||||
draw_quad,
|
||||
device,
|
||||
queue,
|
||||
output_textures,
|
||||
feedback_textures,
|
||||
history_textures,
|
||||
internal_frame_count: 0,
|
||||
},
|
||||
passes: filters,
|
||||
output_framebuffers,
|
||||
feedback_framebuffers,
|
||||
history_framebuffers,
|
||||
disable_mipmaps: false // todo: force no mipmaps,
|
||||
output_framebuffers,
|
||||
feedback_framebuffers,
|
||||
history_framebuffers,
|
||||
disable_mipmaps: false, // todo: force no mipmaps,
|
||||
})
|
||||
}
|
||||
|
||||
fn load_luts(
|
||||
device: &wgpu::Device,
|
||||
queue: &mut wgpu::Queue,
|
||||
queue: &wgpu::Queue,
|
||||
cmd: &mut wgpu::CommandEncoder,
|
||||
textures: &[TextureConfig],
|
||||
) -> error::Result<FxHashMap<usize, LutTexture>> {
|
||||
|
@ -170,6 +179,29 @@ impl FilterChainWGPU {
|
|||
Ok(luts)
|
||||
}
|
||||
|
||||
fn push_history(&mut self, input: &wgpu::Texture, cmd: &mut wgpu::CommandEncoder) {
|
||||
if let Some(mut back) = self.history_framebuffers.pop_back() {
|
||||
if back.image.size() != input.size() || input.format() != back.image.format() {
|
||||
// old back will get dropped.. do we need to defer?
|
||||
let _old_back = std::mem::replace(
|
||||
&mut back,
|
||||
OwnedImage::new(
|
||||
Arc::clone(&self.common.device),
|
||||
input.size().into(),
|
||||
1,
|
||||
input.format().into(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
back.copy_from(cmd, input);
|
||||
}
|
||||
|
||||
self.history_framebuffers.push_front(back)
|
||||
}
|
||||
}
|
||||
|
||||
fn init_passes(
|
||||
device: Arc<Device>,
|
||||
passes: Vec<ShaderPassMeta>,
|
||||
|
@ -193,10 +225,19 @@ impl FilterChainWGPU {
|
|||
.as_ref()
|
||||
.map_or(0, |push| push.size as wgpu::BufferAddress);
|
||||
|
||||
|
||||
let uniform_storage = UniformStorage::new_with_storage(
|
||||
WgpuMappedBuffer::new(&device, wgpu::BufferUsages::UNIFORM, ubo_size as wgpu::BufferAddress, Some("ubo")),
|
||||
WgpuMappedBuffer::new(&device, wgpu::BufferUsages::UNIFORM, push_size as wgpu::BufferAddress, Some("push"))
|
||||
WgpuStagedBuffer::new(
|
||||
&device,
|
||||
wgpu::BufferUsages::UNIFORM,
|
||||
ubo_size as wgpu::BufferAddress,
|
||||
Some("ubo"),
|
||||
),
|
||||
WgpuStagedBuffer::new(
|
||||
&device,
|
||||
wgpu::BufferUsages::UNIFORM,
|
||||
push_size as wgpu::BufferAddress,
|
||||
Some("push"),
|
||||
),
|
||||
);
|
||||
|
||||
let uniform_bindings = reflection.meta.create_binding_map(|param| param.offset());
|
||||
|
@ -212,11 +253,9 @@ impl FilterChainWGPU {
|
|||
Arc::clone(&device),
|
||||
&wgsl,
|
||||
&reflection,
|
||||
render_pass_format.unwrap_or(TextureFormat::R8Unorm),
|
||||
render_pass_format.unwrap_or(TextureFormat::Rgba8Unorm),
|
||||
);
|
||||
|
||||
|
||||
|
||||
Ok(FilterPass {
|
||||
device: Arc::clone(&device),
|
||||
reflection,
|
||||
|
@ -235,13 +274,13 @@ impl FilterChainWGPU {
|
|||
Ok(filters.into_boxed_slice())
|
||||
}
|
||||
|
||||
pub fn frame<'a>(&mut self,
|
||||
pub fn frame<'a>(
|
||||
&mut self,
|
||||
input: Arc<wgpu::Texture>,
|
||||
viewport: &Viewport<OutputImage<'a>>,
|
||||
viewport: &Viewport<OutputView<'a>>,
|
||||
cmd: &mut wgpu::CommandEncoder,
|
||||
frame_count: usize,
|
||||
options: Option<&FrameOptionsWGPU>,
|
||||
|
||||
options: Option<&FrameOptionsWGPU>,
|
||||
) -> error::Result<()> {
|
||||
let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled);
|
||||
let passes = &mut self.passes[0..max];
|
||||
|
@ -249,7 +288,7 @@ impl FilterChainWGPU {
|
|||
if let Some(options) = &options {
|
||||
if options.clear_history {
|
||||
for history in &mut self.history_framebuffers {
|
||||
// history.clear(cmd);
|
||||
history.clear(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,21 +297,11 @@ impl FilterChainWGPU {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
let original_image_view = input.create_view(&wgpu::TextureViewDescriptor {
|
||||
label: Some("original_image_view"),
|
||||
format: Some(input.format()),
|
||||
dimension: Some(wgpu::TextureViewDimension::D2),
|
||||
aspect: TextureAspect::All,
|
||||
base_mip_level: 1,
|
||||
mip_level_count: None,
|
||||
base_array_layer: 1,
|
||||
array_layer_count: None,
|
||||
});
|
||||
let original_image_view = input.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
|
||||
let filter = passes[0].config.filter;
|
||||
let wrap_mode = passes[0].config.wrap_mode;
|
||||
|
||||
|
||||
// update history
|
||||
for (texture, image) in self
|
||||
.common
|
||||
|
@ -325,14 +354,13 @@ impl FilterChainWGPU {
|
|||
|
||||
let frame_direction = options.map_or(1, |f| f.frame_direction);
|
||||
|
||||
|
||||
for (index, pass) in pass.iter_mut().enumerate() {
|
||||
let target = &self.output_framebuffers[index];
|
||||
source.filter_mode = pass.config.filter;
|
||||
source.wrap_mode = pass.config.wrap_mode;
|
||||
source.mip_filter = pass.config.filter;
|
||||
|
||||
let output_image = OutputImage::new(target);
|
||||
let output_image = OutputView::new(target);
|
||||
let out = RenderTarget::identity(&output_image);
|
||||
|
||||
pass.draw(
|
||||
|
@ -345,11 +373,11 @@ impl FilterChainWGPU {
|
|||
&original,
|
||||
&source,
|
||||
&out,
|
||||
QuadType::Offscreen
|
||||
QuadType::Offscreen,
|
||||
)?;
|
||||
|
||||
if target.max_miplevels > 1 && !self.disable_mipmaps {
|
||||
// todo: mipmaps
|
||||
target.generate_mipmaps(cmd);
|
||||
}
|
||||
|
||||
source = self.common.output_textures[index].clone().unwrap();
|
||||
|
@ -378,13 +406,12 @@ impl FilterChainWGPU {
|
|||
&original,
|
||||
&source,
|
||||
&out,
|
||||
QuadType::Final
|
||||
QuadType::Final,
|
||||
)?;
|
||||
}
|
||||
|
||||
// self.push_history(input, cmd)?;
|
||||
self.push_history(&input, cmd);
|
||||
self.common.internal_frame_count = self.common.internal_frame_count.wrapping_add(1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,37 +1,42 @@
|
|||
use crate::buffer::WgpuStagedBuffer;
|
||||
use crate::error;
|
||||
use crate::filter_chain::FilterCommon;
|
||||
use crate::framebuffer::OutputView;
|
||||
use crate::graphics_pipeline::WgpuGraphicsPipeline;
|
||||
use crate::samplers::SamplerSet;
|
||||
use crate::texture::{InputImage, OwnedImage};
|
||||
use librashader_common::{ImageFormat, Size, Viewport};
|
||||
use librashader_preprocess::ShaderSource;
|
||||
use librashader_presets::ShaderPassConfig;
|
||||
use librashader_reflect::back::wgsl::NagaWgslContext;
|
||||
use librashader_reflect::back::ShaderCompilerOutput;
|
||||
use librashader_reflect::reflect::semantics::{BindingStage, MemberOffset, TextureBinding, UniformBinding};
|
||||
use librashader_reflect::reflect::semantics::{
|
||||
BindingStage, MemberOffset, TextureBinding, UniformBinding,
|
||||
};
|
||||
use librashader_reflect::reflect::ShaderReflection;
|
||||
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::{ImageFormat, Size, Viewport};
|
||||
use librashader_runtime::binding::{BindSemantics, TextureInput};
|
||||
use librashader_runtime::filter_pass::FilterPassMeta;
|
||||
use librashader_runtime::quad::QuadType;
|
||||
use librashader_runtime::render_target::RenderTarget;
|
||||
use crate::buffer::WgpuMappedBuffer;
|
||||
use crate::error;
|
||||
use crate::filter_chain::FilterCommon;
|
||||
use crate::framebuffer::OutputImage;
|
||||
use crate::samplers::SamplerSet;
|
||||
use crate::texture::{InputImage, OwnedImage};
|
||||
use librashader_runtime::uniforms::{NoUniformBinder, UniformStorage, UniformStorageAccess};
|
||||
use rustc_hash::FxHashMap;
|
||||
use std::sync::Arc;
|
||||
use wgpu::util::{BufferInitDescriptor, DeviceExt};
|
||||
use wgpu::{
|
||||
BindGroupDescriptor, BindGroupEntry, BindingResource, Buffer, BufferBinding, BufferUsages,
|
||||
RenderPass, ShaderStages, TextureView,
|
||||
};
|
||||
|
||||
pub struct FilterPass {
|
||||
pub device: Arc<wgpu::Device>,
|
||||
pub reflection: ShaderReflection,
|
||||
pub(crate) compiled: ShaderCompilerOutput<String, NagaWgslContext>,
|
||||
pub(crate) uniform_storage: UniformStorage<NoUniformBinder, Option<()>, WgpuMappedBuffer, WgpuMappedBuffer>,
|
||||
pub(crate) uniform_storage:
|
||||
UniformStorage<NoUniformBinder, Option<()>, WgpuStagedBuffer, WgpuStagedBuffer>,
|
||||
pub uniform_bindings: FxHashMap<UniformBinding, MemberOffset>,
|
||||
pub source: ShaderSource,
|
||||
pub config: ShaderPassConfig,
|
||||
pub graphics_pipeline: WgpuGraphicsPipeline,
|
||||
|
||||
}
|
||||
|
||||
impl TextureInput for InputImage {
|
||||
|
@ -42,10 +47,10 @@ impl TextureInput for InputImage {
|
|||
|
||||
pub struct WgpuArcBinding<T> {
|
||||
binding: u32,
|
||||
resource: Arc<T>
|
||||
resource: Arc<T>,
|
||||
}
|
||||
|
||||
impl BindSemantics<NoUniformBinder, Option<()>, WgpuMappedBuffer, WgpuMappedBuffer> for FilterPass {
|
||||
impl BindSemantics<NoUniformBinder, Option<()>, WgpuStagedBuffer, WgpuStagedBuffer> for FilterPass {
|
||||
type InputTexture = InputImage;
|
||||
type SamplerSet = SamplerSet;
|
||||
type DescriptorSet<'a> = (
|
||||
|
@ -66,15 +71,21 @@ impl BindSemantics<NoUniformBinder, Option<()>, WgpuMappedBuffer, WgpuMappedBuff
|
|||
let sampler = samplers.get(texture.wrap_mode, texture.filter_mode, texture.mip_filter);
|
||||
|
||||
let (texture_binding, sampler_binding) = descriptors;
|
||||
texture_binding.insert(binding.binding, WgpuArcBinding {
|
||||
binding: binding.binding,
|
||||
resource: Arc::clone(&texture.view)
|
||||
});
|
||||
texture_binding.insert(
|
||||
binding.binding,
|
||||
WgpuArcBinding {
|
||||
binding: binding.binding,
|
||||
resource: Arc::clone(&texture.view),
|
||||
},
|
||||
);
|
||||
|
||||
sampler_binding.insert(binding.binding, WgpuArcBinding {
|
||||
binding: binding.binding,
|
||||
resource: sampler,
|
||||
});
|
||||
sampler_binding.insert(
|
||||
binding.binding,
|
||||
WgpuArcBinding {
|
||||
binding: binding.binding,
|
||||
resource: sampler,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,13 +97,12 @@ impl FilterPass {
|
|||
parent: &FilterCommon,
|
||||
frame_count: u32,
|
||||
frame_direction: i32,
|
||||
viewport: &Viewport<OutputImage>,
|
||||
viewport: &Viewport<OutputView>,
|
||||
original: &InputImage,
|
||||
source: &InputImage,
|
||||
output: &RenderTarget<OutputImage>,
|
||||
output: &RenderTarget<OutputView>,
|
||||
vbo_type: QuadType,
|
||||
) -> error::Result<()> {
|
||||
|
||||
let mut main_heap = FxHashMap::default();
|
||||
let mut sampler_heap = FxHashMap::default();
|
||||
|
||||
|
@ -110,21 +120,20 @@ impl FilterPass {
|
|||
&mut sampler_heap,
|
||||
);
|
||||
|
||||
|
||||
let mut main_heap_array = Vec::with_capacity(main_heap.len() + 1);
|
||||
let mut sampler_heap_array = Vec::with_capacity(sampler_heap.len() + 1);
|
||||
|
||||
for binding in main_heap.values() {
|
||||
main_heap_array.push(BindGroupEntry {
|
||||
binding: binding.binding,
|
||||
resource: BindingResource::TextureView(&binding.resource)
|
||||
resource: BindingResource::TextureView(&binding.resource),
|
||||
})
|
||||
}
|
||||
|
||||
for binding in sampler_heap.values() {
|
||||
sampler_heap_array.push(BindGroupEntry {
|
||||
binding: binding.binding,
|
||||
resource: BindingResource::Sampler(&binding.resource)
|
||||
resource: BindingResource::Sampler(&binding.resource),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -157,31 +166,24 @@ impl FilterPass {
|
|||
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_array
|
||||
entries: &main_heap_array,
|
||||
});
|
||||
|
||||
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_array
|
||||
entries: &sampler_heap_array,
|
||||
});
|
||||
|
||||
let mut render_pass = self.graphics_pipeline
|
||||
.begin_rendering(output, cmd);
|
||||
let mut render_pass = self.graphics_pipeline.begin_rendering(output, cmd);
|
||||
|
||||
render_pass.set_bind_group(
|
||||
0,
|
||||
&main_bind_group,
|
||||
&[]
|
||||
);
|
||||
render_pass.set_bind_group(0, &main_bind_group, &[]);
|
||||
|
||||
render_pass.set_bind_group(
|
||||
1,
|
||||
&sampler_bind_group,
|
||||
&[]
|
||||
);
|
||||
render_pass.set_bind_group(1, &sampler_bind_group, &[]);
|
||||
|
||||
if let Some(push) = &self.reflection.push_constant && !has_pcb_buffer {
|
||||
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;
|
||||
|
@ -189,11 +191,7 @@ impl FilterPass {
|
|||
if push.stage_mask.contains(BindingStage::VERTEX) {
|
||||
stage_mask |= ShaderStages::VERTEX;
|
||||
}
|
||||
render_pass.set_push_constants(
|
||||
stage_mask,
|
||||
0,
|
||||
self.uniform_storage.push_slice()
|
||||
)
|
||||
render_pass.set_push_constants(stage_mask, 0, self.uniform_storage.push_slice())
|
||||
}
|
||||
|
||||
parent.draw_quad.draw_quad(&mut render_pass, vbo_type);
|
||||
|
@ -213,7 +211,7 @@ impl FilterPass {
|
|||
original: &InputImage,
|
||||
source: &InputImage,
|
||||
main_heap: &'a mut FxHashMap<u32, WgpuArcBinding<wgpu::TextureView>>,
|
||||
sampler_heap: &'a mut FxHashMap<u32, WgpuArcBinding<wgpu::Sampler>>
|
||||
sampler_heap: &'a mut FxHashMap<u32, WgpuArcBinding<wgpu::Sampler>>,
|
||||
) {
|
||||
Self::bind_semantics(
|
||||
&self.device,
|
||||
|
@ -240,8 +238,8 @@ impl FilterPass {
|
|||
);
|
||||
|
||||
// flush to buffers
|
||||
self.uniform_storage.inner_ubo().flush();
|
||||
self.uniform_storage.inner_push().flush();
|
||||
self.uniform_storage.inner_ubo().flush(&parent.queue);
|
||||
self.uniform_storage.inner_push().flush(&parent.queue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,4 +251,4 @@ impl FilterPassMeta for FilterPass {
|
|||
fn config(&self) -> &ShaderPassConfig {
|
||||
&self.config
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
use librashader_common::Size;
|
||||
use crate::texture::OwnedImage;
|
||||
use librashader_common::Size;
|
||||
|
||||
pub struct OutputImage<'a> {
|
||||
pub struct OutputView<'a> {
|
||||
pub size: Size<u32>,
|
||||
pub view: &'a wgpu::TextureView,
|
||||
pub format: wgpu::TextureFormat,
|
||||
}
|
||||
|
||||
impl<'a> OutputImage<'a> {
|
||||
impl<'a> OutputView<'a> {
|
||||
pub fn new(image: &'a OwnedImage) -> Self {
|
||||
Self {
|
||||
size: image.size,
|
||||
view: &image.view,
|
||||
format: image.image.format()
|
||||
format: image.image.format(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,17 +1,24 @@
|
|||
use crate::framebuffer::OutputView;
|
||||
use crate::{error, util};
|
||||
use librashader_reflect::back::wgsl::NagaWgslContext;
|
||||
use librashader_reflect::back::ShaderCompilerOutput;
|
||||
use librashader_reflect::reflect::ShaderReflection;
|
||||
use librashader_runtime::render_target::RenderTarget;
|
||||
use std::borrow::Cow;
|
||||
use std::sync::Arc;
|
||||
use wgpu::{BindGroup, BindGroupDescriptor, BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BufferBindingType, BufferSize, CommandEncoder, Device, Operations, PipelineLayout, PushConstantRange, RenderPass, RenderPassColorAttachment, RenderPassDescriptor, RenderPipelineDescriptor, SamplerBindingType, ShaderModule, ShaderSource, ShaderStages, TextureFormat, TextureSampleType, TextureViewDimension, VertexAttribute, VertexBufferLayout};
|
||||
use librashader_runtime::render_target::RenderTarget;
|
||||
use crate::framebuffer::OutputImage;
|
||||
use wgpu::{
|
||||
BindGroup, BindGroupDescriptor, BindGroupLayout, BindGroupLayoutDescriptor,
|
||||
BindGroupLayoutEntry, BindingType, BufferBindingType, BufferSize, CommandEncoder, Device,
|
||||
Operations, PipelineLayout, PushConstantRange, RenderPass, RenderPassColorAttachment,
|
||||
RenderPassDescriptor, RenderPipelineDescriptor, SamplerBindingType, ShaderModule, ShaderSource,
|
||||
ShaderStages, TextureFormat, TextureSampleType, TextureViewDimension, VertexAttribute,
|
||||
VertexBufferLayout,
|
||||
};
|
||||
|
||||
pub struct WgpuGraphicsPipeline {
|
||||
pub layout: PipelineLayoutObjects,
|
||||
render_pipeline: wgpu::RenderPipeline,
|
||||
pub format: wgpu::TextureFormat
|
||||
pub format: wgpu::TextureFormat,
|
||||
}
|
||||
|
||||
pub struct PipelineLayoutObjects {
|
||||
|
@ -22,7 +29,7 @@ pub struct PipelineLayoutObjects {
|
|||
vertex_entry_name: String,
|
||||
vertex: ShaderModule,
|
||||
fragment: ShaderModule,
|
||||
device: Arc<wgpu::Device>
|
||||
device: Arc<wgpu::Device>,
|
||||
}
|
||||
|
||||
impl PipelineLayoutObjects {
|
||||
|
@ -138,55 +145,56 @@ impl PipelineLayoutObjects {
|
|||
}
|
||||
|
||||
pub fn create_pipeline(&self, framebuffer_format: TextureFormat) -> wgpu::RenderPipeline {
|
||||
self.device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("Render Pipeline"),
|
||||
layout: Some(&self.layout),
|
||||
vertex: wgpu::VertexState {
|
||||
module: &self.vertex,
|
||||
entry_point: &self.vertex_entry_name,
|
||||
buffers: &[VertexBufferLayout {
|
||||
array_stride: 4 * std::mem::size_of::<f32>() as wgpu::BufferAddress,
|
||||
step_mode: wgpu::VertexStepMode::Vertex,
|
||||
attributes: &[
|
||||
wgpu::VertexAttribute {
|
||||
format: wgpu::VertexFormat::Float32x2,
|
||||
offset: 0,
|
||||
shader_location: 0,
|
||||
},
|
||||
wgpu::VertexAttribute {
|
||||
format: wgpu::VertexFormat::Float32x2,
|
||||
offset: (2 * std::mem::size_of::<f32>()) as wgpu::BufferAddress,
|
||||
shader_location: 1,
|
||||
},
|
||||
],
|
||||
}],
|
||||
},
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &self.fragment,
|
||||
entry_point: &self.fragment_entry_name,
|
||||
targets: &[Some(wgpu::ColorTargetState {
|
||||
format: framebuffer_format,
|
||||
blend: Some(wgpu::BlendState::REPLACE),
|
||||
write_mask: wgpu::ColorWrites::ALL,
|
||||
})],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleStrip,
|
||||
strip_index_format: None,
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: None,
|
||||
unclipped_depth: false,
|
||||
polygon_mode: wgpu::PolygonMode::Fill,
|
||||
conservative: false,
|
||||
},
|
||||
depth_stencil: None,
|
||||
multisample: wgpu::MultisampleState {
|
||||
count: 1,
|
||||
mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
multiview: None,
|
||||
})
|
||||
self.device
|
||||
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("Render Pipeline"),
|
||||
layout: Some(&self.layout),
|
||||
vertex: wgpu::VertexState {
|
||||
module: &self.vertex,
|
||||
entry_point: &self.vertex_entry_name,
|
||||
buffers: &[VertexBufferLayout {
|
||||
array_stride: 4 * std::mem::size_of::<f32>() as wgpu::BufferAddress,
|
||||
step_mode: wgpu::VertexStepMode::Vertex,
|
||||
attributes: &[
|
||||
wgpu::VertexAttribute {
|
||||
format: wgpu::VertexFormat::Float32x2,
|
||||
offset: 0,
|
||||
shader_location: 0,
|
||||
},
|
||||
wgpu::VertexAttribute {
|
||||
format: wgpu::VertexFormat::Float32x2,
|
||||
offset: (2 * std::mem::size_of::<f32>()) as wgpu::BufferAddress,
|
||||
shader_location: 1,
|
||||
},
|
||||
],
|
||||
}],
|
||||
},
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &self.fragment,
|
||||
entry_point: &self.fragment_entry_name,
|
||||
targets: &[Some(wgpu::ColorTargetState {
|
||||
format: framebuffer_format,
|
||||
blend: Some(wgpu::BlendState::REPLACE),
|
||||
write_mask: wgpu::ColorWrites::ALL,
|
||||
})],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleStrip,
|
||||
strip_index_format: None,
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: None,
|
||||
unclipped_depth: false,
|
||||
polygon_mode: wgpu::PolygonMode::Fill,
|
||||
conservative: false,
|
||||
},
|
||||
depth_stencil: None,
|
||||
multisample: wgpu::MultisampleState {
|
||||
count: 1,
|
||||
mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
multiview: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,7 +210,7 @@ impl WgpuGraphicsPipeline {
|
|||
Self {
|
||||
layout,
|
||||
render_pipeline,
|
||||
format: render_pass_format
|
||||
format: render_pass_format,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,8 +221,8 @@ impl WgpuGraphicsPipeline {
|
|||
|
||||
pub(crate) fn begin_rendering<'pass>(
|
||||
&'pass self,
|
||||
output: &RenderTarget<'pass, OutputImage>,
|
||||
cmd: &'pass mut CommandEncoder
|
||||
output: &RenderTarget<'pass, OutputView>,
|
||||
cmd: &'pass mut CommandEncoder,
|
||||
) -> RenderPass<'pass> {
|
||||
let mut render_pass = cmd.begin_render_pass(&RenderPassDescriptor {
|
||||
label: Some("librashader"),
|
||||
|
@ -240,19 +248,19 @@ impl WgpuGraphicsPipeline {
|
|||
output.x as u32,
|
||||
output.y as u32,
|
||||
output.output.size.width,
|
||||
output.output.size.height
|
||||
output.output.size.height,
|
||||
);
|
||||
|
||||
|
||||
render_pass.set_viewport(
|
||||
output.x,
|
||||
output.y,
|
||||
output.output.size.width as f32,
|
||||
output.output.size.height as f32,
|
||||
1.0,
|
||||
1.0
|
||||
1.0,
|
||||
);
|
||||
|
||||
render_pass.set_pipeline(&self.render_pipeline);
|
||||
render_pass
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,18 +7,19 @@
|
|||
#![feature(let_chains)]
|
||||
#![feature(strict_provenance)]
|
||||
|
||||
mod buffer;
|
||||
mod draw_quad;
|
||||
mod error;
|
||||
mod filter_chain;
|
||||
mod filter_pass;
|
||||
mod framebuffer;
|
||||
mod graphics_pipeline;
|
||||
mod luts;
|
||||
mod options;
|
||||
mod samplers;
|
||||
mod texture;
|
||||
mod util;
|
||||
mod framebuffer;
|
||||
mod luts;
|
||||
mod options;
|
||||
mod buffer;
|
||||
|
||||
pub use framebuffer::OutputView;
|
||||
pub use filter_chain::FilterChainWGPU;
|
||||
pub use filter_pass::FilterPass;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use std::sync::Arc;
|
||||
use wgpu::{ImageDataLayout, Label, TextureDescriptor};
|
||||
use wgpu::util::DeviceExt;
|
||||
use librashader_presets::TextureConfig;
|
||||
use librashader_runtime::image::{BGRA8, Image};
|
||||
use librashader_runtime::scaling::MipmapSize;
|
||||
use crate::texture::{Handle, InputImage};
|
||||
use librashader_presets::TextureConfig;
|
||||
use librashader_runtime::image::{Image, BGRA8};
|
||||
use librashader_runtime::scaling::MipmapSize;
|
||||
use std::sync::Arc;
|
||||
use wgpu::util::DeviceExt;
|
||||
use wgpu::{ImageDataLayout, Label, TextureDescriptor};
|
||||
|
||||
pub(crate) struct LutTexture(InputImage);
|
||||
impl AsRef<InputImage> for LutTexture {
|
||||
|
@ -16,10 +16,10 @@ impl AsRef<InputImage> for LutTexture {
|
|||
impl LutTexture {
|
||||
pub fn new(
|
||||
device: &wgpu::Device,
|
||||
queue: &mut wgpu::Queue,
|
||||
queue: &wgpu::Queue,
|
||||
_cmd: &mut wgpu::CommandEncoder,
|
||||
image: Image,
|
||||
config: &TextureConfig
|
||||
config: &TextureConfig,
|
||||
) -> LutTexture {
|
||||
let texture = device.create_texture(&TextureDescriptor {
|
||||
label: Some(&config.name),
|
||||
|
@ -39,7 +39,6 @@ impl LutTexture {
|
|||
view_formats: &[wgpu::TextureFormat::Rgba8Unorm],
|
||||
});
|
||||
|
||||
|
||||
queue.write_texture(
|
||||
wgpu::ImageCopyTexture {
|
||||
texture: &texture,
|
||||
|
@ -53,7 +52,7 @@ impl LutTexture {
|
|||
bytes_per_row: Some(4 * image.size.width),
|
||||
rows_per_image: None,
|
||||
},
|
||||
image.size.into()
|
||||
image.size.into(),
|
||||
);
|
||||
|
||||
// todo: mipmaps
|
||||
|
@ -80,4 +79,4 @@ impl LutTexture {
|
|||
|
||||
Self(image)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,4 +7,4 @@ pub struct FrameOptionsWGPU {
|
|||
/// The direction of rendering.
|
||||
/// -1 indicates that the frames are played in reverse order.
|
||||
pub frame_direction: i32,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,12 @@ impl SamplerSet {
|
|||
// SAFETY: the sampler set is complete for the matrix
|
||||
// wrap x filter x mipmap
|
||||
unsafe {
|
||||
Arc::clone(&self.samplers
|
||||
.get(&(wrap, filter, mipmap))
|
||||
.unwrap_unchecked())
|
||||
Arc::clone(
|
||||
&self
|
||||
.samplers
|
||||
.get(&(wrap, filter, mipmap))
|
||||
.unwrap_unchecked(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,8 +51,8 @@ impl SamplerSet {
|
|||
compare: None,
|
||||
anisotropy_clamp: 1,
|
||||
border_color: Some(SamplerBorderColor::TransparentBlack),
|
||||
}),
|
||||
));
|
||||
})),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use wgpu::{TextureFormat, TextureView};
|
||||
use crate::error::FilterChainError;
|
||||
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
|
||||
use librashader_presets::Scale2D;
|
||||
use librashader_runtime::scaling::{MipmapSize, ScaleFramebuffer, ViewportSize};
|
||||
use crate::error::FilterChainError;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use wgpu::{ImageCopyTexture, TextureFormat, TextureView};
|
||||
|
||||
pub struct OwnedImage {
|
||||
device: Arc<wgpu::Device>,
|
||||
|
@ -17,14 +17,14 @@ pub struct OwnedImage {
|
|||
|
||||
pub enum Handle<'a, T> {
|
||||
Borrowed(&'a T),
|
||||
Owned(Arc<T>)
|
||||
Owned(Arc<T>),
|
||||
}
|
||||
|
||||
impl<T> Clone for Handle<'_, T> {
|
||||
fn clone(&self) -> Self {
|
||||
match self {
|
||||
Handle::Borrowed(r) => Handle::Borrowed(r),
|
||||
Handle::Owned(r) => Handle::Owned(Arc::clone(r))
|
||||
Handle::Owned(r) => Handle::Owned(Arc::clone(r)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ impl<T> Deref for Handle<'_, T> {
|
|||
fn deref(&self) -> &Self::Target {
|
||||
match self {
|
||||
Handle::Borrowed(r) => &r,
|
||||
Handle::Owned(r) => &r
|
||||
Handle::Owned(r) => &r,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,12 +56,12 @@ impl AsRef<InputImage> for InputImage {
|
|||
}
|
||||
|
||||
impl OwnedImage {
|
||||
pub fn new(device: Arc<wgpu::Device>,
|
||||
size: Size<u32>,
|
||||
max_miplevels: u32,
|
||||
pub fn new(
|
||||
device: Arc<wgpu::Device>,
|
||||
size: Size<u32>,
|
||||
max_miplevels: u32,
|
||||
format: ImageFormat,
|
||||
) -> Self {
|
||||
|
||||
let format: Option<wgpu::TextureFormat> = format.into();
|
||||
let format = format.unwrap_or(wgpu::TextureFormat::Rgba8Unorm);
|
||||
|
||||
|
@ -117,7 +117,12 @@ impl OwnedImage {
|
|||
|| (!mipmap && self.max_miplevels != 1)
|
||||
|| format != self.image.format()
|
||||
{
|
||||
let mut new = OwnedImage::new(Arc::clone(&self.device), size, self.max_miplevels, format.into());
|
||||
let mut new = OwnedImage::new(
|
||||
Arc::clone(&self.device),
|
||||
size,
|
||||
self.max_miplevels,
|
||||
format.into(),
|
||||
);
|
||||
std::mem::swap(self, &mut new);
|
||||
}
|
||||
size
|
||||
|
@ -132,25 +137,34 @@ impl OwnedImage {
|
|||
mip_filter: filter,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_from(&self, cmd: &mut wgpu::CommandEncoder, source: &wgpu::Texture) {
|
||||
cmd.copy_texture_to_texture(
|
||||
source.as_image_copy(),
|
||||
self.image.as_image_copy(),
|
||||
source.size(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn clear(&self, cmd: &mut wgpu::CommandEncoder) {
|
||||
cmd.clear_texture(&self.image, &wgpu::ImageSubresourceRange::default());
|
||||
}
|
||||
pub fn generate_mipmaps(&self, cmd: &mut wgpu::CommandEncoder) {}
|
||||
}
|
||||
|
||||
impl ScaleFramebuffer for OwnedImage {
|
||||
type Error = FilterChainError;
|
||||
type Context = ();
|
||||
|
||||
fn scale(&mut self,
|
||||
scaling: Scale2D,
|
||||
format: ImageFormat,
|
||||
viewport_size: &Size<u32>,
|
||||
source_size: &Size<u32>,
|
||||
should_mipmap: bool,
|
||||
_context: &Self::Context) -> Result<Size<u32>, Self::Error> {
|
||||
Ok(self.scale(
|
||||
scaling,
|
||||
format,
|
||||
viewport_size,
|
||||
source_size,
|
||||
should_mipmap,
|
||||
))
|
||||
fn scale(
|
||||
&mut self,
|
||||
scaling: Scale2D,
|
||||
format: ImageFormat,
|
||||
viewport_size: &Size<u32>,
|
||||
source_size: &Size<u32>,
|
||||
should_mipmap: bool,
|
||||
_context: &Self::Context,
|
||||
) -> Result<Size<u32>, Self::Error> {
|
||||
Ok(self.scale(scaling, format, viewport_size, source_size, should_mipmap))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use std::sync::Arc;
|
||||
use wgpu::{ Maintain, };
|
||||
use wgpu::Maintain;
|
||||
use winit::{
|
||||
event::*,
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
|
@ -12,6 +12,7 @@ use wgpu::util::DeviceExt;
|
|||
use winit::event_loop::EventLoopBuilder;
|
||||
use winit::keyboard::{Key, KeyCode, PhysicalKey};
|
||||
use winit::platform::windows::EventLoopBuilderExtWindows;
|
||||
use librashader_common::Viewport;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
@ -64,7 +65,7 @@ const VERTICES: &[Vertex] = &[
|
|||
struct State<'a> {
|
||||
surface: wgpu::Surface<'a>,
|
||||
device: Arc<wgpu::Device>,
|
||||
queue: wgpu::Queue,
|
||||
queue: Arc<wgpu::Queue>,
|
||||
config: wgpu::SurfaceConfiguration,
|
||||
size: winit::dpi::PhysicalSize<u32>,
|
||||
clear_color: wgpu::Color,
|
||||
|
@ -74,6 +75,7 @@ struct State<'a> {
|
|||
vertex_buffer: wgpu::Buffer,
|
||||
num_vertices: u32,
|
||||
chain: FilterChainWGPU,
|
||||
frame_count: usize
|
||||
}
|
||||
impl<'a> State<'a> {
|
||||
async fn new(window: &'a Window) -> Self {
|
||||
|
@ -91,7 +93,7 @@ impl<'a> State<'a> {
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let (device, mut queue) = adapter
|
||||
let (device, queue) = adapter
|
||||
.request_device(
|
||||
&wgpu::DeviceDescriptor {
|
||||
required_features: wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER,
|
||||
|
@ -106,7 +108,7 @@ impl<'a> State<'a> {
|
|||
let swapchain_format = swapchain_capabilities.formats[0];
|
||||
|
||||
let mut config = wgpu::SurfaceConfiguration {
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_DST,
|
||||
format: swapchain_format,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
|
@ -117,16 +119,22 @@ impl<'a> State<'a> {
|
|||
};
|
||||
|
||||
let device = Arc::new(device);
|
||||
let queue = Arc::new(queue);
|
||||
|
||||
let mut cmd = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
|
||||
label: Some("start encoder"),
|
||||
});
|
||||
|
||||
let preset =
|
||||
ShaderPreset::try_parse("../test/shaders_slang/crt/crt-royale.slangp").unwrap();
|
||||
ShaderPreset::try_parse("../test/basic.slangp").unwrap();
|
||||
|
||||
|
||||
let chain = FilterChainWGPU::load_from_preset_deferred(Arc::clone(&device), &mut queue, &mut cmd, preset).unwrap();
|
||||
let chain = FilterChainWGPU::load_from_preset_deferred(
|
||||
Arc::clone(&device),
|
||||
Arc::clone(&queue),
|
||||
&mut cmd,
|
||||
preset,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let cmd = cmd.finish();
|
||||
|
||||
|
@ -202,6 +210,7 @@ impl<'a> State<'a> {
|
|||
vertex_buffer,
|
||||
num_vertices,
|
||||
chain,
|
||||
frame_count: 0,
|
||||
}
|
||||
}
|
||||
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
|
||||
|
@ -218,9 +227,46 @@ impl<'a> State<'a> {
|
|||
fn update(&mut self) {}
|
||||
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
|
||||
let output = self.surface.get_current_texture()?;
|
||||
let view = output
|
||||
.texture
|
||||
|
||||
let render_output = Arc::new(self.device.create_texture(
|
||||
&wgpu::TextureDescriptor {
|
||||
label: Some("rendertexture"),
|
||||
size: output.texture.size(),
|
||||
mip_level_count: output.texture.mip_level_count(),
|
||||
sample_count: output.texture.sample_count(),
|
||||
dimension: output.texture.dimension(),
|
||||
format: output.texture.format(),
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING
|
||||
| wgpu::TextureUsages::RENDER_ATTACHMENT
|
||||
| wgpu::TextureUsages::COPY_DST
|
||||
| wgpu::TextureUsages::COPY_SRC,
|
||||
view_formats: &[output.texture.format()],
|
||||
}
|
||||
));
|
||||
|
||||
let filter_output = Arc::new(self.device.create_texture(
|
||||
&wgpu::TextureDescriptor {
|
||||
label: Some("filteroutput"),
|
||||
size: output.texture.size(),
|
||||
mip_level_count: output.texture.mip_level_count(),
|
||||
sample_count: output.texture.sample_count(),
|
||||
dimension: output.texture.dimension(),
|
||||
format: output.texture.format(),
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING
|
||||
| wgpu::TextureUsages::RENDER_ATTACHMENT
|
||||
| wgpu::TextureUsages::COPY_DST
|
||||
| wgpu::TextureUsages::COPY_SRC,
|
||||
view_formats: &[output.texture.format()],
|
||||
}
|
||||
));
|
||||
|
||||
|
||||
let view = render_output
|
||||
.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
|
||||
let filter_view = filter_output
|
||||
.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
|
||||
let mut encoder = self
|
||||
.device
|
||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
|
||||
|
@ -228,7 +274,8 @@ impl<'a> State<'a> {
|
|||
});
|
||||
|
||||
{
|
||||
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
let mut render_pass =
|
||||
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: Some("Render Pass"),
|
||||
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||
view: &view,
|
||||
|
@ -247,9 +294,32 @@ impl<'a> State<'a> {
|
|||
render_pass.draw(0..self.num_vertices, 0..1);
|
||||
}
|
||||
|
||||
self.chain
|
||||
.frame(Arc::clone(&render_output),
|
||||
&Viewport {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
mvp: None,
|
||||
output: librashader_runtime_wgpu::OutputView {
|
||||
size: filter_output.size().into(),
|
||||
view: &filter_view,
|
||||
format: filter_output.format(),
|
||||
},
|
||||
},
|
||||
&mut encoder,
|
||||
self.frame_count, None
|
||||
).expect("failed to draw frame");
|
||||
|
||||
encoder.copy_texture_to_texture(
|
||||
filter_output.as_image_copy(),
|
||||
output.texture.as_image_copy(),
|
||||
output.texture.size()
|
||||
);
|
||||
|
||||
self.queue.submit(std::iter::once(encoder.finish()));
|
||||
output.present();
|
||||
|
||||
self.frame_count += 1;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -266,39 +336,36 @@ pub fn run() {
|
|||
|
||||
pollster::block_on(async {
|
||||
let mut state = State::new(&window).await;
|
||||
event_loop.run(|event, target| {
|
||||
|
||||
match event {
|
||||
Event::WindowEvent {
|
||||
window_id: _,
|
||||
event
|
||||
} => match event {
|
||||
WindowEvent::Resized(new_size) => {
|
||||
state.resize(new_size);
|
||||
// On macos the window needs to be redrawn manually after resizing
|
||||
window.request_redraw();
|
||||
}
|
||||
WindowEvent::RedrawRequested => {
|
||||
state.update();
|
||||
match state.render() {
|
||||
Ok(_) => {}
|
||||
Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => {
|
||||
state.resize(state.size)
|
||||
}
|
||||
Err(wgpu::SurfaceError::OutOfMemory) => target.exit(),
|
||||
Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"),
|
||||
event_loop
|
||||
.run(|event, target| {
|
||||
match event {
|
||||
Event::WindowEvent {
|
||||
window_id: _,
|
||||
event,
|
||||
} => match event {
|
||||
WindowEvent::Resized(new_size) => {
|
||||
state.resize(new_size);
|
||||
// On macos the window needs to be redrawn manually after resizing
|
||||
window.request_redraw();
|
||||
}
|
||||
}
|
||||
WindowEvent::CloseRequested => target.exit(),
|
||||
WindowEvent::RedrawRequested => {
|
||||
state.update();
|
||||
match state.render() {
|
||||
Ok(_) => {}
|
||||
Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => {
|
||||
state.resize(state.size)
|
||||
}
|
||||
Err(wgpu::SurfaceError::OutOfMemory) => target.exit(),
|
||||
Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"),
|
||||
}
|
||||
}
|
||||
WindowEvent::CloseRequested => target.exit(),
|
||||
_ => {}
|
||||
},
|
||||
Event::AboutToWait => window.request_redraw(),
|
||||
_ => {}
|
||||
}
|
||||
Event::AboutToWait => {
|
||||
window.request_redraw()
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
||||
}).unwrap();
|
||||
})
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue