migrate blit
This commit is contained in:
parent
88b3b5e71e
commit
9d41372966
@ -1,6 +1,8 @@
|
|||||||
|
use core::{ops::Deref, result::Result};
|
||||||
|
|
||||||
use crate::FullscreenShader;
|
use crate::FullscreenShader;
|
||||||
use bevy_app::{App, Plugin};
|
use bevy_app::{App, Plugin};
|
||||||
use bevy_asset::{embedded_asset, load_embedded_asset, AssetServer, Handle};
|
use bevy_asset::{embedded_asset, load_embedded_asset, AssetServer};
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
render_resource::{
|
render_resource::{
|
||||||
@ -24,8 +26,7 @@ impl Plugin for BlitPlugin {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render_app
|
render_app
|
||||||
.allow_ambiguous_resource::<SpecializedRenderPipelines<BlitPipeline>>()
|
.allow_ambiguous_resource::<BlitPipeline>()
|
||||||
.init_resource::<SpecializedRenderPipelines<BlitPipeline>>()
|
|
||||||
.add_systems(RenderStartup, init_blit_pipeline);
|
.add_systems(RenderStartup, init_blit_pipeline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -34,8 +35,7 @@ impl Plugin for BlitPlugin {
|
|||||||
pub struct BlitPipeline {
|
pub struct BlitPipeline {
|
||||||
pub layout: BindGroupLayout,
|
pub layout: BindGroupLayout,
|
||||||
pub sampler: Sampler,
|
pub sampler: Sampler,
|
||||||
pub fullscreen_shader: FullscreenShader,
|
pub specialized_cache: SpecializedCache<RenderPipeline, BlitSpecializer>,
|
||||||
pub fragment_shader: Handle<Shader>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_blit_pipeline(
|
pub fn init_blit_pipeline(
|
||||||
@ -57,11 +57,23 @@ pub fn init_blit_pipeline(
|
|||||||
|
|
||||||
let sampler = render_device.create_sampler(&SamplerDescriptor::default());
|
let sampler = render_device.create_sampler(&SamplerDescriptor::default());
|
||||||
|
|
||||||
|
let base_descriptor = RenderPipelineDescriptor {
|
||||||
|
label: Some("blit pipeline".into()),
|
||||||
|
layout: vec![layout.clone()],
|
||||||
|
vertex: fullscreen_shader.to_vertex_state(),
|
||||||
|
fragment: Some(FragmentState {
|
||||||
|
shader: load_embedded_asset!(asset_server.deref(), "blit.wgsl"),
|
||||||
|
..default()
|
||||||
|
}),
|
||||||
|
..default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let specialized_cache = SpecializedCache::new(BlitSpecializer, base_descriptor);
|
||||||
|
|
||||||
commands.insert_resource(BlitPipeline {
|
commands.insert_resource(BlitPipeline {
|
||||||
layout,
|
layout,
|
||||||
sampler,
|
sampler,
|
||||||
fullscreen_shader: fullscreen_shader.clone(),
|
specialized_cache,
|
||||||
fragment_shader: load_embedded_asset!(asset_server.as_ref(), "blit.wgsl"),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,35 +91,34 @@ impl BlitPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
|
pub struct BlitSpecializer;
|
||||||
pub struct BlitPipelineKey {
|
|
||||||
|
impl Specializer<RenderPipeline> for BlitSpecializer {
|
||||||
|
type Key = BlitKey;
|
||||||
|
|
||||||
|
fn specialize(
|
||||||
|
&self,
|
||||||
|
key: Self::Key,
|
||||||
|
descriptor: &mut <RenderPipeline as Specializable>::Descriptor,
|
||||||
|
) -> Result<Canonical<Self::Key>, BevyError> {
|
||||||
|
descriptor.multisample.count = key.samples;
|
||||||
|
|
||||||
|
descriptor.fragment_mut()?.set_target(
|
||||||
|
0,
|
||||||
|
ColorTargetState {
|
||||||
|
format: key.texture_format,
|
||||||
|
blend: key.blend_state,
|
||||||
|
write_mask: ColorWrites::ALL,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Hash, Clone, Copy, SpecializerKey)]
|
||||||
|
pub struct BlitKey {
|
||||||
pub texture_format: TextureFormat,
|
pub texture_format: TextureFormat,
|
||||||
pub blend_state: Option<BlendState>,
|
pub blend_state: Option<BlendState>,
|
||||||
pub samples: u32,
|
pub samples: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecializedRenderPipeline for BlitPipeline {
|
|
||||||
type Key = BlitPipelineKey;
|
|
||||||
|
|
||||||
fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
|
|
||||||
RenderPipelineDescriptor {
|
|
||||||
label: Some("blit pipeline".into()),
|
|
||||||
layout: vec![self.layout.clone()],
|
|
||||||
vertex: self.fullscreen_shader.to_vertex_state(),
|
|
||||||
fragment: Some(FragmentState {
|
|
||||||
shader: self.fragment_shader.clone(),
|
|
||||||
targets: vec![Some(ColorTargetState {
|
|
||||||
format: key.texture_format,
|
|
||||||
blend: key.blend_state,
|
|
||||||
write_mask: ColorWrites::ALL,
|
|
||||||
})],
|
|
||||||
..default()
|
|
||||||
}),
|
|
||||||
multisample: MultisampleState {
|
|
||||||
count: key.samples,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
..default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
blit::{BlitPipeline, BlitPipelineKey},
|
blit::{BlitKey, BlitPipeline},
|
||||||
core_2d::graph::{Core2d, Node2d},
|
core_2d::graph::{Core2d, Node2d},
|
||||||
core_3d::graph::{Core3d, Node3d},
|
core_3d::graph::{Core3d, Node3d},
|
||||||
};
|
};
|
||||||
@ -119,22 +119,23 @@ pub struct MsaaWritebackBlitPipeline(CachedRenderPipelineId);
|
|||||||
fn prepare_msaa_writeback_pipelines(
|
fn prepare_msaa_writeback_pipelines(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
pipeline_cache: Res<PipelineCache>,
|
pipeline_cache: Res<PipelineCache>,
|
||||||
mut pipelines: ResMut<SpecializedRenderPipelines<BlitPipeline>>,
|
mut blit_pipeline: ResMut<BlitPipeline>,
|
||||||
blit_pipeline: Res<BlitPipeline>,
|
|
||||||
view_targets: Query<(Entity, &ViewTarget, &ExtractedCamera, &Msaa)>,
|
view_targets: Query<(Entity, &ViewTarget, &ExtractedCamera, &Msaa)>,
|
||||||
) {
|
) -> Result<(), BevyError> {
|
||||||
for (entity, view_target, camera, msaa) in view_targets.iter() {
|
for (entity, view_target, camera, msaa) in view_targets.iter() {
|
||||||
// only do writeback if writeback is enabled for the camera and this isn't the first camera in the target,
|
// only do writeback if writeback is enabled for the camera and this isn't the first camera in the target,
|
||||||
// as there is nothing to write back for the first camera.
|
// as there is nothing to write back for the first camera.
|
||||||
if msaa.samples() > 1 && camera.msaa_writeback && camera.sorted_camera_index_for_target > 0
|
if msaa.samples() > 1 && camera.msaa_writeback && camera.sorted_camera_index_for_target > 0
|
||||||
{
|
{
|
||||||
let key = BlitPipelineKey {
|
let key = BlitKey {
|
||||||
texture_format: view_target.main_texture_format(),
|
texture_format: view_target.main_texture_format(),
|
||||||
samples: msaa.samples(),
|
samples: msaa.samples(),
|
||||||
blend_state: None,
|
blend_state: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let pipeline = pipelines.specialize(&pipeline_cache, &blit_pipeline, key);
|
let pipeline = blit_pipeline
|
||||||
|
.specialized_cache
|
||||||
|
.specialize(&pipeline_cache, key)?;
|
||||||
commands
|
commands
|
||||||
.entity(entity)
|
.entity(entity)
|
||||||
.insert(MsaaWritebackBlitPipeline(pipeline));
|
.insert(MsaaWritebackBlitPipeline(pipeline));
|
||||||
@ -146,4 +147,5 @@ fn prepare_msaa_writeback_pipelines(
|
|||||||
.remove::<MsaaWritebackBlitPipeline>();
|
.remove::<MsaaWritebackBlitPipeline>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::blit::{BlitPipeline, BlitPipelineKey};
|
use crate::blit::{BlitKey, BlitPipeline};
|
||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
use bevy_platform::collections::HashSet;
|
use bevy_platform::collections::HashSet;
|
||||||
@ -39,10 +39,9 @@ pub struct ViewUpscalingPipeline(CachedRenderPipelineId);
|
|||||||
fn prepare_view_upscaling_pipelines(
|
fn prepare_view_upscaling_pipelines(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut pipeline_cache: ResMut<PipelineCache>,
|
mut pipeline_cache: ResMut<PipelineCache>,
|
||||||
mut pipelines: ResMut<SpecializedRenderPipelines<BlitPipeline>>,
|
mut blit_pipeline: ResMut<BlitPipeline>,
|
||||||
blit_pipeline: Res<BlitPipeline>,
|
|
||||||
view_targets: Query<(Entity, &ViewTarget, Option<&ExtractedCamera>)>,
|
view_targets: Query<(Entity, &ViewTarget, Option<&ExtractedCamera>)>,
|
||||||
) {
|
) -> Result<(), BevyError> {
|
||||||
let mut output_textures = <HashSet<_>>::default();
|
let mut output_textures = <HashSet<_>>::default();
|
||||||
for (entity, view_target, camera) in view_targets.iter() {
|
for (entity, view_target, camera) in view_targets.iter() {
|
||||||
let out_texture_id = view_target.out_texture().id();
|
let out_texture_id = view_target.out_texture().id();
|
||||||
@ -73,12 +72,14 @@ fn prepare_view_upscaling_pipelines(
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let key = BlitPipelineKey {
|
let key = BlitKey {
|
||||||
texture_format: view_target.out_texture_format(),
|
texture_format: view_target.out_texture_format(),
|
||||||
blend_state,
|
blend_state,
|
||||||
samples: 1,
|
samples: 1,
|
||||||
};
|
};
|
||||||
let pipeline = pipelines.specialize(&pipeline_cache, &blit_pipeline, key);
|
let pipeline = blit_pipeline
|
||||||
|
.specialized_cache
|
||||||
|
.specialize(&pipeline_cache, key)?;
|
||||||
|
|
||||||
// Ensure the pipeline is loaded before continuing the frame to prevent frames without any GPU work submitted
|
// Ensure the pipeline is loaded before continuing the frame to prevent frames without any GPU work submitted
|
||||||
pipeline_cache.block_on_render_pipeline(pipeline);
|
pipeline_cache.block_on_render_pipeline(pipeline);
|
||||||
@ -87,4 +88,6 @@ fn prepare_view_upscaling_pipelines(
|
|||||||
.entity(entity)
|
.entity(entity)
|
||||||
.insert(ViewUpscalingPipeline(pipeline));
|
.insert(ViewUpscalingPipeline(pipeline));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user