2020-03-10 07:53:07 +00:00
|
|
|
use super::{wgpu_type_converter::OwnedWgpuVertexBufferDescriptor, WgpuRenderPass, WgpuResources};
|
2020-01-20 08:57:54 +00:00
|
|
|
use crate::{
|
2020-03-01 18:22:58 +00:00
|
|
|
asset::{AssetStorage, Handle},
|
2020-03-26 08:57:36 +00:00
|
|
|
core::Window,
|
2020-01-20 08:57:54 +00:00
|
|
|
legion::prelude::*,
|
2020-02-16 00:28:17 +00:00
|
|
|
render::{
|
2020-03-10 06:08:09 +00:00
|
|
|
pass::{
|
|
|
|
PassDescriptor, RenderPassColorAttachmentDescriptor,
|
|
|
|
RenderPassDepthStencilAttachmentDescriptor,
|
2020-02-16 00:28:17 +00:00
|
|
|
},
|
2020-03-27 06:40:25 +00:00
|
|
|
pipeline::{update_shader_assignments, PipelineCompiler, PipelineDescriptor},
|
2020-03-10 06:08:09 +00:00
|
|
|
render_graph::RenderGraph,
|
2020-03-10 07:53:07 +00:00
|
|
|
render_resource::{
|
2020-03-22 02:57:59 +00:00
|
|
|
resource_name, BufferInfo, RenderResource, RenderResourceAssignments, RenderResources,
|
|
|
|
ResourceInfo,
|
2020-03-10 07:53:07 +00:00
|
|
|
},
|
2020-03-10 06:08:09 +00:00
|
|
|
renderer::Renderer,
|
2020-03-22 02:57:59 +00:00
|
|
|
shader::Shader,
|
2020-03-10 06:08:09 +00:00
|
|
|
texture::{SamplerDescriptor, TextureDescriptor},
|
2020-03-26 08:57:36 +00:00
|
|
|
},
|
2020-01-20 08:57:54 +00:00
|
|
|
};
|
2020-03-25 02:17:41 +00:00
|
|
|
use std::{cell::RefCell, collections::HashMap, ops::Deref, rc::Rc};
|
2020-03-03 01:53:39 +00:00
|
|
|
|
|
|
|
pub struct WgpuRenderer {
|
2020-03-25 02:17:41 +00:00
|
|
|
pub device: Rc<RefCell<wgpu::Device>>,
|
2020-03-03 01:53:39 +00:00
|
|
|
pub queue: wgpu::Queue,
|
|
|
|
pub surface: Option<wgpu::Surface>,
|
|
|
|
pub encoder: Option<wgpu::CommandEncoder>,
|
2020-03-05 08:44:53 +00:00
|
|
|
pub render_pipelines: HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>,
|
2020-03-03 01:53:39 +00:00
|
|
|
pub wgpu_resources: WgpuResources,
|
2020-03-23 01:22:35 +00:00
|
|
|
pub intialized: bool,
|
2020-03-03 01:53:39 +00:00
|
|
|
}
|
|
|
|
|
2020-01-20 08:57:54 +00:00
|
|
|
impl WgpuRenderer {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
let adapter = wgpu::Adapter::request(
|
|
|
|
&wgpu::RequestAdapterOptions {
|
|
|
|
power_preference: wgpu::PowerPreference::Default,
|
|
|
|
},
|
|
|
|
wgpu::BackendBit::PRIMARY,
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let (device, queue) = adapter.request_device(&wgpu::DeviceDescriptor {
|
|
|
|
extensions: wgpu::Extensions {
|
|
|
|
anisotropic_filtering: false,
|
|
|
|
},
|
|
|
|
limits: wgpu::Limits::default(),
|
|
|
|
});
|
|
|
|
|
|
|
|
WgpuRenderer {
|
2020-03-25 02:17:41 +00:00
|
|
|
device: Rc::new(RefCell::new(device)),
|
2020-01-20 08:57:54 +00:00
|
|
|
queue,
|
|
|
|
surface: None,
|
2020-02-04 08:06:17 +00:00
|
|
|
encoder: None,
|
2020-03-23 01:22:35 +00:00
|
|
|
intialized: false,
|
2020-03-27 06:40:25 +00:00
|
|
|
wgpu_resources: WgpuResources::default(),
|
2020-03-05 08:44:53 +00:00
|
|
|
render_pipelines: HashMap::new(),
|
2020-01-20 08:57:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-23 01:22:35 +00:00
|
|
|
fn initialize(&mut self, world: &mut World, resources: &mut Resources) {
|
|
|
|
if self.intialized {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.create_surface(resources);
|
|
|
|
self.initialize_resource_providers(world, resources);
|
2020-03-28 00:43:03 +00:00
|
|
|
self.resize(world, resources);
|
2020-03-23 01:22:35 +00:00
|
|
|
|
|
|
|
self.intialized = true;
|
|
|
|
}
|
|
|
|
|
2020-01-20 08:57:54 +00:00
|
|
|
pub fn create_render_pipeline(
|
2020-03-21 02:32:59 +00:00
|
|
|
wgpu_resources: &mut WgpuResources,
|
2020-01-28 09:53:28 +00:00
|
|
|
pipeline_descriptor: &mut PipelineDescriptor,
|
2020-03-27 06:40:25 +00:00
|
|
|
shader_storage: &AssetStorage<Shader>,
|
2020-01-20 08:57:54 +00:00
|
|
|
device: &wgpu::Device,
|
|
|
|
) -> wgpu::RenderPipeline {
|
2020-03-27 06:40:25 +00:00
|
|
|
let layout = pipeline_descriptor.get_layout().unwrap();
|
|
|
|
for bind_group in layout.bind_groups.iter() {
|
2020-03-26 08:57:36 +00:00
|
|
|
if let None = wgpu_resources.bind_group_layouts.get(&bind_group.id) {
|
2020-01-23 08:31:56 +00:00
|
|
|
let bind_group_layout_binding = bind_group
|
|
|
|
.bindings
|
|
|
|
.iter()
|
2020-02-17 22:12:10 +00:00
|
|
|
.map(|binding| wgpu::BindGroupLayoutBinding {
|
|
|
|
binding: binding.index,
|
2020-01-23 08:31:56 +00:00
|
|
|
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
2020-01-24 07:39:56 +00:00
|
|
|
ty: (&binding.bind_type).into(),
|
2020-01-23 08:31:56 +00:00
|
|
|
})
|
|
|
|
.collect::<Vec<wgpu::BindGroupLayoutBinding>>();
|
2020-03-27 06:40:25 +00:00
|
|
|
let wgpu_bind_group_layout =
|
2020-01-26 00:33:26 +00:00
|
|
|
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
|
|
|
bindings: bind_group_layout_binding.as_slice(),
|
|
|
|
});
|
|
|
|
|
2020-03-21 02:32:59 +00:00
|
|
|
wgpu_resources
|
|
|
|
.bind_group_layouts
|
2020-03-27 06:40:25 +00:00
|
|
|
.insert(bind_group.id, wgpu_bind_group_layout);
|
2020-01-26 00:33:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-27 06:40:25 +00:00
|
|
|
// setup and collect bind group layouts
|
2020-02-17 22:12:10 +00:00
|
|
|
let bind_group_layouts = layout
|
2020-01-26 00:33:26 +00:00
|
|
|
.bind_groups
|
|
|
|
.iter()
|
|
|
|
.map(|bind_group| {
|
2020-03-21 02:32:59 +00:00
|
|
|
wgpu_resources
|
|
|
|
.bind_group_layouts
|
2020-03-26 08:57:36 +00:00
|
|
|
.get(&bind_group.id)
|
2020-03-21 02:32:59 +00:00
|
|
|
.unwrap()
|
2020-01-23 08:31:56 +00:00
|
|
|
})
|
2020-01-26 00:33:26 +00:00
|
|
|
.collect::<Vec<&wgpu::BindGroupLayout>>();
|
|
|
|
|
2020-01-20 08:57:54 +00:00
|
|
|
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
2020-01-27 05:44:01 +00:00
|
|
|
bind_group_layouts: bind_group_layouts.as_slice(),
|
2020-01-20 08:57:54 +00:00
|
|
|
});
|
2020-01-23 08:31:56 +00:00
|
|
|
|
2020-03-27 06:40:25 +00:00
|
|
|
let owned_vertex_buffer_descriptors = layout
|
|
|
|
.vertex_buffer_descriptors
|
|
|
|
.iter()
|
|
|
|
.map(|v| v.into())
|
|
|
|
.collect::<Vec<OwnedWgpuVertexBufferDescriptor>>();
|
2020-03-10 07:53:07 +00:00
|
|
|
|
2020-03-11 04:57:57 +00:00
|
|
|
let color_states = pipeline_descriptor
|
|
|
|
.color_states
|
|
|
|
.iter()
|
|
|
|
.map(|c| c.into())
|
|
|
|
.collect::<Vec<wgpu::ColorStateDescriptor>>();
|
|
|
|
|
2020-03-27 06:40:25 +00:00
|
|
|
if let None = wgpu_resources
|
|
|
|
.shader_modules
|
|
|
|
.get(&pipeline_descriptor.shader_stages.vertex)
|
|
|
|
{
|
|
|
|
wgpu_resources.create_shader_module(
|
|
|
|
device,
|
|
|
|
pipeline_descriptor.shader_stages.vertex,
|
|
|
|
shader_storage,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(fragment_handle) = pipeline_descriptor.shader_stages.fragment {
|
|
|
|
if let None = wgpu_resources.shader_modules.get(&fragment_handle) {
|
|
|
|
wgpu_resources.create_shader_module(device, fragment_handle, shader_storage);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let vertex_shader_module = wgpu_resources
|
|
|
|
.shader_modules
|
|
|
|
.get(&pipeline_descriptor.shader_stages.vertex)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let fragment_shader_module = match pipeline_descriptor.shader_stages.fragment {
|
|
|
|
Some(fragment_handle) => {
|
|
|
|
Some(wgpu_resources.shader_modules.get(&fragment_handle).unwrap())
|
|
|
|
}
|
|
|
|
None => None,
|
|
|
|
};
|
|
|
|
|
2020-01-28 09:53:28 +00:00
|
|
|
let mut render_pipeline_descriptor = wgpu::RenderPipelineDescriptor {
|
2020-01-20 08:57:54 +00:00
|
|
|
layout: &pipeline_layout,
|
|
|
|
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
|
|
|
module: &vertex_shader_module,
|
2020-02-17 22:12:10 +00:00
|
|
|
entry_point: "main",
|
2020-01-20 08:57:54 +00:00
|
|
|
},
|
2020-03-27 06:40:25 +00:00
|
|
|
fragment_stage: match pipeline_descriptor.shader_stages.fragment {
|
2020-02-18 02:36:31 +00:00
|
|
|
Some(_) => Some(wgpu::ProgrammableStageDescriptor {
|
2020-02-17 22:12:10 +00:00
|
|
|
entry_point: "main",
|
2020-01-20 08:57:54 +00:00
|
|
|
module: fragment_shader_module.as_ref().unwrap(),
|
|
|
|
}),
|
|
|
|
None => None,
|
|
|
|
},
|
2020-03-11 04:57:57 +00:00
|
|
|
rasterization_state: pipeline_descriptor
|
|
|
|
.rasterization_state
|
|
|
|
.as_ref()
|
|
|
|
.map(|r| r.into()),
|
|
|
|
primitive_topology: pipeline_descriptor.primitive_topology.into(),
|
|
|
|
color_states: &color_states,
|
|
|
|
depth_stencil_state: pipeline_descriptor
|
|
|
|
.depth_stencil_state
|
|
|
|
.as_ref()
|
|
|
|
.map(|d| d.into()),
|
|
|
|
index_format: pipeline_descriptor.index_format.into(),
|
2020-03-10 07:53:07 +00:00
|
|
|
vertex_buffers: &owned_vertex_buffer_descriptors
|
2020-01-20 08:57:54 +00:00
|
|
|
.iter()
|
|
|
|
.map(|v| v.into())
|
|
|
|
.collect::<Vec<wgpu::VertexBufferDescriptor>>(),
|
|
|
|
sample_count: pipeline_descriptor.sample_count,
|
|
|
|
sample_mask: pipeline_descriptor.sample_mask,
|
|
|
|
alpha_to_coverage_enabled: pipeline_descriptor.alpha_to_coverage_enabled,
|
|
|
|
};
|
|
|
|
|
2020-01-28 09:53:28 +00:00
|
|
|
device.create_render_pipeline(&mut render_pipeline_descriptor)
|
2020-01-20 08:57:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn create_render_pass<'a>(
|
2020-03-05 08:44:53 +00:00
|
|
|
wgpu_resources: &'a WgpuResources,
|
2020-01-20 08:57:54 +00:00
|
|
|
pass_descriptor: &PassDescriptor,
|
2020-03-27 06:40:25 +00:00
|
|
|
global_render_resource_assignments: &RenderResourceAssignments,
|
2020-01-20 08:57:54 +00:00
|
|
|
encoder: &'a mut wgpu::CommandEncoder,
|
|
|
|
frame: &'a wgpu::SwapChainOutput,
|
|
|
|
) -> wgpu::RenderPass<'a> {
|
|
|
|
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
|
|
|
color_attachments: &pass_descriptor
|
|
|
|
.color_attachments
|
|
|
|
.iter()
|
2020-03-27 06:40:25 +00:00
|
|
|
.map(|c| {
|
|
|
|
Self::create_wgpu_color_attachment_descriptor(
|
|
|
|
wgpu_resources,
|
|
|
|
global_render_resource_assignments,
|
|
|
|
c,
|
|
|
|
frame,
|
|
|
|
)
|
|
|
|
})
|
2020-01-20 08:57:54 +00:00
|
|
|
.collect::<Vec<wgpu::RenderPassColorAttachmentDescriptor>>(),
|
2020-03-09 03:06:59 +00:00
|
|
|
depth_stencil_attachment: pass_descriptor.depth_stencil_attachment.as_ref().map(|d| {
|
2020-03-27 06:40:25 +00:00
|
|
|
Self::create_wgpu_depth_stencil_attachment_descriptor(
|
|
|
|
wgpu_resources,
|
|
|
|
global_render_resource_assignments,
|
|
|
|
d,
|
|
|
|
frame,
|
|
|
|
)
|
2020-03-09 03:06:59 +00:00
|
|
|
}),
|
2020-01-20 08:57:54 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn create_wgpu_color_attachment_descriptor<'a>(
|
2020-03-03 06:36:11 +00:00
|
|
|
wgpu_resources: &'a WgpuResources,
|
2020-03-27 06:40:25 +00:00
|
|
|
global_render_resource_assignments: &RenderResourceAssignments,
|
2020-01-20 08:57:54 +00:00
|
|
|
color_attachment_descriptor: &RenderPassColorAttachmentDescriptor,
|
|
|
|
frame: &'a wgpu::SwapChainOutput,
|
|
|
|
) -> wgpu::RenderPassColorAttachmentDescriptor<'a> {
|
|
|
|
let attachment = match color_attachment_descriptor.attachment.as_str() {
|
2020-01-23 08:31:56 +00:00
|
|
|
resource_name::texture::SWAP_CHAIN => &frame.view,
|
2020-02-24 05:13:03 +00:00
|
|
|
_ => {
|
2020-03-27 06:40:25 +00:00
|
|
|
match global_render_resource_assignments
|
|
|
|
.get(&color_attachment_descriptor.attachment)
|
2020-02-24 05:13:03 +00:00
|
|
|
{
|
2020-03-03 01:53:39 +00:00
|
|
|
Some(resource) => wgpu_resources.textures.get(&resource).unwrap(),
|
2020-02-24 05:13:03 +00:00
|
|
|
None => panic!(
|
|
|
|
"Color attachment {} does not exist",
|
|
|
|
&color_attachment_descriptor.attachment
|
|
|
|
),
|
|
|
|
}
|
|
|
|
}
|
2020-01-20 08:57:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let resolve_target = match color_attachment_descriptor.resolve_target {
|
|
|
|
Some(ref target) => match target.as_str() {
|
2020-01-23 08:31:56 +00:00
|
|
|
resource_name::texture::SWAP_CHAIN => Some(&frame.view),
|
2020-03-27 06:40:25 +00:00
|
|
|
_ => match global_render_resource_assignments.get(target.as_str()) {
|
2020-03-03 01:53:39 +00:00
|
|
|
Some(resource) => Some(wgpu_resources.textures.get(&resource).unwrap()),
|
2020-02-24 05:13:03 +00:00
|
|
|
None => panic!(
|
|
|
|
"Color attachment {} does not exist",
|
|
|
|
&color_attachment_descriptor.attachment
|
|
|
|
),
|
|
|
|
},
|
2020-01-20 08:57:54 +00:00
|
|
|
},
|
|
|
|
None => None,
|
|
|
|
};
|
|
|
|
|
|
|
|
wgpu::RenderPassColorAttachmentDescriptor {
|
2020-03-10 07:53:07 +00:00
|
|
|
store_op: color_attachment_descriptor.store_op.into(),
|
|
|
|
load_op: color_attachment_descriptor.load_op.into(),
|
|
|
|
clear_color: color_attachment_descriptor.clear_color.into(),
|
2020-01-20 08:57:54 +00:00
|
|
|
attachment,
|
|
|
|
resolve_target,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn create_wgpu_depth_stencil_attachment_descriptor<'a>(
|
2020-03-03 01:53:39 +00:00
|
|
|
wgpu_resources: &'a WgpuResources,
|
2020-03-27 06:40:25 +00:00
|
|
|
global_render_resource_assignments: &RenderResourceAssignments,
|
2020-01-20 08:57:54 +00:00
|
|
|
depth_stencil_attachment_descriptor: &RenderPassDepthStencilAttachmentDescriptor,
|
|
|
|
frame: &'a wgpu::SwapChainOutput,
|
2020-03-05 08:44:53 +00:00
|
|
|
) -> wgpu::RenderPassDepthStencilAttachmentDescriptor<'a> {
|
2020-01-20 08:57:54 +00:00
|
|
|
let attachment = match depth_stencil_attachment_descriptor.attachment.as_str() {
|
2020-01-23 08:31:56 +00:00
|
|
|
resource_name::texture::SWAP_CHAIN => &frame.view,
|
2020-02-24 05:13:03 +00:00
|
|
|
_ => {
|
2020-03-27 06:40:25 +00:00
|
|
|
match global_render_resource_assignments
|
|
|
|
.get(&depth_stencil_attachment_descriptor.attachment)
|
2020-02-24 05:13:03 +00:00
|
|
|
{
|
2020-03-03 01:53:39 +00:00
|
|
|
Some(ref resource) => wgpu_resources.textures.get(&resource).unwrap(),
|
2020-02-24 05:13:03 +00:00
|
|
|
None => panic!(
|
|
|
|
"Depth stencil attachment {} does not exist",
|
|
|
|
&depth_stencil_attachment_descriptor.attachment
|
|
|
|
),
|
|
|
|
}
|
|
|
|
}
|
2020-01-20 08:57:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
wgpu::RenderPassDepthStencilAttachmentDescriptor {
|
|
|
|
attachment,
|
|
|
|
clear_depth: depth_stencil_attachment_descriptor.clear_depth,
|
|
|
|
clear_stencil: depth_stencil_attachment_descriptor.clear_stencil,
|
2020-03-10 07:53:07 +00:00
|
|
|
depth_load_op: depth_stencil_attachment_descriptor.depth_load_op.into(),
|
|
|
|
depth_store_op: depth_stencil_attachment_descriptor.depth_store_op.into(),
|
|
|
|
stencil_load_op: depth_stencil_attachment_descriptor.stencil_load_op.into(),
|
|
|
|
stencil_store_op: depth_stencil_attachment_descriptor.stencil_store_op.into(),
|
2020-01-20 08:57:54 +00:00
|
|
|
}
|
|
|
|
}
|
2020-01-26 00:33:26 +00:00
|
|
|
|
2020-03-22 02:57:59 +00:00
|
|
|
pub fn initialize_resource_providers(&mut self, world: &mut World, resources: &mut Resources) {
|
|
|
|
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
2020-02-18 00:33:46 +00:00
|
|
|
self.encoder = Some(
|
|
|
|
self.device
|
2020-03-25 02:17:41 +00:00
|
|
|
.borrow()
|
2020-02-18 00:33:46 +00:00
|
|
|
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }),
|
|
|
|
);
|
|
|
|
for resource_provider in render_graph.resource_providers.iter_mut() {
|
2020-03-09 06:19:07 +00:00
|
|
|
resource_provider.initialize(self, world, resources);
|
2020-02-18 00:33:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// consume current encoder
|
|
|
|
let command_buffer = self.encoder.take().unwrap().finish();
|
|
|
|
self.queue.submit(&[command_buffer]);
|
|
|
|
}
|
2020-01-27 09:13:38 +00:00
|
|
|
|
2020-03-22 02:57:59 +00:00
|
|
|
pub fn update_resource_providers(&mut self, world: &mut World, resources: &mut Resources) {
|
|
|
|
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
|
|
|
for resource_provider in render_graph.resource_providers.iter_mut() {
|
|
|
|
resource_provider.update(self, world, resources);
|
|
|
|
}
|
2020-01-20 08:57:54 +00:00
|
|
|
|
2020-03-22 02:57:59 +00:00
|
|
|
for resource_provider in render_graph.resource_providers.iter_mut() {
|
|
|
|
resource_provider.finish_update(self, world, resources);
|
|
|
|
}
|
|
|
|
}
|
2020-02-18 00:33:46 +00:00
|
|
|
|
2020-03-22 02:57:59 +00:00
|
|
|
pub fn create_queued_textures(&mut self, resources: &mut Resources) {
|
|
|
|
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
2020-03-27 06:40:25 +00:00
|
|
|
let mut render_resource_assignments =
|
|
|
|
resources.get_mut::<RenderResourceAssignments>().unwrap();
|
2020-03-22 02:57:59 +00:00
|
|
|
for (name, texture_descriptor) in render_graph.queued_textures.drain(..) {
|
|
|
|
let resource = self.create_texture(&texture_descriptor, None);
|
2020-03-27 06:40:25 +00:00
|
|
|
render_resource_assignments.set(&name, resource);
|
2020-03-22 02:57:59 +00:00
|
|
|
}
|
|
|
|
}
|
2020-02-05 06:07:02 +00:00
|
|
|
|
2020-03-22 02:57:59 +00:00
|
|
|
pub fn create_surface(&mut self, resources: &Resources) {
|
|
|
|
let window = resources.get::<winit::window::Window>().unwrap();
|
|
|
|
let surface = wgpu::Surface::create(window.deref());
|
|
|
|
self.surface = Some(surface);
|
2020-01-20 08:57:54 +00:00
|
|
|
}
|
2020-03-22 02:57:59 +00:00
|
|
|
}
|
2020-01-20 08:57:54 +00:00
|
|
|
|
2020-03-22 02:57:59 +00:00
|
|
|
impl Renderer for WgpuRenderer {
|
2020-03-28 00:43:03 +00:00
|
|
|
fn resize(&mut self, world: &mut World, resources: &mut Resources) {
|
2020-02-05 06:07:02 +00:00
|
|
|
self.encoder = Some(
|
|
|
|
self.device
|
2020-03-25 02:17:41 +00:00
|
|
|
.borrow()
|
2020-02-05 06:07:02 +00:00
|
|
|
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }),
|
|
|
|
);
|
2020-03-28 00:43:03 +00:00
|
|
|
let swap_chain_descriptor: wgpu::SwapChainDescriptor = {
|
|
|
|
let window: &Window = &resources.get::<Window>().unwrap();
|
|
|
|
window.into()
|
|
|
|
};
|
|
|
|
|
2020-01-20 08:57:54 +00:00
|
|
|
let swap_chain = self
|
|
|
|
.device
|
2020-03-25 02:17:41 +00:00
|
|
|
.borrow()
|
2020-03-28 00:43:03 +00:00
|
|
|
.create_swap_chain(self.surface.as_ref().unwrap(), &swap_chain_descriptor);
|
2020-01-20 08:57:54 +00:00
|
|
|
|
2020-01-23 08:31:56 +00:00
|
|
|
// WgpuRenderer can't own swap_chain without creating lifetime ergonomics issues, so lets just store it in World.
|
2020-03-09 06:19:07 +00:00
|
|
|
resources.insert(swap_chain);
|
2020-03-22 02:57:59 +00:00
|
|
|
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
2020-01-27 05:44:01 +00:00
|
|
|
for resource_provider in render_graph.resource_providers.iter_mut() {
|
2020-03-28 00:43:03 +00:00
|
|
|
resource_provider.resize(self, world, resources, swap_chain_descriptor.width, swap_chain_descriptor.height);
|
2020-01-27 05:44:01 +00:00
|
|
|
}
|
2020-02-06 01:50:56 +00:00
|
|
|
|
2020-02-05 06:07:02 +00:00
|
|
|
// consume current encoder
|
|
|
|
let command_buffer = self.encoder.take().unwrap().finish();
|
|
|
|
self.queue.submit(&[command_buffer]);
|
2020-01-20 08:57:54 +00:00
|
|
|
}
|
|
|
|
|
2020-03-22 02:57:59 +00:00
|
|
|
fn update(&mut self, world: &mut World, resources: &mut Resources) {
|
2020-03-23 01:22:35 +00:00
|
|
|
self.initialize(world, resources);
|
2020-02-04 08:06:17 +00:00
|
|
|
// TODO: this self.encoder handoff is a bit gross, but its here to give resource providers access to buffer copies without
|
|
|
|
// exposing the wgpu renderer internals to ResourceProvider traits. if this can be made cleaner that would be pretty cool.
|
2020-02-05 06:07:02 +00:00
|
|
|
self.encoder = Some(
|
|
|
|
self.device
|
2020-03-25 02:17:41 +00:00
|
|
|
.borrow()
|
2020-02-05 06:07:02 +00:00
|
|
|
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }),
|
|
|
|
);
|
2020-02-04 08:06:17 +00:00
|
|
|
|
2020-03-22 02:57:59 +00:00
|
|
|
self.update_resource_providers(world, resources);
|
2020-03-28 05:41:45 +00:00
|
|
|
update_shader_assignments(world, resources, self);
|
2020-03-22 02:57:59 +00:00
|
|
|
self.create_queued_textures(resources);
|
2020-02-06 01:50:56 +00:00
|
|
|
|
2020-02-04 08:06:17 +00:00
|
|
|
let mut encoder = self.encoder.take().unwrap();
|
|
|
|
|
2020-03-09 06:19:07 +00:00
|
|
|
let mut swap_chain = resources.get_mut::<wgpu::SwapChain>().unwrap();
|
2020-01-20 08:57:54 +00:00
|
|
|
let frame = swap_chain
|
|
|
|
.get_next_texture()
|
|
|
|
.expect("Timeout when acquiring next swap chain texture");
|
|
|
|
|
2020-02-04 05:00:00 +00:00
|
|
|
// self.setup_dynamic_entity_shader_uniforms(world, render_graph, &mut encoder);
|
2020-01-20 08:57:54 +00:00
|
|
|
|
2020-01-27 05:44:01 +00:00
|
|
|
// setup, pipelines, bind groups, and resources
|
2020-03-09 06:19:07 +00:00
|
|
|
let mut pipeline_storage = resources
|
2020-02-16 00:28:17 +00:00
|
|
|
.get_mut::<AssetStorage<PipelineDescriptor>>()
|
|
|
|
.unwrap();
|
2020-03-09 06:19:07 +00:00
|
|
|
let shader_storage = resources.get::<AssetStorage<Shader>>().unwrap();
|
2020-03-22 02:57:59 +00:00
|
|
|
let render_graph = resources.get::<RenderGraph>().unwrap();
|
|
|
|
let mut render_graph_mut = resources.get_mut::<RenderGraph>().unwrap();
|
2020-03-27 06:40:25 +00:00
|
|
|
let global_render_resource_assignments =
|
|
|
|
resources.get::<RenderResourceAssignments>().unwrap();
|
|
|
|
let pipeline_compiler = resources.get::<PipelineCompiler>().unwrap();
|
|
|
|
|
2020-02-16 00:28:17 +00:00
|
|
|
for pipeline_descriptor_handle in render_graph.pipeline_descriptors.iter() {
|
2020-03-27 06:40:25 +00:00
|
|
|
if let Some(compiled_pipelines_iter) =
|
|
|
|
pipeline_compiler.iter_compiled_pipelines(*pipeline_descriptor_handle)
|
2020-02-16 00:28:17 +00:00
|
|
|
{
|
2020-03-27 06:40:25 +00:00
|
|
|
for compiled_pipeline_handle in compiled_pipelines_iter {
|
|
|
|
// create pipelines
|
|
|
|
// TODO: merge this into "setup draw targets" loop
|
|
|
|
if !self.render_pipelines.contains_key(compiled_pipeline_handle) {
|
|
|
|
let compiled_pipeline_descriptor =
|
|
|
|
pipeline_storage.get_mut(compiled_pipeline_handle).unwrap();
|
|
|
|
|
|
|
|
let render_pipeline = WgpuRenderer::create_render_pipeline(
|
|
|
|
&mut self.wgpu_resources,
|
|
|
|
compiled_pipeline_descriptor,
|
|
|
|
&shader_storage,
|
|
|
|
&self.device.borrow(),
|
|
|
|
);
|
|
|
|
self.render_pipelines
|
|
|
|
.insert(*compiled_pipeline_handle, render_pipeline);
|
|
|
|
}
|
|
|
|
}
|
2020-01-27 05:44:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-09 03:06:59 +00:00
|
|
|
// setup draw targets
|
|
|
|
for (pass_name, _pass_descriptor) in render_graph.pass_descriptors.iter() {
|
|
|
|
if let Some(pass_pipelines) = render_graph.pass_pipelines.get(pass_name) {
|
|
|
|
for pass_pipeline in pass_pipelines.iter() {
|
2020-03-27 06:40:25 +00:00
|
|
|
if let Some(compiled_pipelines_iter) =
|
|
|
|
pipeline_compiler.iter_compiled_pipelines(*pass_pipeline)
|
|
|
|
{
|
|
|
|
for compiled_pipeline_handle in compiled_pipelines_iter {
|
|
|
|
let pipeline_descriptor =
|
|
|
|
pipeline_storage.get(compiled_pipeline_handle).unwrap();
|
|
|
|
for draw_target_name in pipeline_descriptor.draw_targets.iter() {
|
|
|
|
let draw_target = render_graph_mut
|
|
|
|
.draw_targets
|
|
|
|
.get_mut(draw_target_name)
|
|
|
|
.unwrap();
|
|
|
|
draw_target.setup(
|
|
|
|
world,
|
|
|
|
resources,
|
|
|
|
self,
|
|
|
|
*compiled_pipeline_handle,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2020-03-09 03:06:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// begin render passes
|
2020-01-20 08:57:54 +00:00
|
|
|
for (pass_name, pass_descriptor) in render_graph.pass_descriptors.iter() {
|
2020-03-09 03:06:59 +00:00
|
|
|
let mut render_pass = Self::create_render_pass(
|
|
|
|
&self.wgpu_resources,
|
|
|
|
pass_descriptor,
|
2020-03-27 06:40:25 +00:00
|
|
|
&global_render_resource_assignments,
|
2020-03-09 03:06:59 +00:00
|
|
|
&mut encoder,
|
|
|
|
&frame,
|
|
|
|
);
|
2020-01-20 08:57:54 +00:00
|
|
|
if let Some(pass_pipelines) = render_graph.pass_pipelines.get(pass_name) {
|
|
|
|
for pass_pipeline in pass_pipelines.iter() {
|
2020-03-27 06:40:25 +00:00
|
|
|
if let Some(compiled_pipelines_iter) =
|
|
|
|
pipeline_compiler.iter_compiled_pipelines(*pass_pipeline)
|
|
|
|
{
|
|
|
|
for compiled_pipeline_handle in compiled_pipelines_iter {
|
|
|
|
let pipeline_descriptor =
|
|
|
|
pipeline_storage.get(compiled_pipeline_handle).unwrap();
|
|
|
|
let render_pipeline =
|
|
|
|
self.render_pipelines.get(compiled_pipeline_handle).unwrap();
|
|
|
|
render_pass.set_pipeline(render_pipeline);
|
|
|
|
|
|
|
|
let mut wgpu_render_pass = WgpuRenderPass {
|
|
|
|
render_pass: &mut render_pass,
|
|
|
|
pipeline_descriptor,
|
|
|
|
wgpu_resources: &self.wgpu_resources,
|
|
|
|
renderer: &self,
|
|
|
|
};
|
|
|
|
|
|
|
|
for draw_target_name in pipeline_descriptor.draw_targets.iter() {
|
|
|
|
let draw_target =
|
|
|
|
render_graph.draw_targets.get(draw_target_name).unwrap();
|
|
|
|
draw_target.draw(
|
|
|
|
world,
|
|
|
|
resources,
|
|
|
|
&mut wgpu_render_pass,
|
|
|
|
*compiled_pipeline_handle,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2020-01-20 08:57:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let command_buffer = encoder.finish();
|
|
|
|
self.queue.submit(&[command_buffer]);
|
|
|
|
}
|
2020-01-24 07:39:56 +00:00
|
|
|
|
2020-03-21 02:32:59 +00:00
|
|
|
fn create_buffer_with_data(&mut self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource {
|
2020-03-09 03:06:59 +00:00
|
|
|
self.wgpu_resources
|
2020-03-25 02:17:41 +00:00
|
|
|
.create_buffer_with_data(&self.device.borrow(), buffer_info, data)
|
2020-02-08 06:42:30 +00:00
|
|
|
}
|
|
|
|
|
2020-03-21 02:32:59 +00:00
|
|
|
fn create_buffer(&mut self, buffer_info: BufferInfo) -> RenderResource {
|
2020-03-25 02:17:41 +00:00
|
|
|
self.wgpu_resources
|
|
|
|
.create_buffer(&self.device.borrow(), buffer_info)
|
2020-02-08 06:42:30 +00:00
|
|
|
}
|
|
|
|
|
2020-02-24 05:13:03 +00:00
|
|
|
fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> {
|
2020-03-03 06:36:11 +00:00
|
|
|
self.wgpu_resources.resource_info.get(&resource)
|
2020-01-23 08:31:56 +00:00
|
|
|
}
|
|
|
|
|
2020-03-21 02:32:59 +00:00
|
|
|
fn get_resource_info_mut(&mut self, resource: RenderResource) -> Option<&mut ResourceInfo> {
|
|
|
|
self.wgpu_resources.resource_info.get_mut(&resource)
|
|
|
|
}
|
|
|
|
|
2020-02-24 05:13:03 +00:00
|
|
|
fn remove_buffer(&mut self, resource: RenderResource) {
|
2020-03-03 06:36:11 +00:00
|
|
|
self.wgpu_resources.remove_buffer(resource);
|
2020-01-24 07:39:56 +00:00
|
|
|
}
|
2020-02-04 05:00:00 +00:00
|
|
|
|
2020-02-05 06:07:02 +00:00
|
|
|
fn create_buffer_mapped(
|
|
|
|
&mut self,
|
2020-03-21 02:32:59 +00:00
|
|
|
buffer_info: BufferInfo,
|
2020-03-25 02:17:41 +00:00
|
|
|
setup_data: &mut dyn FnMut(&mut [u8], &mut dyn Renderer),
|
2020-02-24 05:13:03 +00:00
|
|
|
) -> RenderResource {
|
2020-03-25 02:17:41 +00:00
|
|
|
let buffer = WgpuResources::begin_create_buffer_mapped(&buffer_info, self, setup_data);
|
|
|
|
self.wgpu_resources.assign_buffer(buffer, buffer_info)
|
2020-02-04 05:00:00 +00:00
|
|
|
}
|
|
|
|
|
2020-02-05 06:07:02 +00:00
|
|
|
fn copy_buffer_to_buffer(
|
|
|
|
&mut self,
|
2020-02-24 05:13:03 +00:00
|
|
|
source_buffer: RenderResource,
|
2020-02-05 06:07:02 +00:00
|
|
|
source_offset: u64,
|
2020-02-24 05:13:03 +00:00
|
|
|
destination_buffer: RenderResource,
|
2020-02-05 06:07:02 +00:00
|
|
|
destination_offset: u64,
|
|
|
|
size: u64,
|
|
|
|
) {
|
2020-03-09 03:06:59 +00:00
|
|
|
self.wgpu_resources.copy_buffer_to_buffer(
|
|
|
|
self.encoder.as_mut().unwrap(),
|
|
|
|
source_buffer,
|
|
|
|
source_offset,
|
|
|
|
destination_buffer,
|
|
|
|
destination_offset,
|
|
|
|
size,
|
|
|
|
);
|
2020-02-04 05:00:00 +00:00
|
|
|
}
|
2020-03-03 06:36:11 +00:00
|
|
|
|
2020-02-24 07:41:48 +00:00
|
|
|
fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource {
|
2020-03-09 03:06:59 +00:00
|
|
|
self.wgpu_resources
|
2020-03-25 02:17:41 +00:00
|
|
|
.create_sampler(&self.device.borrow(), sampler_descriptor)
|
2020-02-24 05:13:03 +00:00
|
|
|
}
|
|
|
|
|
2020-02-24 07:41:48 +00:00
|
|
|
fn create_texture(
|
2020-02-24 05:13:03 +00:00
|
|
|
&mut self,
|
|
|
|
texture_descriptor: &TextureDescriptor,
|
|
|
|
bytes: Option<&[u8]>,
|
|
|
|
) -> RenderResource {
|
2020-03-09 03:06:59 +00:00
|
|
|
self.wgpu_resources.create_texture(
|
2020-03-25 02:17:41 +00:00
|
|
|
&self.device.borrow(),
|
2020-03-09 03:06:59 +00:00
|
|
|
self.encoder.as_mut().unwrap(),
|
|
|
|
texture_descriptor,
|
|
|
|
bytes,
|
|
|
|
)
|
2020-02-24 05:13:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn remove_texture(&mut self, resource: RenderResource) {
|
2020-03-03 06:36:11 +00:00
|
|
|
self.wgpu_resources.remove_texture(resource);
|
2020-02-06 01:50:56 +00:00
|
|
|
}
|
2020-02-24 07:41:48 +00:00
|
|
|
|
|
|
|
fn remove_sampler(&mut self, resource: RenderResource) {
|
2020-03-03 06:36:11 +00:00
|
|
|
self.wgpu_resources.remove_sampler(resource);
|
2020-02-24 07:41:48 +00:00
|
|
|
}
|
|
|
|
|
2020-03-01 18:22:58 +00:00
|
|
|
fn get_render_resources(&self) -> &RenderResources {
|
2020-03-03 06:36:11 +00:00
|
|
|
&self.wgpu_resources.render_resources
|
2020-02-24 07:41:48 +00:00
|
|
|
}
|
|
|
|
|
2020-03-01 18:22:58 +00:00
|
|
|
fn get_render_resources_mut(&mut self) -> &mut RenderResources {
|
2020-03-03 06:36:11 +00:00
|
|
|
&mut self.wgpu_resources.render_resources
|
2020-03-01 18:22:58 +00:00
|
|
|
}
|
|
|
|
|
2020-03-21 00:49:29 +00:00
|
|
|
fn setup_bind_groups(
|
2020-03-09 03:06:59 +00:00
|
|
|
&mut self,
|
2020-03-26 08:57:36 +00:00
|
|
|
render_resource_assignments: &mut RenderResourceAssignments,
|
2020-03-09 03:06:59 +00:00
|
|
|
pipeline_descriptor: &PipelineDescriptor,
|
|
|
|
) {
|
|
|
|
let pipeline_layout = pipeline_descriptor.get_layout().unwrap();
|
|
|
|
for bind_group in pipeline_layout.bind_groups.iter() {
|
2020-03-26 08:57:36 +00:00
|
|
|
if let Some(render_resource_set_id) =
|
|
|
|
render_resource_assignments.get_or_update_render_resource_set_id(bind_group)
|
|
|
|
{
|
2020-03-09 03:06:59 +00:00
|
|
|
if let None = self
|
|
|
|
.wgpu_resources
|
2020-03-26 08:57:36 +00:00
|
|
|
.get_bind_group(bind_group.id, render_resource_set_id)
|
2020-03-09 03:06:59 +00:00
|
|
|
{
|
2020-03-26 08:57:36 +00:00
|
|
|
self.wgpu_resources.create_bind_group(
|
2020-03-25 02:17:41 +00:00
|
|
|
&self.device.borrow(),
|
2020-03-21 02:32:59 +00:00
|
|
|
bind_group,
|
|
|
|
render_resource_assignments,
|
|
|
|
);
|
2020-03-09 03:06:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-02-24 07:41:48 +00:00
|
|
|
}
|
2020-03-11 04:57:57 +00:00
|
|
|
}
|