pathfinder: more backend work. it now renders the clear color without crashing

This commit is contained in:
Carter Anderson 2020-05-11 09:01:31 -07:00
parent a5f47fd7da
commit 35e1d8b498
11 changed files with 460 additions and 97 deletions

View file

@ -71,6 +71,10 @@ opt-level = 3
name = "hello_world"
path = "examples/hello_world.rs"
[[example]]
name = "pathfinder"
path = "examples/2d/pathfinder.rs"
[[example]]
name = "sprite"
path = "examples/2d/sprite.rs"

View file

@ -1,23 +1,33 @@
use bevy_asset::{AssetStorage, Handle};
use bevy_render::{
pipeline::{
state_descriptors::CompareFunction, InputStepMode, PipelineDescriptor,
VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat,
pass::{
LoadOp, PassDescriptor, RenderPassColorAttachmentDescriptor,
RenderPassDepthStencilAttachmentDescriptor, StoreOp, TextureAttachment,
},
render_resource::{BufferInfo, BufferUsage, RenderResource},
pipeline::{
state_descriptors::{
BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite,
CompareFunction, DepthStencilStateDescriptor, StencilOperation,
StencilStateFaceDescriptor,
},
InputStepMode, PipelineDescriptor, VertexAttributeDescriptor, VertexBufferDescriptor,
VertexFormat,
},
render_resource::{BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments},
renderer::RenderContext,
shader::{Shader, ShaderSource, ShaderStage, ShaderStages},
texture::{
AddressMode, Extent3d, FilterMode, SamplerDescriptor, TextureDescriptor, TextureDimension,
TextureFormat, TextureUsage,
},
Color,
};
use pathfinder_canvas::vec2i;
use pathfinder_geometry::{rect::RectI, vector::Vector2I};
use pathfinder_gpu::{
BufferData, BufferTarget, BufferUploadMode, Device, ProgramKind, RenderState, RenderTarget,
ShaderKind, TextureData, TextureDataRef, TextureSamplingFlags, VertexAttrClass,
VertexAttrDescriptor, VertexAttrType, FeatureLevel,
BufferData, BufferTarget, BufferUploadMode, Device, FeatureLevel, ProgramKind, RenderState,
RenderTarget, ShaderKind, TextureData, TextureDataRef, TextureSamplingFlags, VertexAttrClass,
VertexAttrDescriptor, VertexAttrType,
};
use pathfinder_resources::ResourceLoader;
use std::{borrow::Cow, cell::RefCell, collections::HashMap, mem, rc::Rc, time::Duration};
@ -27,17 +37,245 @@ pub struct BevyPathfinderDevice<'a> {
render_context: RefCell<&'a mut dyn RenderContext>,
shaders: RefCell<&'a mut AssetStorage<Shader>>,
samplers: RefCell<HashMap<u8, RenderResource>>,
main_color_texture: RenderResource,
main_depth_stencil_texture: RenderResource,
}
impl<'a> BevyPathfinderDevice<'a> {
pub fn new(
render_context: &'a mut dyn RenderContext,
shaders: &'a mut AssetStorage<Shader>,
main_color_texture: RenderResource,
main_depth_stencil_texture: RenderResource,
) -> Self {
BevyPathfinderDevice {
render_context: RefCell::new(render_context),
shaders: RefCell::new(shaders),
samplers: RefCell::new(HashMap::new()),
main_color_texture,
main_depth_stencil_texture,
}
}
pub fn prepare_to_draw(&self, render_state: &RenderState<BevyPathfinderDevice>) {
let pass_descriptor = self.create_pass_descriptor(render_state);
self.update_pipline_descriptor(render_state, &pass_descriptor);
// setup uniforms
let mut render_context = self.render_context.borrow_mut();
let render_resource_assignments = RenderResourceAssignments::default();
render_context.begin_pass(
&pass_descriptor,
&render_resource_assignments,
&mut |pass| {
let viewport = render_state.viewport;
pass.set_viewport(
viewport.origin().x() as f32,
viewport.origin().y() as f32,
viewport.size().x() as f32,
viewport.size().y() as f32,
0.0,
1.0,
);
if let Some(stencil_state) = render_state.options.stencil {
pass.set_stencil_reference(stencil_state.reference);
}
for (i, vertex_buffer) in render_state
.vertex_array
.vertex_buffers
.borrow()
.iter()
.enumerate()
{
let resource = vertex_buffer.handle.borrow().unwrap();
pass.set_vertex_buffer(i as u32, resource, 0);
}
if let Some(ref index_buffer) = *render_state.vertex_array.index_buffer.borrow(){
let resource = index_buffer.handle.borrow().unwrap();
pass.set_index_buffer(resource, 0);
}
},
)
}
fn get_texture_format(&self, _render_resource: RenderResource) -> Option<TextureFormat> {
// TODO: lookup real texture format
// let mut texture_format = None;
// self.render_context.borrow().resources().get_resource_info(
// texture_resource,
// &mut |info| {
// if let Some(info) = info {
// match info {
// ResourceInfo::Texture {
// }
// }
// texture_format = Some(info)
// }
// },
// );
Some(TextureFormat::Bgra8UnormSrgb)
}
pub fn update_pipline_descriptor(
&self,
render_state: &RenderState<BevyPathfinderDevice>,
pass_descriptor: &PassDescriptor,
) {
if self.render_context.borrow().resources().get_asset_resource(render_state.program.pipeline_handle, 0).is_some() {
return
}
let mut pipeline_descriptor = render_state.program.pipeline_descriptor.borrow_mut();
let color_texture_format = if let TextureAttachment::RenderResource(texture_resource) =
pass_descriptor
.color_attachments
.first()
.unwrap()
.attachment
{
self.get_texture_format(texture_resource)
.expect("expected color attachment RenderResource to have a texture format")
} else {
panic!("expected a RenderResource color attachment");
};
// TODO: lookup real texture format
// TODO: make sure colors render correctly
let mut color_state = ColorStateDescriptor {
format: color_texture_format,
color_blend: BlendDescriptor {
src_factor: BlendFactor::SrcAlpha,
dst_factor: BlendFactor::OneMinusSrcAlpha,
operation: BlendOperation::Add,
},
alpha_blend: BlendDescriptor {
src_factor: BlendFactor::One,
dst_factor: BlendFactor::One,
operation: BlendOperation::Add,
},
write_mask: if render_state.options.color_mask {
ColorWrite::all()
} else {
ColorWrite::empty()
},
};
if let Some(blend_state) = render_state.options.blend {
let blend_op = blend_state.op.to_bevy_blend_op();
color_state.color_blend.src_factor = blend_state.src_rgb_factor.to_bevy_blend_factor();
color_state.color_blend.dst_factor = blend_state.dest_rgb_factor.to_bevy_blend_factor();
color_state.color_blend.operation = blend_op;
color_state.alpha_blend.src_factor =
blend_state.src_alpha_factor.to_bevy_blend_factor();
color_state.alpha_blend.dst_factor =
blend_state.dest_alpha_factor.to_bevy_blend_factor();
color_state.color_blend.operation = blend_op;
}
pipeline_descriptor.color_states.push(color_state);
if let Some(ref _pass_depth_stencil_descriptor) = pass_descriptor.depth_stencil_attachment {
// TODO: lookup texture format
// TODO: maybe we need a stencil-type depth format? TextureFormat::Depth24PlusStencil8
let depth_format = TextureFormat::Depth32Float;
let mut descriptor = DepthStencilStateDescriptor {
format: depth_format,
depth_write_enabled: false,
depth_compare: CompareFunction::Less,
stencil_front: StencilStateFaceDescriptor::IGNORE,
stencil_back: StencilStateFaceDescriptor::IGNORE,
stencil_read_mask: 0,
stencil_write_mask: 0,
};
if let Some(depth_state) = render_state.options.depth {
let compare_function = depth_state.func.to_bevy_compare_function();
descriptor.depth_compare = compare_function;
descriptor.depth_write_enabled = true;
}
if let Some(stencil_state) = render_state.options.stencil {
let compare = stencil_state.func.to_bevy_compare_function();
let (pass_op, write_mask) = if stencil_state.write {
(StencilOperation::Replace, stencil_state.mask)
} else {
(StencilOperation::Keep, 0)
};
let stencil_descriptor = StencilStateFaceDescriptor {
compare,
pass_op,
depth_fail_op: StencilOperation::Keep,
fail_op: StencilOperation::Keep,
};
descriptor.stencil_write_mask = write_mask;
descriptor.stencil_front = stencil_descriptor.clone();
descriptor.stencil_back = stencil_descriptor;
}
}
}
pub fn create_pass_descriptor(
&self,
render_state: &RenderState<BevyPathfinderDevice>,
) -> PassDescriptor {
let mut depth_texture = None;
let color_texture = match render_state.target {
RenderTarget::Default { .. } => {
depth_texture = Some(self.main_depth_stencil_texture);
self.main_color_texture
}
RenderTarget::Framebuffer(framebuffer) => framebuffer.handle,
};
let mut color_attachment = RenderPassColorAttachmentDescriptor {
attachment: TextureAttachment::RenderResource(color_texture),
clear_color: Color::WHITE,
load_op: LoadOp::Load,
store_op: StoreOp::Store,
resolve_target: None,
};
if let Some(color) = render_state.options.clear_ops.color {
color_attachment.clear_color = Color::rgba(color.r(), color.g(), color.b(), color.a());
color_attachment.load_op = LoadOp::Clear;
}
let depth_stencil_attachment = if let Some(depth_texture) = depth_texture {
let mut descriptor = RenderPassDepthStencilAttachmentDescriptor {
attachment: TextureAttachment::RenderResource(depth_texture),
depth_load_op: LoadOp::Load,
depth_store_op: StoreOp::Store,
stencil_load_op: LoadOp::Load,
stencil_store_op: StoreOp::Store,
clear_depth: 1.0,
clear_stencil: 0,
};
if let Some(depth) = render_state.options.clear_ops.depth {
descriptor.clear_depth = depth;
descriptor.depth_load_op = LoadOp::Clear;
}
if let Some(value) = render_state.options.clear_ops.stencil {
descriptor.clear_stencil = value as u32;
descriptor.stencil_load_op = LoadOp::Clear;
}
Some(descriptor)
} else {
None
};
PassDescriptor {
color_attachments: vec![color_attachment],
depth_stencil_attachment,
sample_count: 1,
}
}
}
@ -59,6 +297,11 @@ pub struct BevyVertexArray {
index_buffer: RefCell<Option<BevyBuffer>>,
}
pub struct BevyProgram {
pipeline_descriptor: RefCell<PipelineDescriptor>,
pipeline_handle: Handle<PipelineDescriptor>,
}
pub struct BevyTexture {
handle: RenderResource,
texture_descriptor: TextureDescriptor,
@ -75,7 +318,7 @@ impl<'a> Device for BevyPathfinderDevice<'a> {
type Buffer = BevyBuffer;
type Fence = ();
type Framebuffer = BevyTexture;
type Program = PipelineDescriptor;
type Program = BevyProgram;
type Shader = Handle<Shader>;
type StorageBuffer = ();
type Texture = BevyTexture;
@ -134,25 +377,6 @@ impl<'a> Device for BevyPathfinderDevice<'a> {
name: &str,
kind: ShaderKind,
) -> Self::Shader {
// let shader_bytes = match (name, kind) {
// ("blit", ShaderKind::Fragment) => shaders::BLIT_FS,
// ("blit", ShaderKind::Vertex) => shaders::BLIT_VS,
// // ("debug_solid", ShaderKind::Fragment) => shaders::DEMO_GROUND_FS,
// // ("demo_ground", ShaderKind::Vertex) => shaders::DEMO_GROUND_VS,
// ("fill", ShaderKind::Fragment) => shaders::FILL_FS,
// ("fill", ShaderKind::Vertex) => shaders::FILL_VS,
// ("reproject", ShaderKind::Fragment) => shaders::REPROJECT_FS,
// ("reproject", ShaderKind::Vertex) => shaders::REPROJECT_VS,
// ("stencil", ShaderKind::Fragment) => shaders::STENCIL_FS,
// ("stencil", ShaderKind::Vertex) => shaders::STENCIL_VS,
// ("tile_clip", ShaderKind::Fragment) => shaders::TILE_CLIP_FS,
// ("tile_clip", ShaderKind::Vertex) => shaders::TILE_CLIP_VS,
// ("tile_copy", ShaderKind::Fragment) => shaders::TILE_COPY_FS,
// ("tile_copy", ShaderKind::Vertex) => shaders::TILE_COPY_VS,
// ("tile", ShaderKind::Fragment) => shaders::TILE_FS,
// ("tile", ShaderKind::Vertex) => shaders::TILE_VS,
// _ => panic!("encountered unexpected shader {} {:?}", name, kind),
// };
let suffix = match kind {
ShaderKind::Vertex => 'v',
ShaderKind::Fragment => 'f',
@ -196,7 +420,7 @@ impl<'a> Device for BevyPathfinderDevice<'a> {
_resources: &dyn ResourceLoader,
_name: &str,
shaders: ProgramKind<Handle<Shader>>,
) -> Self::Program {
) -> BevyProgram {
match shaders {
ProgramKind::Compute(_) => panic!("bevy does not currently support compute shaders"),
ProgramKind::Raster { vertex, fragment } => {
@ -205,17 +429,17 @@ impl<'a> Device for BevyPathfinderDevice<'a> {
fragment: Some(fragment),
});
descriptor.reflect_layout(&self.shaders.borrow(), false, None, None);
descriptor
BevyProgram {
pipeline_descriptor: RefCell::new(descriptor),
pipeline_handle: Handle::new(),
}
}
}
}
fn get_vertex_attr(
&self,
descriptor: &PipelineDescriptor,
name: &str,
) -> Option<Self::VertexAttr> {
fn get_vertex_attr(&self, program: &BevyProgram, name: &str) -> Option<BevyVertexAttr> {
// TODO: this probably isn't actually used for anything. try to optimize
let layout = descriptor.get_layout().unwrap();
let pipeline_descriptor = program.pipeline_descriptor.borrow();
let layout = pipeline_descriptor.get_layout().unwrap();
let attribute_name = format!("a{}", name);
for buffer_descriptor in layout.vertex_buffer_descriptors.iter() {
let attribute = buffer_descriptor
@ -230,12 +454,9 @@ impl<'a> Device for BevyPathfinderDevice<'a> {
}
}
// // TODO: remove this
// panic!("failed to find attribute {} ", attribute_name);
None
}
fn get_uniform(&self, _program: &PipelineDescriptor, name: &str) -> Self::Uniform {
fn get_uniform(&self, _program: &BevyProgram, name: &str) -> Self::Uniform {
BevyUniform {
name: name.to_string(),
}
@ -251,10 +472,7 @@ impl<'a> Device for BevyPathfinderDevice<'a> {
.vertex_buffers
.borrow_mut()
.push(buffer.clone()),
BufferTarget::Index => {
*vertex_array.index_buffer.borrow_mut() =
Some(buffer.clone())
}
BufferTarget::Index => *vertex_array.index_buffer.borrow_mut() = Some(buffer.clone()),
_ => panic!("Buffers bound to vertex arrays must be vertex or index buffers!"),
}
}
@ -370,10 +588,16 @@ impl<'a> Device for BevyPathfinderDevice<'a> {
}
}
fn allocate_buffer<T>(&self, buffer: &BevyBuffer, data: BufferData<T>, _target: BufferTarget) {
fn allocate_buffer<T>(&self, buffer: &BevyBuffer, data: BufferData<T>, target: BufferTarget) {
let usage = match target {
BufferTarget::Vertex => BufferUsage::VERTEX,
BufferTarget::Index => BufferUsage::INDEX,
BufferTarget::Storage => BufferUsage::empty(),
};
let buffer_usage = match buffer.mode {
BufferUploadMode::Dynamic => BufferUsage::WRITE_ALL,
BufferUploadMode::Static => BufferUsage::COPY_DST,
BufferUploadMode::Dynamic => BufferUsage::WRITE_ALL | usage,
BufferUploadMode::Static => BufferUsage::COPY_DST | usage,
};
match data {
BufferData::Uninitialized(size) => {
@ -534,19 +758,22 @@ impl<'a> Device for BevyPathfinderDevice<'a> {
fn end_commands(&self) {
// NOTE: the Bevy Render Graph handles command buffer submission
}
fn draw_arrays(&self, _index_count: u32, _render_state: &RenderState<Self>) {
todo!()
fn draw_arrays(&self, _index_count: u32, render_state: &RenderState<Self>) {
self.prepare_to_draw(render_state);
println!("draw_arrays");
}
fn draw_elements(&self, _index_count: u32, _render_state: &RenderState<Self>) {
todo!()
fn draw_elements(&self, _index_count: u32, render_state: &RenderState<Self>) {
self.prepare_to_draw(render_state);
println!("draw_elements");
}
fn draw_elements_instanced(
&self,
_index_count: u32,
_instance_count: u32,
_render_state: &RenderState<Self>,
render_state: &RenderState<Self>,
) {
todo!()
self.prepare_to_draw(render_state);
println!("draw_elements_instanced");
}
fn create_timer_query(&self) -> Self::TimerQuery {
// TODO: maybe not needed
@ -598,7 +825,7 @@ impl<'a> Device for BevyPathfinderDevice<'a> {
.resources()
.create_buffer_with_data(
BufferInfo {
buffer_usage: BufferUsage::COPY_DST,
buffer_usage: BufferUsage::COPY_SRC | BufferUsage::COPY_DST,
..Default::default()
},
slice_to_u8(data_slice),
@ -626,9 +853,7 @@ impl<'a> Device for BevyPathfinderDevice<'a> {
fn get_texture_bytes<'a>(data_ref: &'a TextureDataRef) -> &'a [u8] {
match data_ref {
TextureDataRef::U8(data) => data,
TextureDataRef::F16(data) => {
slice_to_u8(data)
}
TextureDataRef::F16(data) => slice_to_u8(data),
TextureDataRef::F32(data) => data.as_bytes(),
}
}
@ -641,3 +866,61 @@ fn slice_to_u8<T>(slice: &[T]) -> &[u8] {
)
}
}
trait ToBevyBlendOp {
fn to_bevy_blend_op(self) -> BlendOperation;
}
impl ToBevyBlendOp for pathfinder_gpu::BlendOp {
#[inline]
fn to_bevy_blend_op(self) -> BlendOperation {
match self {
pathfinder_gpu::BlendOp::Add => BlendOperation::Add,
pathfinder_gpu::BlendOp::Subtract => BlendOperation::Subtract,
pathfinder_gpu::BlendOp::ReverseSubtract => BlendOperation::ReverseSubtract,
pathfinder_gpu::BlendOp::Min => BlendOperation::Min,
pathfinder_gpu::BlendOp::Max => BlendOperation::Max,
}
}
}
trait ToBevyBlendFactor {
fn to_bevy_blend_factor(self) -> BlendFactor;
}
impl ToBevyBlendFactor for pathfinder_gpu::BlendFactor {
#[inline]
fn to_bevy_blend_factor(self) -> BlendFactor {
match self {
pathfinder_gpu::BlendFactor::Zero => BlendFactor::Zero,
pathfinder_gpu::BlendFactor::One => BlendFactor::One,
pathfinder_gpu::BlendFactor::SrcAlpha => BlendFactor::SrcAlpha,
pathfinder_gpu::BlendFactor::OneMinusSrcAlpha => BlendFactor::OneMinusSrcAlpha,
pathfinder_gpu::BlendFactor::DestAlpha => BlendFactor::DstAlpha,
pathfinder_gpu::BlendFactor::OneMinusDestAlpha => BlendFactor::OneMinusDstAlpha,
pathfinder_gpu::BlendFactor::DestColor => BlendFactor::DstColor,
}
}
}
trait ToBevyCompareFunction {
fn to_bevy_compare_function(self) -> CompareFunction;
}
impl ToBevyCompareFunction for pathfinder_gpu::DepthFunc {
fn to_bevy_compare_function(self) -> CompareFunction {
match self {
pathfinder_gpu::DepthFunc::Always => CompareFunction::Always,
pathfinder_gpu::DepthFunc::Less => CompareFunction::Less,
}
}
}
impl ToBevyCompareFunction for pathfinder_gpu::StencilFunc {
fn to_bevy_compare_function(self) -> CompareFunction {
match self {
pathfinder_gpu::StencilFunc::Always => CompareFunction::Always,
pathfinder_gpu::StencilFunc::Equal => CompareFunction::Equal,
}
}
}

View file

@ -3,7 +3,13 @@ mod pathfinder_node;
use bevy_app::{AppBuilder, AppPlugin};
pub use device::*;
use bevy_render::render_graph::RenderGraph;
use bevy_render::{
base_render_graph,
render_graph::{
nodes::{WindowSwapChainNode, WindowTextureNode},
RenderGraph,
},
};
use pathfinder_node::PathfinderNode;
#[derive(Default)]
@ -13,5 +19,21 @@ impl AppPlugin for PathfinderPlugin {
fn build(&self, app: &mut AppBuilder) {
let mut render_graph = app.resources().get_mut::<RenderGraph>().unwrap();
render_graph.add_node_named("pathfinder", PathfinderNode::default());
render_graph
.add_slot_edge(
base_render_graph::node::PRIMARY_SWAP_CHAIN,
WindowSwapChainNode::OUT_TEXTURE,
"pathfinder",
PathfinderNode::IN_COLOR_TEXTURE,
)
.unwrap();
render_graph
.add_slot_edge(
base_render_graph::node::MAIN_DEPTH_TEXTURE,
WindowTextureNode::OUT_TEXTURE,
"pathfinder",
PathfinderNode::IN_DEPTH_STENCIL_TEXTURE,
)
.unwrap();
}
}

View file

@ -1,7 +1,8 @@
use crate::BevyPathfinderDevice;
use bevy_asset::AssetStorage;
use bevy_render::{
render_graph::{Node, ResourceSlots},
render_graph::{Node, ResourceSlotInfo, ResourceSlots},
render_resource::ResourceInfo,
renderer::RenderContext,
shader::Shader,
};
@ -16,21 +17,47 @@ use pathfinder_renderer::{
options::BuildOptions,
};
use pathfinder_resources::embedded::EmbeddedResourceLoader;
use std::borrow::Cow;
#[derive(Default)]
pub struct PathfinderNode;
impl PathfinderNode {
pub const IN_COLOR_TEXTURE: &'static str = "color";
pub const IN_DEPTH_STENCIL_TEXTURE: &'static str = "depth_stencil";
}
impl Node for PathfinderNode {
fn input(&self) -> &[ResourceSlotInfo] {
static INPUT: &[ResourceSlotInfo] = &[
ResourceSlotInfo {
name: Cow::Borrowed(PathfinderNode::IN_COLOR_TEXTURE),
resource_type: ResourceInfo::Texture,
},
ResourceSlotInfo {
name: Cow::Borrowed(PathfinderNode::IN_DEPTH_STENCIL_TEXTURE),
resource_type: ResourceInfo::Texture,
},
];
INPUT
}
fn update(
&mut self,
_world: &World,
resources: &Resources,
render_context: &mut dyn RenderContext,
_input: &ResourceSlots,
input: &ResourceSlots,
_output: &mut ResourceSlots,
) {
let mut shaders = resources.get_mut::<AssetStorage<Shader>>().unwrap();
let device = BevyPathfinderDevice::new(render_context, &mut shaders);
let color_texture = input.get(PathfinderNode::IN_COLOR_TEXTURE).unwrap();
let depth_stencil_texture = input.get(PathfinderNode::IN_DEPTH_STENCIL_TEXTURE).unwrap();
let device = BevyPathfinderDevice::new(
render_context,
&mut shaders,
color_texture,
depth_stencil_texture,
);
let window_size = Vector2I::new(640 as i32, 480 as i32);
let mut renderer = Renderer::new(
device,

View file

@ -1,24 +0,0 @@
use pathfinder_resources::ResourceLoader;
pub struct BevyResourceLoader {
}
impl BevyResourceLoader {
pub fn new() -> Self {
BevyResourceLoader {}
}
}
const AREA_LUT: &'static [u8] = include_bytes!("resources/area-lut.png");
const GAMMA_LUT: &'static [u8] = include_bytes!("resources/gamma-lut.png");
impl ResourceLoader for BevyResourceLoader {
fn slurp(&self, path: &str) -> Result<Vec<u8>, std::io::Error> {
match path {
"textures/area-lut.png" => Ok(AREA_LUT.to_vec()),
"textures/gamma-lut.png" => Ok(GAMMA_LUT.to_vec()),
_ => panic!("failed to find resource {}", path),
}
}
}

View file

@ -17,15 +17,17 @@ use legion::prelude::Resources;
pub struct BaseRenderGraphConfig {
pub add_2d_camera: bool,
pub add_3d_camera: bool,
pub add_main_depth_texture: bool,
pub add_main_pass: bool,
pub connect_main_pass_to_swapchain: bool,
pub connect_main_pass_to_main_depth_texture: bool,
}
pub mod node {
pub const PRIMARY_SWAP_CHAIN: &str = "swapchain";
pub const CAMERA: &str = "camera";
pub const CAMERA2D: &str = "camera2d";
pub const MAIN_PASS_DEPTH_TEXTURE: &str = "main_pass_depth_texture";
pub const MAIN_DEPTH_TEXTURE: &str = "main_pass_depth_texture";
pub const MAIN_PASS: &str = "main_pass";
}
@ -35,7 +37,9 @@ impl Default for BaseRenderGraphConfig {
add_2d_camera: true,
add_3d_camera: true,
add_main_pass: true,
add_main_depth_texture: true,
connect_main_pass_to_swapchain: true,
connect_main_pass_to_main_depth_texture: true,
}
}
}
@ -64,9 +68,9 @@ impl BaseRenderGraphBuilder for RenderGraph {
self.add_system_node_named(node::CAMERA2D, Camera2dNode::default(), resources);
}
if config.add_main_pass {
if config.add_main_depth_texture {
self.add_node_named(
node::MAIN_PASS_DEPTH_TEXTURE,
node::MAIN_DEPTH_TEXTURE,
WindowTextureNode::new(
WindowReference::Primary,
TextureDescriptor {
@ -85,7 +89,9 @@ impl BaseRenderGraphBuilder for RenderGraph {
resources.get_event_reader::<WindowResized>(),
),
);
}
if config.add_main_pass {
self.add_node_named(
node::MAIN_PASS,
PassNode::new(PassDescriptor {
@ -109,14 +115,6 @@ impl BaseRenderGraphBuilder for RenderGraph {
}),
);
self.add_slot_edge(
node::MAIN_PASS_DEPTH_TEXTURE,
WindowTextureNode::OUT_TEXTURE,
node::MAIN_PASS,
"depth",
)
.unwrap();
if config.add_3d_camera {
self.add_node_edge(node::CAMERA, node::MAIN_PASS).unwrap();
}
@ -145,6 +143,16 @@ impl BaseRenderGraphBuilder for RenderGraph {
.unwrap();
}
if config.connect_main_pass_to_main_depth_texture {
self.add_slot_edge(
node::MAIN_DEPTH_TEXTURE,
WindowTextureNode::OUT_TEXTURE,
node::MAIN_PASS,
"depth",
)
.unwrap();
}
self
}
}

View file

@ -11,6 +11,8 @@ pub trait RenderPass {
fn set_index_buffer(&mut self, resource: RenderResource, offset: u64);
fn set_vertex_buffer(&mut self, start_slot: u32, resource: RenderResource, offset: u64);
fn set_pipeline(&mut self, pipeline_handle: Handle<PipelineDescriptor>);
fn set_viewport(&mut self, x: f32, y: f32, w: f32, h: f32, min_depth: f32, max_depth: f32);
fn set_stencil_reference(&mut self, reference: u32);
fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>);
// TODO: try to somehow take into account the "set" pipeline instead of passing it in here
fn set_render_resources(

View file

@ -28,6 +28,14 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
.set_vertex_buffer(start_slot, &buffer, offset, 0);
}
fn set_viewport(&mut self, x: f32, y: f32, w: f32, h: f32, min_depth: f32, max_depth: f32) {
self.render_pass.set_viewport(x, y, w, h, min_depth, max_depth);
}
fn set_stencil_reference(&mut self, reference: u32) {
self.render_pass.set_stencil_reference(reference);
}
fn set_index_buffer(&mut self, resource: RenderResource, offset: u64) {
let buffer = self.render_resources.buffers.get(&resource).unwrap();
self.render_pass.set_index_buffer(&buffer, offset, 0);

29
examples/2d/pathfinder.rs Normal file
View file

@ -0,0 +1,29 @@
use bevy::prelude::*;
use bevy::render::base_render_graph::BaseRenderGraphConfig;
use bevy_diagnostic::{PrintDiagnosticsPlugin, FrameTimeDiagnosticsPlugin};
use bevy_wgpu::diagnostic::WgpuResourceDiagnosticsPlugin;
fn main() {
App::build()
.add_plugin(bevy::core::CorePlugin::default())
.add_plugin(bevy::diagnostic::DiagnosticsPlugin::default())
.add_plugin(bevy::input::InputPlugin::default())
.add_plugin(bevy::window::WindowPlugin::default())
.add_plugin(bevy::render::RenderPlugin {
base_render_graph_config: Some(BaseRenderGraphConfig {
add_2d_camera: true,
add_3d_camera: false,
add_main_pass: false,
add_main_depth_texture:true,
connect_main_pass_to_swapchain: false,
connect_main_pass_to_main_depth_texture: false,
})
})
.add_plugin(bevy::pathfinder::PathfinderPlugin::default())
.add_plugin(bevy::winit::WinitPlugin::default())
.add_plugin(bevy::wgpu::WgpuPlugin::default())
.add_plugin(FrameTimeDiagnosticsPlugin::default())
.add_plugin(WgpuResourceDiagnosticsPlugin::default())
.add_plugin(PrintDiagnosticsPlugin::default())
.run();
}

View file

@ -21,8 +21,8 @@ impl AddDefaultPlugins for AppBuilder {
#[cfg(feature = "render")]
self.add_plugin(bevy_render::RenderPlugin::default());
#[cfg(feature = "pathfinder")]
self.add_plugin(bevy_pathfinder::PathfinderPlugin::default());
// #[cfg(feature = "pathfinder")]
// self.add_plugin(bevy_pathfinder::PathfinderPlugin::default());
#[cfg(feature = "pbr")]
self.add_plugin(bevy_pbr::PbrPlugin::default());

View file

@ -73,3 +73,7 @@ pub use bevy_transform as transform;
pub use bevy_ui as ui;
#[cfg(feature = "window")]
pub use bevy_window as window;
#[cfg(feature = "winit")]
pub use bevy_winit as winit;
#[cfg(feature = "wgpu")]
pub use bevy_wgpu as wgpu;