mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
pathfinder: more backend work. it now renders the clear color without crashing
This commit is contained in:
parent
a5f47fd7da
commit
35e1d8b498
11 changed files with 460 additions and 97 deletions
|
@ -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"
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
29
examples/2d/pathfinder.rs
Normal 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();
|
||||
}
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue