render: make it easier to get Frame from RenderTarget
This commit is contained in:
parent
6c1bff5768
commit
0e71c5734f
|
@ -86,15 +86,4 @@ impl<'a> RenderGraphContext<'a> {
|
||||||
) {
|
) {
|
||||||
self.queue_buffer_write(target_slot, offset, bytemuck::bytes_of(&bytes));
|
self.queue_buffer_write(target_slot, offset, bytemuck::bytes_of(&bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_frame(&self, render_target: &RenderTarget) -> super::Frame {
|
|
||||||
let texture = render_target.frame_texture()
|
|
||||||
.expect("failed to create frame texture"); // should this be returned to the user?
|
|
||||||
|
|
||||||
Frame {
|
|
||||||
device: self.device.clone(),
|
|
||||||
queue: self.queue.clone(),
|
|
||||||
texture,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,7 +168,7 @@ impl Node for BasePass {
|
||||||
.expect("somehow the main render target slot is missing");
|
.expect("somehow the main render target slot is missing");
|
||||||
let rt = tv_slot.as_render_target().unwrap();
|
let rt = tv_slot.as_render_target().unwrap();
|
||||||
let rt_size = rt.size();
|
let rt_size = rt.size();
|
||||||
let frame = context.get_frame(&rt);
|
let frame = rt.create_frame();
|
||||||
/* debug_assert!(
|
/* debug_assert!(
|
||||||
!rt.current_texture.is_some(),
|
!rt.current_texture.is_some(),
|
||||||
"main render target surface was not presented!"
|
"main render target surface was not presented!"
|
||||||
|
|
|
@ -0,0 +1,190 @@
|
||||||
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
|
use lyra_game_derive::RenderGraphLabel;
|
||||||
|
|
||||||
|
use crate::render::{
|
||||||
|
graph::{Node, NodeDesc, NodeSlot, NodeType, RenderTarget, SlotAttribute, SlotType, SlotValue},
|
||||||
|
resource::{FragmentState, PipelineDescriptor, RenderPipelineDescriptor, Shader, VertexState},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::BasePassSlots;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Hash, RenderGraphLabel)]
|
||||||
|
pub enum TintPassSlots {
|
||||||
|
InputRenderTarget,
|
||||||
|
InputTextureView,
|
||||||
|
|
||||||
|
TextureViewBindGroup,
|
||||||
|
Frame
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Clone, Copy, Hash, RenderGraphLabel)]
|
||||||
|
pub struct TintPassLabel;
|
||||||
|
|
||||||
|
pub struct TintPass {
|
||||||
|
render_target: Option<RenderTarget>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TintPass {
|
||||||
|
pub fn new(render_target: RenderTarget) -> Self {
|
||||||
|
Self {
|
||||||
|
render_target: Some(render_target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Node for TintPass {
|
||||||
|
fn desc<'a, 'b>(
|
||||||
|
&'a mut self,
|
||||||
|
graph: &'b mut crate::render::graph::RenderGraph,
|
||||||
|
) -> crate::render::graph::NodeDesc {
|
||||||
|
let device = &graph.device;
|
||||||
|
|
||||||
|
// get surface config format
|
||||||
|
/* let main_rt = graph
|
||||||
|
.slot_value(BasePassSlots::MainRenderTarget)
|
||||||
|
.and_then(|s| s.as_render_target())
|
||||||
|
.expect("missing main render target");
|
||||||
|
let surface_config_format = main_rt.format();
|
||||||
|
drop(main_rt); */
|
||||||
|
|
||||||
|
let bgl = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
|
label: Some("tint_bgl"),
|
||||||
|
entries: &[
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 0,
|
||||||
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||||
|
ty: wgpu::BindingType::Texture {
|
||||||
|
sample_type: wgpu::TextureSampleType::Float { filterable: false },
|
||||||
|
view_dimension: wgpu::TextureViewDimension::D2,
|
||||||
|
multisampled: false,
|
||||||
|
},
|
||||||
|
count: None,
|
||||||
|
},
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 1,
|
||||||
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||||
|
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::NonFiltering),
|
||||||
|
count: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
let bgl = Rc::new(bgl);
|
||||||
|
|
||||||
|
let input_view = graph
|
||||||
|
.slot_value(BasePassSlots::WindowTextureView)
|
||||||
|
.and_then(|s| s.as_texture_view())
|
||||||
|
.expect("missing input texture view");
|
||||||
|
|
||||||
|
let bg = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
|
label: Some("tint_bg"),
|
||||||
|
layout: &*bgl,
|
||||||
|
entries: &[wgpu::BindGroupEntry {
|
||||||
|
binding: 0,
|
||||||
|
resource: wgpu::BindingResource::TextureView(input_view),
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
|
||||||
|
let shader = Rc::new(Shader {
|
||||||
|
label: Some("tint_shader".into()),
|
||||||
|
source: include_str!("../../shaders/tint.wgsl").to_string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut desc = NodeDesc::new(
|
||||||
|
NodeType::Render,
|
||||||
|
Some(PipelineDescriptor::Render(RenderPipelineDescriptor {
|
||||||
|
label: Some("tint_pass".into()),
|
||||||
|
layouts: vec![bgl.clone()],
|
||||||
|
push_constant_ranges: vec![],
|
||||||
|
vertex: VertexState {
|
||||||
|
module: shader.clone(),
|
||||||
|
entry_point: "vs_main".into(),
|
||||||
|
buffers: vec![],
|
||||||
|
},
|
||||||
|
fragment: Some(FragmentState {
|
||||||
|
module: shader,
|
||||||
|
entry_point: "fs_main".into(),
|
||||||
|
targets: vec![Some(wgpu::ColorTargetState {
|
||||||
|
format: self.render_target.as_ref().unwrap().format(),
|
||||||
|
blend: Some(wgpu::BlendState::REPLACE),
|
||||||
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
|
})],
|
||||||
|
}),
|
||||||
|
depth_stencil: None,
|
||||||
|
primitive: wgpu::PrimitiveState::default(),
|
||||||
|
multisample: wgpu::MultisampleState::default(),
|
||||||
|
multiview: None,
|
||||||
|
})),
|
||||||
|
vec![(&TintPassSlots::TextureViewBindGroup, bg.into(), Some(bgl))],
|
||||||
|
);
|
||||||
|
|
||||||
|
// desc.add_buffer_slot(
|
||||||
|
// FxaaPassSlots::Lights,
|
||||||
|
// SlotAttribute::Output,
|
||||||
|
// Some(SlotValue::Buffer(light_buffers.buffer.clone())),
|
||||||
|
// );
|
||||||
|
|
||||||
|
desc.add_slot(NodeSlot {
|
||||||
|
ty: SlotType::Frame,
|
||||||
|
attribute: SlotAttribute::Output,
|
||||||
|
label: TintPassSlots::Frame.into(),
|
||||||
|
value: Some(SlotValue::Lazy),
|
||||||
|
});
|
||||||
|
|
||||||
|
desc
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare(
|
||||||
|
&mut self,
|
||||||
|
_: &mut crate::render::graph::RenderGraph,
|
||||||
|
_: &mut lyra_ecs::World,
|
||||||
|
_: &mut crate::render::graph::RenderGraphContext,
|
||||||
|
) {
|
||||||
|
//todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execute(
|
||||||
|
&mut self,
|
||||||
|
graph: &mut crate::render::graph::RenderGraph,
|
||||||
|
_: &crate::render::graph::NodeDesc,
|
||||||
|
context: &mut crate::render::graph::RenderGraphContext,
|
||||||
|
) {
|
||||||
|
let rt = self.render_target.as_ref().unwrap();
|
||||||
|
let frame = rt.create_frame();
|
||||||
|
|
||||||
|
let view = frame.texture()
|
||||||
|
.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
|
|
||||||
|
let frame_slot = graph
|
||||||
|
.slot_value_mut(TintPassSlots::Frame)
|
||||||
|
.expect("somehow the frame slot is missing");
|
||||||
|
*frame_slot = SlotValue::Frame(Rc::new(RefCell::new(Some(frame))));
|
||||||
|
|
||||||
|
let bg = graph.bind_group(TintPassSlots::TextureViewBindGroup);
|
||||||
|
|
||||||
|
/* let view = graph
|
||||||
|
.slot_value(BasePassSlots::WindowTextureView)
|
||||||
|
.unwrap()
|
||||||
|
.as_texture_view()
|
||||||
|
.expect("BasePassSlots::WindowTextureView was not a TextureView slot"); */
|
||||||
|
|
||||||
|
{
|
||||||
|
let encoder = context.encoder.as_mut().unwrap();
|
||||||
|
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
|
label: Some("tint_pass"),
|
||||||
|
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||||
|
view: &view,
|
||||||
|
resolve_target: None,
|
||||||
|
ops: wgpu::Operations {
|
||||||
|
load: wgpu::LoadOp::Load,
|
||||||
|
store: true,
|
||||||
|
},
|
||||||
|
})],
|
||||||
|
depth_stencil_attachment: None,
|
||||||
|
});
|
||||||
|
|
||||||
|
pass.set_bind_group(0, bg, &[]);
|
||||||
|
pass.draw(0..4, 0..1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -89,6 +89,21 @@ impl RenderTarget {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create the frame of the RenderTarget.
|
||||||
|
///
|
||||||
|
/// If this is target is a surface and the frame texture was already retrieved from the
|
||||||
|
/// swap chain, a [`wgpu::SurfaceError`] error will be returned.
|
||||||
|
pub fn create_frame(&self) -> Frame {
|
||||||
|
let texture = self.frame_texture()
|
||||||
|
.expect("failed to create frame texture"); // TODO: should be returned to the user
|
||||||
|
let size = self.size();
|
||||||
|
|
||||||
|
Frame {
|
||||||
|
size,
|
||||||
|
texture,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum FrameTexture {
|
pub enum FrameTexture {
|
||||||
|
@ -96,10 +111,12 @@ pub enum FrameTexture {
|
||||||
Texture(Arc<wgpu::Texture>),
|
Texture(Arc<wgpu::Texture>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
/// Represents the current frame that is being rendered to.
|
||||||
|
//#[allow(dead_code)]
|
||||||
pub struct Frame {
|
pub struct Frame {
|
||||||
pub(crate) device: Arc<wgpu::Device>,
|
/* pub(crate) device: Arc<wgpu::Device>,
|
||||||
pub(crate) queue: Arc<wgpu::Queue>,
|
pub(crate) queue: Arc<wgpu::Queue>, */
|
||||||
|
pub(crate) size: math::UVec2,
|
||||||
pub(crate) texture: FrameTexture,
|
pub(crate) texture: FrameTexture,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,4 +137,9 @@ impl Frame {
|
||||||
FrameTexture::Texture(_) => {},
|
FrameTexture::Texture(_) => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The size of the frame
|
||||||
|
pub fn size(&self) -> math::UVec2 {
|
||||||
|
self.size
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
@group(0) @binding(0)
|
||||||
|
var t_screen: texture_2d<f32>;
|
||||||
|
@group(0) @binding(1)
|
||||||
|
var s_screen: sampler;
|
||||||
|
|
||||||
|
struct VertexOutput {
|
||||||
|
@builtin(position) clip_position: vec4<f32>,
|
||||||
|
@location(0) tex_coords: vec2<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
@vertex
|
||||||
|
fn vs_main(
|
||||||
|
@builtin(vertex_index) vertex_index: u32,
|
||||||
|
) -> VertexOutput {
|
||||||
|
|
||||||
|
const vertices = array<vec4<f32>, 4>(vec4<f32>(-1.0, -1.0, 0.0, 1.0), vec4<f32>(1.0, -1.0, 0.0, 1.0), vec4<f32>(-1.0, 1.0, 0.0, 1.0), vec4<f32>(1.0, 1.0, 0.0, 1.0));
|
||||||
|
const tex_coords = array<vec2<f32>, 4>(vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 0.0), vec2<f32>(0.0, 1.0), vec2<f32>(1.0, 1.0));
|
||||||
|
|
||||||
|
var out: VertexOutput;
|
||||||
|
out.clip_position = vertices[vertex_index];
|
||||||
|
out.tex_coords = tex_coords[vertex_index];
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
|
let rgb: vec3<f32> = textureSample(t_screen, s_screen, in.tex_coords).xyz;
|
||||||
|
rgb *= vec3<f32>(0.8);
|
||||||
|
return vec4<f32>(rgb, 1.0);
|
||||||
|
}
|
Loading…
Reference in New Issue