partially working rwlock implementation (blocked on lifetime issues)
This commit is contained in:
parent
537d75bbce
commit
b53f198b99
@ -239,7 +239,7 @@ impl PipelineAssignments {
|
||||
// TODO: make this a system
|
||||
pub fn update_shader_assignments(
|
||||
world: &mut World,
|
||||
resources: &mut Resources,
|
||||
resources: &Resources,
|
||||
render_context: &dyn RenderContext,
|
||||
) {
|
||||
// PERF: this seems like a lot of work for things that don't change that often.
|
||||
|
||||
@ -17,25 +17,13 @@ impl RenderResource {
|
||||
// the overlap could cause accidents.
|
||||
#[derive(Default)]
|
||||
pub struct AssetResources {
|
||||
pub texture_to_resource: HashMap<Handle<Texture>, RenderResource>,
|
||||
pub texture_to_sampler_resource: HashMap<Handle<Texture>, RenderResource>,
|
||||
pub mesh_to_vertices_resource: HashMap<Handle<Mesh>, RenderResource>,
|
||||
pub mesh_to_indices_resource: HashMap<Handle<Mesh>, RenderResource>,
|
||||
texture_to_resource: HashMap<Handle<Texture>, RenderResource>,
|
||||
texture_to_sampler_resource: HashMap<Handle<Texture>, RenderResource>,
|
||||
mesh_to_vertices_resource: HashMap<Handle<Mesh>, RenderResource>,
|
||||
mesh_to_indices_resource: HashMap<Handle<Mesh>, RenderResource>,
|
||||
}
|
||||
|
||||
impl AssetResources {
|
||||
pub fn consume(&mut self, render_resources: AssetResources) {
|
||||
// TODO: this is brittle. consider a single change-stream-based approach instead?
|
||||
self.texture_to_resource
|
||||
.extend(render_resources.texture_to_resource);
|
||||
self.texture_to_sampler_resource
|
||||
.extend(render_resources.texture_to_sampler_resource);
|
||||
self.mesh_to_vertices_resource
|
||||
.extend(render_resources.mesh_to_vertices_resource);
|
||||
self.mesh_to_indices_resource
|
||||
.extend(render_resources.mesh_to_indices_resource);
|
||||
}
|
||||
|
||||
pub fn set_texture_resource(&mut self, texture: Handle<Texture>, resource: RenderResource) {
|
||||
self.texture_to_resource.insert(texture, resource);
|
||||
}
|
||||
|
||||
@ -6,13 +6,33 @@ use crate::{
|
||||
};
|
||||
use bevy_asset::{AssetStorage, Handle};
|
||||
use bevy_window::{Window, WindowId};
|
||||
use std::any::Any;
|
||||
|
||||
pub struct GlobalRenderResourceContext {
|
||||
pub context: Box<dyn RenderResourceContext + Send + Sync + 'static>,
|
||||
}
|
||||
|
||||
impl GlobalRenderResourceContext {
|
||||
pub fn new<T>(context: T) -> GlobalRenderResourceContext
|
||||
where
|
||||
T: RenderResourceContext + Send + Sync + 'static,
|
||||
{
|
||||
GlobalRenderResourceContext {
|
||||
context: Box::new(context),
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn render_resources_mut(&mut self) -> &dyn RenderResourceContext {
|
||||
// (&mut self.context).downcast_mut::<dyn RenderResourceContext>()
|
||||
// }
|
||||
|
||||
// pub fn downcast_mut(&self) -> &dyn RenderResourceContext {
|
||||
// self.context.downcast_ref::<RenderResourceContext>()
|
||||
// }
|
||||
}
|
||||
|
||||
// TODO: Rename to RenderResources after cleaning up AssetResources rename
|
||||
pub trait RenderResourceContext {
|
||||
pub trait RenderResourceContext: Any {
|
||||
fn create_swap_chain(&mut self, window: &Window);
|
||||
fn next_swap_chain_texture(&mut self, window_id: WindowId);
|
||||
fn drop_swap_chain_texture(&mut self, window_id: WindowId);
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
mod systems;
|
||||
mod wgpu_render_context;
|
||||
mod wgpu_render_resource_context;
|
||||
mod wgpu_transactional_render_resource_context;
|
||||
|
||||
pub use systems::*;
|
||||
pub use wgpu_render_context::*;
|
||||
pub use wgpu_render_resource_context::*;
|
||||
pub use wgpu_transactional_render_resource_context::*;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use super::WgpuRenderResourceContextTrait;
|
||||
use super::WgpuRenderResourceContext;
|
||||
use crate::{
|
||||
wgpu_type_converter::{OwnedWgpuVertexBufferDescriptor, WgpuInto},
|
||||
WgpuRenderPass,
|
||||
@ -21,7 +21,7 @@ use bevy_window::WindowId;
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
#[derive(Default)]
|
||||
struct LazyCommandEncoder {
|
||||
pub struct LazyCommandEncoder {
|
||||
command_encoder: Option<wgpu::CommandEncoder>,
|
||||
}
|
||||
|
||||
@ -55,22 +55,16 @@ impl LazyCommandEncoder {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WgpuRenderContext<T>
|
||||
where
|
||||
T: RenderResourceContext,
|
||||
{
|
||||
pub struct WgpuRenderContext {
|
||||
pub device: Arc<wgpu::Device>,
|
||||
// TODO: remove this
|
||||
pub primary_window: Option<WindowId>,
|
||||
command_encoder: LazyCommandEncoder,
|
||||
pub render_resources: T,
|
||||
pub command_encoder: LazyCommandEncoder,
|
||||
pub render_resources: WgpuRenderResourceContext,
|
||||
}
|
||||
|
||||
impl<T> WgpuRenderContext<T>
|
||||
where
|
||||
T: RenderResourceContext,
|
||||
{
|
||||
pub fn new(device: Arc<wgpu::Device>, resources: T) -> Self {
|
||||
impl WgpuRenderContext {
|
||||
pub fn new(device: Arc<wgpu::Device>, resources: WgpuRenderResourceContext) -> Self {
|
||||
WgpuRenderContext {
|
||||
device,
|
||||
primary_window: None,
|
||||
@ -81,34 +75,25 @@ where
|
||||
|
||||
/// Consume this context, finalize the current CommandEncoder (if it exists), and take the current WgpuResources.
|
||||
/// This is intended to be called from a worker thread right before synchronizing with the main thread.
|
||||
pub fn finish(mut self) -> (Option<wgpu::CommandBuffer>, T) {
|
||||
(
|
||||
self.command_encoder.take().map(|encoder| encoder.finish()),
|
||||
self.render_resources,
|
||||
)
|
||||
}
|
||||
|
||||
/// Consume this context, finalize the current CommandEncoder (if it exists), and take the current WgpuResources.
|
||||
/// This is intended to be called from a worker thread right before synchronizing with the main thread.
|
||||
pub fn finish_encoder(&mut self) -> Option<wgpu::CommandBuffer> {
|
||||
pub fn finish(&mut self) -> Option<wgpu::CommandBuffer> {
|
||||
self.command_encoder.take().map(|encoder| encoder.finish())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> RenderContext for WgpuRenderContext<T>
|
||||
where
|
||||
T: RenderResourceContext + WgpuRenderResourceContextTrait,
|
||||
{
|
||||
impl RenderContext for WgpuRenderContext {
|
||||
fn create_texture_with_data(
|
||||
&mut self,
|
||||
texture_descriptor: &TextureDescriptor,
|
||||
bytes: &[u8],
|
||||
) -> RenderResource {
|
||||
self.render_resources.create_texture_with_data(
|
||||
self.command_encoder.get_or_create(&self.device),
|
||||
texture_descriptor,
|
||||
bytes,
|
||||
)
|
||||
self.render_resources
|
||||
.wgpu_resources
|
||||
.create_texture_with_data(
|
||||
&self.device,
|
||||
self.command_encoder.get_or_create(&self.device),
|
||||
texture_descriptor,
|
||||
bytes,
|
||||
)
|
||||
}
|
||||
fn copy_buffer_to_buffer(
|
||||
&mut self,
|
||||
@ -119,15 +104,11 @@ where
|
||||
size: u64,
|
||||
) {
|
||||
let command_encoder = self.command_encoder.get_or_create(&self.device);
|
||||
let source = self.render_resources.get_buffer(source_buffer).unwrap();
|
||||
let destination = self
|
||||
.render_resources
|
||||
.get_buffer(destination_buffer)
|
||||
.unwrap();
|
||||
command_encoder.copy_buffer_to_buffer(
|
||||
source,
|
||||
self.render_resources.wgpu_resources.copy_buffer_to_buffer(
|
||||
command_encoder,
|
||||
source_buffer,
|
||||
source_offset,
|
||||
destination,
|
||||
destination_buffer,
|
||||
destination_offset,
|
||||
size,
|
||||
);
|
||||
@ -148,6 +129,7 @@ where
|
||||
{
|
||||
if let None = self
|
||||
.render_resources
|
||||
.wgpu_resources
|
||||
.get_bind_group(bind_group_descriptor.id, *render_resource_set_id)
|
||||
{
|
||||
log::trace!(
|
||||
@ -155,6 +137,19 @@ where
|
||||
render_resource_set_id
|
||||
);
|
||||
let wgpu_bind_group = {
|
||||
let textures = self
|
||||
.render_resources
|
||||
.wgpu_resources
|
||||
.textures
|
||||
.read()
|
||||
.unwrap();
|
||||
let samplers = self
|
||||
.render_resources
|
||||
.wgpu_resources
|
||||
.samplers
|
||||
.read()
|
||||
.unwrap();
|
||||
let buffers = self.render_resources.wgpu_resources.buffers.read().unwrap();
|
||||
let bindings = bind_group_descriptor
|
||||
.bindings
|
||||
.iter()
|
||||
@ -174,10 +169,7 @@ where
|
||||
resource: match &binding.bind_type {
|
||||
BindType::SampledTexture { .. } => {
|
||||
if let ResourceInfo::Texture = resource_info {
|
||||
let texture = self
|
||||
.render_resources
|
||||
.get_texture(resource)
|
||||
.unwrap();
|
||||
let texture = textures.get(&resource).unwrap();
|
||||
wgpu::BindingResource::TextureView(texture)
|
||||
} else {
|
||||
panic!("expected a Texture resource");
|
||||
@ -185,10 +177,7 @@ where
|
||||
}
|
||||
BindType::Sampler { .. } => {
|
||||
if let ResourceInfo::Sampler = resource_info {
|
||||
let sampler = self
|
||||
.render_resources
|
||||
.get_sampler(resource)
|
||||
.unwrap();
|
||||
let sampler = samplers.get(&resource).unwrap();
|
||||
wgpu::BindingResource::Sampler(sampler)
|
||||
} else {
|
||||
panic!("expected a Sampler resource");
|
||||
@ -197,10 +186,7 @@ where
|
||||
BindType::Uniform { .. } => {
|
||||
if let ResourceInfo::Buffer(buffer_info) = resource_info
|
||||
{
|
||||
let buffer = self
|
||||
.render_resources
|
||||
.get_buffer(resource)
|
||||
.unwrap();
|
||||
let buffer = buffers.get(&resource).unwrap();
|
||||
wgpu::BindingResource::Buffer {
|
||||
buffer,
|
||||
range: 0..buffer_info.size as u64,
|
||||
@ -221,19 +207,26 @@ where
|
||||
}
|
||||
})
|
||||
.collect::<Vec<wgpu::Binding>>();
|
||||
let bind_group_layout = self
|
||||
let bind_group_layouts = self
|
||||
.render_resources
|
||||
.get_bind_group_layout(bind_group_descriptor.id)
|
||||
.wgpu_resources
|
||||
.bind_group_layouts
|
||||
.read()
|
||||
.unwrap();
|
||||
let bind_group_layout =
|
||||
bind_group_layouts.get(&bind_group_descriptor.id).unwrap();
|
||||
let wgpu_bind_group_descriptor = wgpu::BindGroupDescriptor {
|
||||
label: None,
|
||||
layout: bind_group_layout,
|
||||
bindings: bindings.as_slice(),
|
||||
};
|
||||
self.render_resources
|
||||
.create_bind_group(*render_resource_set_id, &wgpu_bind_group_descriptor)
|
||||
self.render_resources.wgpu_resources.create_bind_group(
|
||||
&self.device,
|
||||
*render_resource_set_id,
|
||||
&wgpu_bind_group_descriptor,
|
||||
)
|
||||
};
|
||||
self.render_resources.set_bind_group(
|
||||
self.render_resources.wgpu_resources.set_bind_group(
|
||||
bind_group_descriptor.id,
|
||||
*render_resource_set_id,
|
||||
wgpu_bind_group,
|
||||
@ -250,13 +243,27 @@ where
|
||||
pipeline_descriptor: &mut PipelineDescriptor,
|
||||
shader_storage: &AssetStorage<Shader>,
|
||||
) {
|
||||
if let Some(_) = self.render_resources.get_pipeline(pipeline_handle) {
|
||||
if let Some(_) = self
|
||||
.render_resources
|
||||
.wgpu_resources
|
||||
.render_pipelines
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(&pipeline_handle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let layout = pipeline_descriptor.get_layout().unwrap();
|
||||
for bind_group in layout.bind_groups.iter() {
|
||||
if let None = self.render_resources.get_bind_group_layout(bind_group.id) {
|
||||
if let None = self
|
||||
.render_resources
|
||||
.wgpu_resources
|
||||
.bind_group_layouts
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(&bind_group.id)
|
||||
{
|
||||
let bind_group_layout_binding = bind_group
|
||||
.bindings
|
||||
.iter()
|
||||
@ -266,32 +273,37 @@ where
|
||||
ty: (&binding.bind_type).wgpu_into(),
|
||||
})
|
||||
.collect::<Vec<wgpu::BindGroupLayoutEntry>>();
|
||||
self.render_resources.create_bind_group_layout(
|
||||
bind_group.id,
|
||||
&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: bind_group_layout_binding.as_slice(),
|
||||
label: None,
|
||||
},
|
||||
);
|
||||
self.render_resources
|
||||
.wgpu_resources
|
||||
.create_bind_group_layout(
|
||||
&self.device,
|
||||
bind_group.id,
|
||||
&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: bind_group_layout_binding.as_slice(),
|
||||
label: None,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// setup and collect bind group layouts
|
||||
let bind_group_layouts = layout
|
||||
.bind_groups
|
||||
.iter()
|
||||
.map(|bind_group| {
|
||||
self.render_resources
|
||||
.get_bind_group_layout(bind_group.id)
|
||||
.unwrap()
|
||||
})
|
||||
.collect::<Vec<&wgpu::BindGroupLayout>>();
|
||||
|
||||
let pipeline_layout = self
|
||||
.device
|
||||
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: bind_group_layouts.as_slice(),
|
||||
});
|
||||
let pipeline_layout = {
|
||||
let bind_group_layouts = self
|
||||
.render_resources
|
||||
.wgpu_resources
|
||||
.bind_group_layouts
|
||||
.read()
|
||||
.unwrap();
|
||||
// setup and collect bind group layouts
|
||||
let bind_group_layouts = layout
|
||||
.bind_groups
|
||||
.iter()
|
||||
.map(|bind_group| bind_group_layouts.get(&bind_group.id).unwrap())
|
||||
.collect::<Vec<&wgpu::BindGroupLayout>>();
|
||||
self.device
|
||||
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: bind_group_layouts.as_slice(),
|
||||
})
|
||||
};
|
||||
|
||||
let owned_vertex_buffer_descriptors = layout
|
||||
.vertex_buffer_descriptors
|
||||
@ -305,32 +317,46 @@ where
|
||||
.map(|c| c.wgpu_into())
|
||||
.collect::<Vec<wgpu::ColorStateDescriptor>>();
|
||||
|
||||
if let None = self
|
||||
if self
|
||||
.render_resources
|
||||
.get_shader_module(pipeline_descriptor.shader_stages.vertex)
|
||||
.wgpu_resources
|
||||
.shader_modules
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(&pipeline_descriptor.shader_stages.vertex)
|
||||
.is_none()
|
||||
{
|
||||
self.render_resources
|
||||
.create_shader_module(pipeline_descriptor.shader_stages.vertex, shader_storage);
|
||||
}
|
||||
|
||||
if let Some(fragment_handle) = pipeline_descriptor.shader_stages.fragment {
|
||||
if let None = self.render_resources.get_shader_module(fragment_handle) {
|
||||
if self
|
||||
.render_resources
|
||||
.wgpu_resources
|
||||
.shader_modules
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(&fragment_handle)
|
||||
.is_none()
|
||||
{
|
||||
self.render_resources
|
||||
.create_shader_module(fragment_handle, shader_storage);
|
||||
}
|
||||
};
|
||||
let wgpu_pipeline = {
|
||||
let vertex_shader_module = self
|
||||
let shader_modules = self
|
||||
.render_resources
|
||||
.get_shader_module(pipeline_descriptor.shader_stages.vertex)
|
||||
.wgpu_resources
|
||||
.shader_modules
|
||||
.read()
|
||||
.unwrap();
|
||||
let vertex_shader_module = shader_modules
|
||||
.get(&pipeline_descriptor.shader_stages.vertex)
|
||||
.unwrap();
|
||||
|
||||
let fragment_shader_module = match pipeline_descriptor.shader_stages.fragment {
|
||||
Some(fragment_handle) => Some(
|
||||
self.render_resources
|
||||
.get_shader_module(fragment_handle)
|
||||
.unwrap(),
|
||||
),
|
||||
Some(fragment_handle) => Some(shader_modules.get(&fragment_handle).unwrap()),
|
||||
None => None,
|
||||
};
|
||||
|
||||
@ -370,9 +396,11 @@ where
|
||||
};
|
||||
|
||||
self.render_resources
|
||||
.create_render_pipeline(&render_pipeline_descriptor)
|
||||
.wgpu_resources
|
||||
.create_render_pipeline(&self.device, &render_pipeline_descriptor)
|
||||
};
|
||||
self.render_resources
|
||||
.wgpu_resources
|
||||
.set_render_pipeline(pipeline_handle, wgpu_pipeline);
|
||||
}
|
||||
fn begin_pass(
|
||||
@ -406,15 +434,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_render_pass<'a, 'b, T>(
|
||||
render_context: &'a WgpuRenderContext<T>,
|
||||
pub fn create_render_pass<'a, 'b>(
|
||||
render_context: &'a WgpuRenderContext,
|
||||
pass_descriptor: &PassDescriptor,
|
||||
global_render_resource_assignments: &'b RenderResourceAssignments,
|
||||
encoder: &'a mut wgpu::CommandEncoder,
|
||||
) -> wgpu::RenderPass<'a>
|
||||
where
|
||||
T: WgpuRenderResourceContextTrait + RenderResourceContext,
|
||||
{
|
||||
) -> wgpu::RenderPass<'a> {
|
||||
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
color_attachments: &pass_descriptor
|
||||
.color_attachments
|
||||
@ -437,19 +462,20 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
fn get_texture_view<'a, T>(
|
||||
render_context: &'a WgpuRenderContext<T>,
|
||||
fn get_texture_view<'a>(
|
||||
render_context: &'a WgpuRenderContext,
|
||||
global_render_resource_assignments: &RenderResourceAssignments,
|
||||
name: &str,
|
||||
) -> &'a wgpu::TextureView
|
||||
where
|
||||
T: WgpuRenderResourceContextTrait + RenderResourceContext,
|
||||
{
|
||||
) -> &'a wgpu::TextureView {
|
||||
match name {
|
||||
resource_name::texture::SWAP_CHAIN => {
|
||||
if let Some(primary_swap_chain) = render_context
|
||||
.render_resources
|
||||
.get_swap_chain_output(render_context.primary_window.as_ref().unwrap())
|
||||
.wgpu_resources
|
||||
.swap_chain_outputs
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(render_context.primary_window.as_ref().unwrap())
|
||||
.map(|output| &output.view)
|
||||
{
|
||||
primary_swap_chain
|
||||
@ -460,7 +486,11 @@ where
|
||||
_ => match global_render_resource_assignments.get(name) {
|
||||
Some(resource) => render_context
|
||||
.render_resources
|
||||
.get_texture(resource)
|
||||
.wgpu_resources
|
||||
.textures
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(&resource)
|
||||
.unwrap(),
|
||||
None => {
|
||||
// if let Some(swap_chain_output) = swap_chain_outputs.get(name) {
|
||||
@ -473,14 +503,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn create_wgpu_color_attachment_descriptor<'a, T>(
|
||||
render_context: &'a WgpuRenderContext<T>,
|
||||
fn create_wgpu_color_attachment_descriptor<'a>(
|
||||
render_context: &'a WgpuRenderContext,
|
||||
global_render_resource_assignments: &RenderResourceAssignments,
|
||||
color_attachment_descriptor: &RenderPassColorAttachmentDescriptor,
|
||||
) -> wgpu::RenderPassColorAttachmentDescriptor<'a>
|
||||
where
|
||||
T: WgpuRenderResourceContextTrait + RenderResourceContext,
|
||||
{
|
||||
) -> wgpu::RenderPassColorAttachmentDescriptor<'a> {
|
||||
let attachment = get_texture_view(
|
||||
render_context,
|
||||
global_render_resource_assignments,
|
||||
@ -507,14 +534,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn create_wgpu_depth_stencil_attachment_descriptor<'a, T>(
|
||||
render_context: &'a WgpuRenderContext<T>,
|
||||
fn create_wgpu_depth_stencil_attachment_descriptor<'a>(
|
||||
render_context: &'a WgpuRenderContext,
|
||||
global_render_resource_assignments: &RenderResourceAssignments,
|
||||
depth_stencil_attachment_descriptor: &RenderPassDepthStencilAttachmentDescriptor,
|
||||
) -> wgpu::RenderPassDepthStencilAttachmentDescriptor<'a>
|
||||
where
|
||||
T: WgpuRenderResourceContextTrait + RenderResourceContext,
|
||||
{
|
||||
) -> wgpu::RenderPassDepthStencilAttachmentDescriptor<'a> {
|
||||
let attachment = get_texture_view(
|
||||
render_context,
|
||||
global_render_resource_assignments,
|
||||
|
||||
@ -3,9 +3,8 @@ use crate::WgpuResources;
|
||||
use bevy_asset::{AssetStorage, Handle};
|
||||
use bevy_render::{
|
||||
mesh::Mesh,
|
||||
pipeline::{BindGroupDescriptorId, PipelineDescriptor},
|
||||
render_resource::{
|
||||
AssetResources, BufferInfo, RenderResource, RenderResourceSetId, ResourceInfo,
|
||||
AssetResources, BufferInfo, RenderResource, ResourceInfo,
|
||||
},
|
||||
renderer_2::RenderResourceContext,
|
||||
shader::Shader,
|
||||
@ -14,158 +13,18 @@ use bevy_render::{
|
||||
use std::sync::Arc;
|
||||
use bevy_window::{WindowId, Window};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WgpuRenderResourceContext {
|
||||
pub device: Arc<wgpu::Device>,
|
||||
pub wgpu_resources: WgpuResources,
|
||||
pub wgpu_resources: Arc<WgpuResources>,
|
||||
}
|
||||
|
||||
// TODO: make this name not terrible
|
||||
pub trait WgpuRenderResourceContextTrait {
|
||||
fn create_texture_with_data(
|
||||
&mut self,
|
||||
command_encoder: &mut wgpu::CommandEncoder,
|
||||
texture_descriptor: &TextureDescriptor,
|
||||
bytes: &[u8],
|
||||
) -> RenderResource;
|
||||
|
||||
fn create_bind_group(
|
||||
&self,
|
||||
render_resource_set_id: RenderResourceSetId,
|
||||
descriptor: &wgpu::BindGroupDescriptor,
|
||||
) -> wgpu::BindGroup;
|
||||
fn set_bind_group(
|
||||
&mut self,
|
||||
bind_group_descriptor_id: BindGroupDescriptorId,
|
||||
render_resource_set_id: RenderResourceSetId,
|
||||
bind_group: wgpu::BindGroup,
|
||||
);
|
||||
fn create_bind_group_layout(
|
||||
&mut self,
|
||||
bind_group_id: BindGroupDescriptorId,
|
||||
descriptor: &wgpu::BindGroupLayoutDescriptor,
|
||||
);
|
||||
fn create_render_pipeline(
|
||||
&self,
|
||||
descriptor: &wgpu::RenderPipelineDescriptor,
|
||||
) -> wgpu::RenderPipeline;
|
||||
fn set_render_pipeline(
|
||||
&mut self,
|
||||
pipeline_handle: Handle<PipelineDescriptor>,
|
||||
pipeline: wgpu::RenderPipeline,
|
||||
);
|
||||
fn get_bind_group(
|
||||
&self,
|
||||
bind_group_id: BindGroupDescriptorId,
|
||||
render_resource_set_id: RenderResourceSetId,
|
||||
) -> Option<&wgpu::BindGroup>;
|
||||
fn get_bind_group_layout(
|
||||
&self,
|
||||
bind_group_id: BindGroupDescriptorId,
|
||||
) -> Option<&wgpu::BindGroupLayout>;
|
||||
fn get_buffer(&self, render_resource: RenderResource) -> Option<&wgpu::Buffer>;
|
||||
fn get_swap_chain_output(&self, window_id: &WindowId) -> Option<&wgpu::SwapChainOutput>;
|
||||
fn get_texture(&self, render_resource: RenderResource) -> Option<&wgpu::TextureView>;
|
||||
fn get_sampler(&self, render_resource: RenderResource) -> Option<&wgpu::Sampler>;
|
||||
fn get_pipeline(&self, pipeline: Handle<PipelineDescriptor>) -> Option<&wgpu::RenderPipeline>;
|
||||
fn get_shader_module(&self, shader: Handle<Shader>) -> Option<&wgpu::ShaderModule>;
|
||||
}
|
||||
|
||||
impl WgpuRenderResourceContextTrait for WgpuRenderResourceContext {
|
||||
fn get_buffer(&self, render_resource: RenderResource) -> Option<&wgpu::Buffer> {
|
||||
self.wgpu_resources.buffers.get(&render_resource)
|
||||
}
|
||||
fn create_texture_with_data(
|
||||
&mut self,
|
||||
command_encoder: &mut wgpu::CommandEncoder,
|
||||
texture_descriptor: &TextureDescriptor,
|
||||
bytes: &[u8],
|
||||
) -> RenderResource {
|
||||
self.wgpu_resources.create_texture_with_data(
|
||||
&self.device,
|
||||
command_encoder,
|
||||
texture_descriptor,
|
||||
bytes,
|
||||
)
|
||||
}
|
||||
fn create_bind_group(
|
||||
&self,
|
||||
render_resource_set_id: RenderResourceSetId,
|
||||
descriptor: &wgpu::BindGroupDescriptor,
|
||||
) -> wgpu::BindGroup {
|
||||
self.wgpu_resources
|
||||
.create_bind_group(&self.device, render_resource_set_id, descriptor)
|
||||
}
|
||||
fn create_bind_group_layout(
|
||||
&mut self,
|
||||
bind_group_id: BindGroupDescriptorId,
|
||||
descriptor: &wgpu::BindGroupLayoutDescriptor,
|
||||
) {
|
||||
self.wgpu_resources
|
||||
.create_bind_group_layout(&self.device, bind_group_id, descriptor);
|
||||
}
|
||||
fn create_render_pipeline(
|
||||
&self,
|
||||
descriptor: &wgpu::RenderPipelineDescriptor,
|
||||
) -> wgpu::RenderPipeline {
|
||||
self.wgpu_resources
|
||||
.create_render_pipeline(&self.device, descriptor)
|
||||
}
|
||||
fn get_bind_group(
|
||||
&self,
|
||||
bind_group_descriptor_id: BindGroupDescriptorId,
|
||||
render_resource_set_id: RenderResourceSetId,
|
||||
) -> Option<&wgpu::BindGroup> {
|
||||
self.wgpu_resources
|
||||
.get_bind_group(bind_group_descriptor_id, render_resource_set_id)
|
||||
}
|
||||
fn get_bind_group_layout(
|
||||
&self,
|
||||
bind_group_id: BindGroupDescriptorId,
|
||||
) -> Option<&wgpu::BindGroupLayout> {
|
||||
self.wgpu_resources.bind_group_layouts.get(&bind_group_id)
|
||||
}
|
||||
fn get_texture(&self, render_resource: RenderResource) -> Option<&wgpu::TextureView> {
|
||||
self.wgpu_resources.textures.get(&render_resource)
|
||||
}
|
||||
fn get_sampler(&self, render_resource: RenderResource) -> Option<&wgpu::Sampler> {
|
||||
self.wgpu_resources.samplers.get(&render_resource)
|
||||
}
|
||||
fn get_pipeline(&self, pipeline: Handle<PipelineDescriptor>) -> Option<&wgpu::RenderPipeline> {
|
||||
self.wgpu_resources.render_pipelines.get(&pipeline)
|
||||
}
|
||||
fn get_shader_module(&self, shader: Handle<Shader>) -> Option<&wgpu::ShaderModule> {
|
||||
self.wgpu_resources.shader_modules.get(&shader)
|
||||
}
|
||||
fn set_bind_group(
|
||||
&mut self,
|
||||
bind_group_descriptor_id: BindGroupDescriptorId,
|
||||
render_resource_set_id: RenderResourceSetId,
|
||||
bind_group: wgpu::BindGroup,
|
||||
) {
|
||||
self.wgpu_resources.set_bind_group(
|
||||
bind_group_descriptor_id,
|
||||
render_resource_set_id,
|
||||
bind_group,
|
||||
);
|
||||
}
|
||||
fn set_render_pipeline(
|
||||
&mut self,
|
||||
pipeline_handle: Handle<PipelineDescriptor>,
|
||||
pipeline: wgpu::RenderPipeline,
|
||||
) {
|
||||
self.wgpu_resources
|
||||
.set_render_pipeline(pipeline_handle, pipeline);
|
||||
}
|
||||
fn get_swap_chain_output(&self, window_id: &WindowId) -> Option<&wgpu::SwapChainOutput> {
|
||||
self.wgpu_resources.swap_chain_outputs.get(window_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl WgpuRenderResourceContext {
|
||||
pub fn new(device: Arc<wgpu::Device>) -> Self {
|
||||
WgpuRenderResourceContext {
|
||||
device,
|
||||
wgpu_resources: WgpuResources::default(),
|
||||
wgpu_resources: Arc::new(WgpuResources::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -251,7 +110,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
||||
shader_handle: Handle<Shader>,
|
||||
shader_storage: &AssetStorage<Shader>,
|
||||
) {
|
||||
if self.get_shader_module(shader_handle).is_some() {
|
||||
if self.wgpu_resources.shader_modules.read().unwrap().get(&shader_handle).is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -1,307 +0,0 @@
|
||||
use crate::WgpuResources;
|
||||
|
||||
use super::WgpuRenderResourceContextTrait;
|
||||
use bevy_asset::Handle;
|
||||
use bevy_render::{
|
||||
mesh::Mesh,
|
||||
pipeline::{BindGroupDescriptorId, PipelineDescriptor},
|
||||
render_resource::{
|
||||
AssetResources, BufferInfo, RenderResource, RenderResourceSetId, ResourceInfo,
|
||||
},
|
||||
renderer_2::RenderResourceContext,
|
||||
shader::Shader,
|
||||
texture::{SamplerDescriptor, Texture, TextureDescriptor},
|
||||
};
|
||||
use bevy_window::{WindowId, Window};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct WgpuTransactionalRenderResourceContext<'a> {
|
||||
pub device: Arc<wgpu::Device>,
|
||||
pub local_resources: WgpuResources,
|
||||
pub parent_resources: &'a WgpuResources,
|
||||
removed_resources: Vec<RenderResource>,
|
||||
}
|
||||
|
||||
impl<'a> WgpuRenderResourceContextTrait for WgpuTransactionalRenderResourceContext<'a> {
|
||||
fn get_buffer(&self, render_resource: RenderResource) -> Option<&wgpu::Buffer> {
|
||||
let local = self.local_resources.buffers.get(&render_resource);
|
||||
if local.is_some() {
|
||||
return local;
|
||||
}
|
||||
|
||||
self.parent_resources.buffers.get(&render_resource)
|
||||
}
|
||||
|
||||
fn create_texture_with_data(
|
||||
&mut self,
|
||||
command_encoder: &mut wgpu::CommandEncoder,
|
||||
texture_descriptor: &TextureDescriptor,
|
||||
bytes: &[u8],
|
||||
) -> RenderResource {
|
||||
self.local_resources.create_texture_with_data(
|
||||
&self.device,
|
||||
command_encoder,
|
||||
texture_descriptor,
|
||||
bytes,
|
||||
)
|
||||
}
|
||||
fn create_bind_group(
|
||||
&self,
|
||||
render_resource_set_id: RenderResourceSetId,
|
||||
descriptor: &wgpu::BindGroupDescriptor,
|
||||
) -> wgpu::BindGroup {
|
||||
self.local_resources
|
||||
.create_bind_group(&self.device, render_resource_set_id, descriptor)
|
||||
}
|
||||
fn create_bind_group_layout(
|
||||
&mut self,
|
||||
bind_group_id: BindGroupDescriptorId,
|
||||
descriptor: &wgpu::BindGroupLayoutDescriptor,
|
||||
) {
|
||||
self.local_resources
|
||||
.create_bind_group_layout(&self.device, bind_group_id, descriptor);
|
||||
}
|
||||
fn create_render_pipeline(
|
||||
&self,
|
||||
descriptor: &wgpu::RenderPipelineDescriptor,
|
||||
) -> wgpu::RenderPipeline {
|
||||
self.local_resources
|
||||
.create_render_pipeline(&self.device, descriptor)
|
||||
}
|
||||
fn get_bind_group(
|
||||
&self,
|
||||
bind_group_descriptor_id: BindGroupDescriptorId,
|
||||
render_resource_set_id: RenderResourceSetId,
|
||||
) -> Option<&wgpu::BindGroup> {
|
||||
let local = self
|
||||
.local_resources
|
||||
.get_bind_group(bind_group_descriptor_id, render_resource_set_id);
|
||||
if local.is_some() {
|
||||
return local;
|
||||
}
|
||||
self.parent_resources
|
||||
.get_bind_group(bind_group_descriptor_id, render_resource_set_id)
|
||||
}
|
||||
fn get_bind_group_layout(
|
||||
&self,
|
||||
bind_group_id: BindGroupDescriptorId,
|
||||
) -> Option<&wgpu::BindGroupLayout> {
|
||||
let local = self.local_resources.bind_group_layouts.get(&bind_group_id);
|
||||
if local.is_some() {
|
||||
return local;
|
||||
}
|
||||
self.parent_resources.bind_group_layouts.get(&bind_group_id)
|
||||
}
|
||||
fn get_texture(&self, render_resource: RenderResource) -> Option<&wgpu::TextureView> {
|
||||
let local = self.local_resources.textures.get(&render_resource);
|
||||
if local.is_some() {
|
||||
return local;
|
||||
}
|
||||
self.parent_resources.textures.get(&render_resource)
|
||||
}
|
||||
fn get_sampler(&self, render_resource: RenderResource) -> Option<&wgpu::Sampler> {
|
||||
let local = self.local_resources.samplers.get(&render_resource);
|
||||
if local.is_some() {
|
||||
return local;
|
||||
}
|
||||
self.parent_resources.samplers.get(&render_resource)
|
||||
}
|
||||
fn get_pipeline(&self, pipeline: Handle<PipelineDescriptor>) -> Option<&wgpu::RenderPipeline> {
|
||||
let local = self.local_resources.render_pipelines.get(&pipeline);
|
||||
if local.is_some() {
|
||||
return local;
|
||||
}
|
||||
self.parent_resources.render_pipelines.get(&pipeline)
|
||||
}
|
||||
fn get_shader_module(&self, shader: Handle<Shader>) -> Option<&wgpu::ShaderModule> {
|
||||
let local = self.local_resources.shader_modules.get(&shader);
|
||||
if local.is_some() {
|
||||
return local;
|
||||
}
|
||||
self.parent_resources.shader_modules.get(&shader)
|
||||
}
|
||||
fn set_bind_group(
|
||||
&mut self,
|
||||
bind_group_descriptor_id: BindGroupDescriptorId,
|
||||
render_resource_set_id: RenderResourceSetId,
|
||||
bind_group: wgpu::BindGroup,
|
||||
) {
|
||||
self.local_resources.set_bind_group(
|
||||
bind_group_descriptor_id,
|
||||
render_resource_set_id,
|
||||
bind_group,
|
||||
);
|
||||
}
|
||||
fn set_render_pipeline(
|
||||
&mut self,
|
||||
pipeline_handle: Handle<PipelineDescriptor>,
|
||||
pipeline: wgpu::RenderPipeline,
|
||||
) {
|
||||
self.local_resources
|
||||
.set_render_pipeline(pipeline_handle, pipeline);
|
||||
}
|
||||
fn get_swap_chain_output(
|
||||
&self,
|
||||
window_id: &bevy_window::WindowId,
|
||||
) -> Option<&wgpu::SwapChainOutput> {
|
||||
let local = self.local_resources.swap_chain_outputs.get(window_id);
|
||||
if local.is_some() {
|
||||
return local;
|
||||
}
|
||||
self.parent_resources.swap_chain_outputs.get(window_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> WgpuTransactionalRenderResourceContext<'a> {
|
||||
pub fn new(device: Arc<wgpu::Device>, parent_resources: &'a WgpuResources) -> Self {
|
||||
WgpuTransactionalRenderResourceContext {
|
||||
device,
|
||||
local_resources: WgpuResources::default(),
|
||||
parent_resources,
|
||||
removed_resources: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> RenderResourceContext for WgpuTransactionalRenderResourceContext<'a> {
|
||||
fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource {
|
||||
self.local_resources
|
||||
.create_sampler(&self.device, sampler_descriptor)
|
||||
}
|
||||
fn create_texture(&mut self, texture_descriptor: &TextureDescriptor) -> RenderResource {
|
||||
self.local_resources
|
||||
.create_texture(&self.device, texture_descriptor)
|
||||
}
|
||||
fn create_buffer(&mut self, buffer_info: BufferInfo) -> RenderResource {
|
||||
self.local_resources
|
||||
.create_buffer(&self.device, buffer_info)
|
||||
}
|
||||
|
||||
// TODO: clean this up
|
||||
fn create_buffer_mapped(
|
||||
&mut self,
|
||||
buffer_info: BufferInfo,
|
||||
setup_data: &mut dyn FnMut(&mut [u8], &mut dyn RenderResourceContext),
|
||||
) -> RenderResource {
|
||||
let buffer = WgpuResources::begin_create_buffer_mapped_transactional_render_context(
|
||||
&buffer_info,
|
||||
self,
|
||||
setup_data,
|
||||
);
|
||||
self.local_resources.assign_buffer(buffer, buffer_info)
|
||||
}
|
||||
|
||||
fn create_buffer_with_data(&mut self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource {
|
||||
self.local_resources
|
||||
.create_buffer_with_data(&self.device, buffer_info, data)
|
||||
}
|
||||
|
||||
fn remove_buffer(&mut self, resource: RenderResource) {
|
||||
self.local_resources.remove_buffer(resource);
|
||||
self.removed_resources.push(resource);
|
||||
}
|
||||
fn remove_texture(&mut self, resource: RenderResource) {
|
||||
self.local_resources.remove_texture(resource);
|
||||
self.removed_resources.push(resource);
|
||||
}
|
||||
fn remove_sampler(&mut self, resource: RenderResource) {
|
||||
self.local_resources.remove_sampler(resource);
|
||||
self.removed_resources.push(resource);
|
||||
}
|
||||
|
||||
fn get_texture_resource(&self, texture: Handle<Texture>) -> Option<RenderResource> {
|
||||
let local = self
|
||||
.local_resources
|
||||
.asset_resources
|
||||
.get_texture_resource(texture);
|
||||
if local.is_some() {
|
||||
return local;
|
||||
}
|
||||
|
||||
self.parent_resources
|
||||
.asset_resources
|
||||
.get_texture_resource(texture)
|
||||
}
|
||||
|
||||
fn get_texture_sampler_resource(&self, texture: Handle<Texture>) -> Option<RenderResource> {
|
||||
let local = self
|
||||
.local_resources
|
||||
.asset_resources
|
||||
.get_texture_sampler_resource(texture);
|
||||
|
||||
if local.is_some() {
|
||||
return local;
|
||||
}
|
||||
|
||||
self.parent_resources
|
||||
.asset_resources
|
||||
.get_texture_sampler_resource(texture)
|
||||
}
|
||||
|
||||
fn get_mesh_vertices_resource(&self, mesh: Handle<Mesh>) -> Option<RenderResource> {
|
||||
let local = self
|
||||
.local_resources
|
||||
.asset_resources
|
||||
.get_mesh_vertices_resource(mesh);
|
||||
if local.is_some() {
|
||||
return local;
|
||||
}
|
||||
|
||||
self.parent_resources
|
||||
.asset_resources
|
||||
.get_mesh_vertices_resource(mesh)
|
||||
}
|
||||
|
||||
fn get_mesh_indices_resource(&self, mesh: Handle<Mesh>) -> Option<RenderResource> {
|
||||
let local = self
|
||||
.local_resources
|
||||
.asset_resources
|
||||
.get_mesh_indices_resource(mesh);
|
||||
if local.is_some() {
|
||||
return local;
|
||||
}
|
||||
|
||||
self.parent_resources
|
||||
.asset_resources
|
||||
.get_mesh_indices_resource(mesh)
|
||||
}
|
||||
|
||||
fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> {
|
||||
let local = self.local_resources.get_resource_info(resource);
|
||||
if local.is_some() {
|
||||
return local;
|
||||
}
|
||||
|
||||
self.parent_resources.get_resource_info(resource)
|
||||
}
|
||||
|
||||
fn asset_resources(&self) -> &AssetResources {
|
||||
&self.local_resources.asset_resources
|
||||
}
|
||||
fn asset_resources_mut(&mut self) -> &mut AssetResources {
|
||||
&mut self.local_resources.asset_resources
|
||||
}
|
||||
fn create_shader_module(
|
||||
&mut self,
|
||||
shader_handle: Handle<Shader>,
|
||||
shader_storage: &bevy_asset::AssetStorage<Shader>,
|
||||
) {
|
||||
if self.get_shader_module(shader_handle).is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
let shader = shader_storage.get(&shader_handle).unwrap();
|
||||
self.local_resources
|
||||
.create_shader_module(&self.device, shader_handle, shader);
|
||||
}
|
||||
fn create_swap_chain(&mut self, window: &Window) {
|
||||
self.local_resources
|
||||
.create_window_swap_chain(&self.device, window)
|
||||
}
|
||||
fn next_swap_chain_texture(&mut self, window_id: bevy_window::WindowId) {
|
||||
self.local_resources.next_swap_chain_texture(window_id);
|
||||
}
|
||||
fn drop_swap_chain_texture(&mut self, window_id: WindowId) {
|
||||
self.local_resources.remove_swap_chain_texture(window_id);
|
||||
}
|
||||
}
|
||||
@ -1,47 +1,48 @@
|
||||
use crate::renderer_2::{WgpuRenderContext, WgpuRenderResourceContextTrait};
|
||||
use crate::renderer_2::WgpuRenderContext;
|
||||
use bevy_asset::Handle;
|
||||
use bevy_render::{
|
||||
pass::RenderPass,
|
||||
pipeline::PipelineDescriptor,
|
||||
render_resource::{
|
||||
RenderResource, RenderResourceAssignments, RenderResourceSetId, ResourceInfo,
|
||||
},
|
||||
renderer_2::{RenderContext, RenderResourceContext},
|
||||
renderer_2::RenderContext,
|
||||
};
|
||||
use std::{collections::HashMap, ops::Range};
|
||||
|
||||
pub struct WgpuRenderPass<'a, T>
|
||||
where
|
||||
T: RenderResourceContext + WgpuRenderResourceContextTrait,
|
||||
{
|
||||
pub struct WgpuRenderPass<'a> {
|
||||
pub render_pass: wgpu::RenderPass<'a>,
|
||||
pub render_context: &'a WgpuRenderContext<T>,
|
||||
pub render_context: &'a WgpuRenderContext,
|
||||
pub bound_bind_groups: HashMap<u32, RenderResourceSetId>,
|
||||
}
|
||||
|
||||
impl<'a, T> RenderPass for WgpuRenderPass<'a, T>
|
||||
where
|
||||
T: RenderResourceContext + WgpuRenderResourceContextTrait,
|
||||
{
|
||||
impl<'a> RenderPass for WgpuRenderPass<'a> {
|
||||
fn get_render_context(&self) -> &dyn RenderContext {
|
||||
self.render_context
|
||||
}
|
||||
|
||||
fn set_vertex_buffer(&mut self, start_slot: u32, resource: RenderResource, offset: u64) {
|
||||
let buffer = self
|
||||
let buffers = self
|
||||
.render_context
|
||||
.render_resources
|
||||
.get_buffer(resource)
|
||||
.wgpu_resources
|
||||
.buffers
|
||||
.read()
|
||||
.unwrap();
|
||||
let buffer = buffers.get(&resource).unwrap();
|
||||
self.render_pass
|
||||
.set_vertex_buffer(start_slot, &buffer, offset, 0);
|
||||
}
|
||||
|
||||
fn set_index_buffer(&mut self, resource: RenderResource, offset: u64) {
|
||||
let buffer = self
|
||||
let buffers = self
|
||||
.render_context
|
||||
.render_resources
|
||||
.get_buffer(resource)
|
||||
.wgpu_resources
|
||||
.buffers
|
||||
.read()
|
||||
.unwrap();
|
||||
let buffer = buffers.get(&resource).unwrap();
|
||||
self.render_pass.set_index_buffer(&buffer, offset, 0);
|
||||
}
|
||||
|
||||
@ -55,8 +56,7 @@ where
|
||||
pipeline_descriptor: &PipelineDescriptor,
|
||||
render_resource_assignments: &RenderResourceAssignments,
|
||||
) -> Option<Range<u32>> {
|
||||
let pipeline_layout = pipeline_descriptor.get_layout()
|
||||
.unwrap();
|
||||
let pipeline_layout = pipeline_descriptor.get_layout().unwrap();
|
||||
// PERF: vertex buffer lookup comes at a cost when vertex buffers aren't in render_resource_assignments. iterating over render_resource_assignment vertex buffers
|
||||
// would likely be faster
|
||||
let mut indices = None;
|
||||
@ -102,6 +102,7 @@ where
|
||||
if let Some(wgpu_bind_group) = self
|
||||
.render_context
|
||||
.render_resources
|
||||
.wgpu_resources
|
||||
.get_bind_group(bind_group.id, *render_resource_set_id)
|
||||
{
|
||||
const EMPTY: &'static [u32] = &[];
|
||||
@ -148,8 +149,17 @@ where
|
||||
|
||||
indices
|
||||
}
|
||||
fn set_pipeline(&mut self, pipeline_handle: bevy_asset::Handle<PipelineDescriptor>) {
|
||||
let pipeline = self.render_context.render_resources.get_pipeline(pipeline_handle).expect("Attempted to use a pipeline that does not exist in this RenderPass's RenderContext");
|
||||
fn set_pipeline(&mut self, pipeline_handle: Handle<PipelineDescriptor>) {
|
||||
let render_pipelines = self
|
||||
.render_context
|
||||
.render_resources
|
||||
.wgpu_resources
|
||||
.render_pipelines
|
||||
.read()
|
||||
.unwrap();
|
||||
let pipeline = render_pipelines.get(&pipeline_handle).expect(
|
||||
"Attempted to use a pipeline that does not exist in this RenderPass's RenderContext",
|
||||
);
|
||||
self.render_pass.set_pipeline(pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
use super::WgpuResources;
|
||||
use crate::renderer_2::{
|
||||
render_resource_sets_system, WgpuRenderContext, WgpuRenderResourceContext,
|
||||
WgpuTransactionalRenderResourceContext,
|
||||
};
|
||||
use bevy_app::{EventReader, Events};
|
||||
use bevy_asset::AssetStorage;
|
||||
@ -9,14 +7,14 @@ use bevy_render::{
|
||||
pipeline::{update_shader_assignments, PipelineCompiler, PipelineDescriptor},
|
||||
render_graph::RenderGraph,
|
||||
render_resource::RenderResourceAssignments,
|
||||
renderer_2::{RenderContext, RenderResourceContext},
|
||||
renderer_2::{GlobalRenderResourceContext, RenderContext, RenderResourceContext},
|
||||
};
|
||||
use bevy_window::{WindowCreated, WindowResized, Windows};
|
||||
use legion::prelude::*;
|
||||
use std::{collections::HashSet, ops::Deref, sync::Arc};
|
||||
use std::{any::Any, collections::HashSet, ops::Deref, sync::Arc};
|
||||
|
||||
pub struct WgpuRenderer {
|
||||
pub global_context: WgpuRenderContext<WgpuRenderResourceContext>,
|
||||
pub device: Arc<wgpu::Device>,
|
||||
pub queue: wgpu::Queue,
|
||||
pub window_resized_event_reader: EventReader<WindowResized>,
|
||||
pub window_created_event_reader: EventReader<WindowCreated>,
|
||||
@ -48,10 +46,7 @@ impl WgpuRenderer {
|
||||
.await;
|
||||
let device = Arc::new(device);
|
||||
WgpuRenderer {
|
||||
global_context: WgpuRenderContext::new(
|
||||
device.clone(),
|
||||
WgpuRenderResourceContext::new(device),
|
||||
),
|
||||
device,
|
||||
queue,
|
||||
window_resized_event_reader,
|
||||
window_created_event_reader,
|
||||
@ -61,8 +56,8 @@ impl WgpuRenderer {
|
||||
|
||||
pub fn initialize_resource_providers(
|
||||
world: &mut World,
|
||||
resources: &mut Resources,
|
||||
render_context: &mut WgpuRenderContext<WgpuRenderResourceContext>,
|
||||
resources: &Resources,
|
||||
render_context: &mut WgpuRenderContext,
|
||||
) {
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
for resource_provider in render_graph.resource_providers.iter_mut() {
|
||||
@ -74,8 +69,8 @@ impl WgpuRenderer {
|
||||
world: &World,
|
||||
resources: &Resources,
|
||||
device: Arc<wgpu::Device>,
|
||||
global_wgpu_resources: &WgpuResources,
|
||||
) -> (Vec<wgpu::CommandBuffer>, Vec<WgpuResources>) {
|
||||
render_resource_context: &WgpuRenderResourceContext,
|
||||
) -> Vec<wgpu::CommandBuffer> {
|
||||
let max_thread_count = 8;
|
||||
let (sender, receiver) = crossbeam_channel::bounded(max_thread_count);
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
@ -86,21 +81,15 @@ impl WgpuRenderer {
|
||||
crossbeam_utils::thread::scope(|s| {
|
||||
for resource_provider_chunk in render_graph.resource_providers.chunks_mut(chunk_size) {
|
||||
let device = device.clone();
|
||||
let resource_device = device.clone();
|
||||
let sender = sender.clone();
|
||||
let global_wgpu_resources = &*global_wgpu_resources;
|
||||
let world = &*world;
|
||||
let resources = &*resources;
|
||||
actual_thread_count += 1;
|
||||
// println!("spawn {}", resource_provider_chunk.len());
|
||||
let render_resource_context = render_resource_context.clone();
|
||||
s.spawn(move |_| {
|
||||
let mut render_context = WgpuRenderContext::new(
|
||||
device,
|
||||
WgpuTransactionalRenderResourceContext::new(
|
||||
resource_device,
|
||||
global_wgpu_resources,
|
||||
),
|
||||
);
|
||||
let mut render_context =
|
||||
WgpuRenderContext::new(device, render_resource_context);
|
||||
for resource_provider in resource_provider_chunk.iter_mut() {
|
||||
resource_provider.update(&mut render_context, world, resources);
|
||||
}
|
||||
@ -111,37 +100,28 @@ impl WgpuRenderer {
|
||||
.unwrap();
|
||||
|
||||
let mut command_buffers = Vec::new();
|
||||
let mut local_resources = Vec::new();
|
||||
for _i in 0..actual_thread_count {
|
||||
let (command_buffer, render_resources) = receiver.recv().unwrap();
|
||||
let command_buffer = receiver.recv().unwrap();
|
||||
if let Some(command_buffer) = command_buffer {
|
||||
command_buffers.push(command_buffer);
|
||||
}
|
||||
|
||||
local_resources.push(render_resources.local_resources);
|
||||
|
||||
// println!("got {}", i);
|
||||
}
|
||||
|
||||
(command_buffers, local_resources)
|
||||
command_buffers
|
||||
}
|
||||
|
||||
pub fn update_resource_providers(
|
||||
&mut self,
|
||||
world: &mut World,
|
||||
resources: &mut Resources,
|
||||
queue: &mut wgpu::Queue,
|
||||
device: Arc<wgpu::Device>,
|
||||
global_wgpu_resources: &mut WgpuResources,
|
||||
resources: &Resources,
|
||||
render_resource_context: &WgpuRenderResourceContext,
|
||||
) {
|
||||
let (mut command_buffers, local_resources) = Self::parallel_resource_provider_update(
|
||||
let mut command_buffers = Self::parallel_resource_provider_update(
|
||||
world,
|
||||
resources,
|
||||
device.clone(),
|
||||
global_wgpu_resources,
|
||||
self.device.clone(),
|
||||
render_resource_context,
|
||||
);
|
||||
for local_resource in local_resources {
|
||||
global_wgpu_resources.consume(local_resource);
|
||||
}
|
||||
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
let mut results = Vec::new();
|
||||
@ -150,15 +130,13 @@ impl WgpuRenderer {
|
||||
// crossbeam_utils::thread::scope(|s| {
|
||||
for resource_provider_chunk in render_graph.resource_providers.chunks_mut(chunk_size) {
|
||||
// TODO: try to unify this Device usage
|
||||
let device = device.clone();
|
||||
let device = self.device.clone();
|
||||
let resource_device = device.clone();
|
||||
// let sender = sender.clone();
|
||||
// s.spawn(|_| {
|
||||
// TODO: replace WgpuResources with Global+Local resources
|
||||
let mut render_context = WgpuRenderContext::new(
|
||||
device,
|
||||
WgpuTransactionalRenderResourceContext::new(resource_device, global_wgpu_resources),
|
||||
);
|
||||
let mut render_context =
|
||||
WgpuRenderContext::new(device, render_resource_context.clone());
|
||||
for resource_provider in resource_provider_chunk.iter_mut() {
|
||||
resource_provider.finish_update(&mut render_context, world, resources);
|
||||
}
|
||||
@ -168,42 +146,37 @@ impl WgpuRenderer {
|
||||
}
|
||||
// });
|
||||
|
||||
let mut local_resources = Vec::new();
|
||||
for (command_buffer, render_resources) in results {
|
||||
for command_buffer in results {
|
||||
// for i in 0..thread_count {
|
||||
// let (command_buffer, wgpu_resources) = receiver.recv().unwrap();
|
||||
if let Some(command_buffer) = command_buffer {
|
||||
command_buffers.push(command_buffer);
|
||||
}
|
||||
|
||||
local_resources.push(render_resources.local_resources);
|
||||
// println!("got {}", i);
|
||||
}
|
||||
for local_resource in local_resources {
|
||||
global_wgpu_resources.consume(local_resource);
|
||||
}
|
||||
|
||||
queue.submit(&command_buffers);
|
||||
self.queue.submit(&command_buffers);
|
||||
}
|
||||
|
||||
pub fn create_queued_textures(&mut self, resources: &mut Resources) {
|
||||
pub fn create_queued_textures(
|
||||
&mut self,
|
||||
resources: &Resources,
|
||||
global_render_resources: &mut WgpuRenderResourceContext,
|
||||
) {
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
let mut render_resource_assignments =
|
||||
resources.get_mut::<RenderResourceAssignments>().unwrap();
|
||||
for (name, texture_descriptor) in render_graph.queued_textures.drain(..) {
|
||||
let resource = self
|
||||
.global_context
|
||||
.resources_mut()
|
||||
.create_texture(&texture_descriptor);
|
||||
let resource = global_render_resources.create_texture(&texture_descriptor);
|
||||
render_resource_assignments.set(&name, resource);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_window_resized_events(
|
||||
resources: &mut Resources,
|
||||
device: &wgpu::Device,
|
||||
wgpu_resources: &mut WgpuResources,
|
||||
window_resized_event_reader: &mut EventReader<WindowResized>,
|
||||
&mut self,
|
||||
resources: &Resources,
|
||||
global_render_resources: &mut WgpuRenderResourceContext,
|
||||
) {
|
||||
let windows = resources.get::<Windows>().unwrap();
|
||||
let window_resized_events = resources.get::<Events<WindowResized>>().unwrap();
|
||||
@ -211,7 +184,7 @@ impl WgpuRenderer {
|
||||
// iterate in reverse order so we can handle the latest window resize event first for each window.
|
||||
// we skip earlier events for the same window because it results in redundant work
|
||||
for window_resized_event in window_resized_events
|
||||
.iter(window_resized_event_reader)
|
||||
.iter(&mut self.window_resized_event_reader)
|
||||
.rev()
|
||||
{
|
||||
if handled_windows.contains(&window_resized_event.id) {
|
||||
@ -223,21 +196,22 @@ impl WgpuRenderer {
|
||||
.expect("Received window resized event for non-existent window");
|
||||
|
||||
// TODO: consider making this a WgpuRenderContext method
|
||||
wgpu_resources.create_window_swap_chain(device, window);
|
||||
global_render_resources.create_swap_chain(window);
|
||||
|
||||
handled_windows.insert(window_resized_event.id);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_window_created_events(
|
||||
resources: &mut Resources,
|
||||
device: &wgpu::Device,
|
||||
wgpu_resources: &mut WgpuResources,
|
||||
window_created_event_reader: &mut EventReader<WindowCreated>,
|
||||
&mut self,
|
||||
resources: &Resources,
|
||||
global_render_resource_context: &mut WgpuRenderResourceContext,
|
||||
) {
|
||||
let windows = resources.get::<Windows>().unwrap();
|
||||
let window_created_events = resources.get::<Events<WindowCreated>>().unwrap();
|
||||
for window_created_event in window_created_events.iter(window_created_event_reader) {
|
||||
for window_created_event in
|
||||
window_created_events.iter(&mut self.window_created_event_reader)
|
||||
{
|
||||
let window = windows
|
||||
.get(window_created_event.id)
|
||||
.expect("Received window created event for non-existent window");
|
||||
@ -246,49 +220,81 @@ impl WgpuRenderer {
|
||||
let winit_windows = resources.get::<bevy_winit::WinitWindows>().unwrap();
|
||||
let primary_winit_window = winit_windows.get_window(window.id).unwrap();
|
||||
let surface = wgpu::Surface::create(primary_winit_window.deref());
|
||||
wgpu_resources.set_window_surface(window.id, surface);
|
||||
wgpu_resources.create_window_swap_chain(device, window);
|
||||
global_render_resource_context
|
||||
.wgpu_resources
|
||||
.set_window_surface(window.id, surface);
|
||||
global_render_resource_context.create_swap_chain(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_global_render_resource_context(&self, resources: &mut Resources) {
|
||||
resources.insert(GlobalRenderResourceContext::new(
|
||||
WgpuRenderResourceContext::new(self.device.clone()),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn update(&mut self, world: &mut World, resources: &mut Resources) {
|
||||
Self::handle_window_created_events(
|
||||
resources,
|
||||
&self.global_context.device,
|
||||
&mut self.global_context.render_resources.wgpu_resources,
|
||||
&mut self.window_created_event_reader,
|
||||
);
|
||||
Self::handle_window_resized_events(
|
||||
resources,
|
||||
&self.global_context.device,
|
||||
&mut self.global_context.render_resources.wgpu_resources,
|
||||
&mut self.window_resized_event_reader,
|
||||
);
|
||||
if !self.intialized {
|
||||
Self::initialize_resource_providers(world, resources, &mut self.global_context);
|
||||
let buffer = self.global_context.finish_encoder();
|
||||
if let Some(buffer) = buffer {
|
||||
self.queue.submit(&[buffer]);
|
||||
}
|
||||
self.intialized = true;
|
||||
self.create_global_render_resource_context(resources);
|
||||
}
|
||||
|
||||
Self::update_resource_providers(
|
||||
world,
|
||||
resources,
|
||||
&mut self.queue,
|
||||
self.global_context.device.clone(),
|
||||
&mut self.global_context.render_resources.wgpu_resources,
|
||||
);
|
||||
let mut encoder = {
|
||||
let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap();
|
||||
let mut any_context = (&mut global_context.context) as &mut dyn Any;
|
||||
// let mut any_context = (&mut global_context.context);
|
||||
// println!("{}", std::any::type_name_of_val(any_context));
|
||||
let mut render_resource_context = any_context
|
||||
.downcast_mut::<WgpuRenderResourceContext>()
|
||||
.unwrap();
|
||||
panic!("ahh");
|
||||
|
||||
update_shader_assignments(world, resources, &self.global_context);
|
||||
self.create_queued_textures(resources);
|
||||
// let mut render_resource_context = any_context
|
||||
// .downcast_mut::<WgpuRenderResourceContext>()
|
||||
// .unwrap();
|
||||
self.handle_window_created_events(resources, render_resource_context);
|
||||
|
||||
self.handle_window_resized_events(resources, render_resource_context);
|
||||
let mut render_context =
|
||||
WgpuRenderContext::new(self.device.clone(), render_resource_context.clone());
|
||||
if !self.intialized {
|
||||
Self::initialize_resource_providers(world, resources, &mut render_context);
|
||||
let buffer = render_context.finish();
|
||||
if let Some(buffer) = buffer {
|
||||
self.queue.submit(&[buffer]);
|
||||
}
|
||||
self.intialized = true;
|
||||
}
|
||||
|
||||
self.update_resource_providers(
|
||||
world,
|
||||
resources,
|
||||
render_resource_context,
|
||||
);
|
||||
|
||||
update_shader_assignments(world, resources, &render_context);
|
||||
self.create_queued_textures(resources, &mut render_context.render_resources);
|
||||
render_context.command_encoder.take()
|
||||
};
|
||||
|
||||
// TODO: add to POST_UPDATE and remove redundant global_context
|
||||
render_resource_sets_system().run(world, resources);
|
||||
let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap();
|
||||
let mut any_context = (&mut global_context.context) as &mut dyn Any;
|
||||
// let mut any_context = (&mut global_context.context);
|
||||
// println!("{}", std::any::type_name_of_val(any_context));
|
||||
let mut render_resource_context = any_context
|
||||
.downcast_mut::<WgpuRenderResourceContext>()
|
||||
.unwrap();
|
||||
let mut render_context =
|
||||
WgpuRenderContext::new(self.device.clone(), render_resource_context.clone());
|
||||
if let Some(command_encoder) = encoder.take() {
|
||||
render_context.command_encoder.set(command_encoder);
|
||||
}
|
||||
|
||||
// setup draw targets
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
render_graph.setup_pipeline_draw_targets(world, resources, &mut self.global_context);
|
||||
render_graph.setup_pipeline_draw_targets(world, resources, &mut render_context);
|
||||
|
||||
// get next swap chain texture on primary window
|
||||
let primary_window_id = resources
|
||||
@ -297,10 +303,10 @@ impl WgpuRenderer {
|
||||
.get_primary()
|
||||
.map(|window| window.id);
|
||||
if let Some(primary_window_id) = primary_window_id {
|
||||
self.global_context
|
||||
render_context
|
||||
.render_resources
|
||||
.next_swap_chain_texture(primary_window_id);
|
||||
self.global_context.primary_window = Some(primary_window_id);
|
||||
render_context.primary_window = Some(primary_window_id);
|
||||
}
|
||||
|
||||
// begin render passes
|
||||
@ -310,7 +316,7 @@ impl WgpuRenderer {
|
||||
for (pass_name, pass_descriptor) in render_graph.pass_descriptors.iter() {
|
||||
let global_render_resource_assignments =
|
||||
resources.get::<RenderResourceAssignments>().unwrap();
|
||||
self.global_context.begin_pass(
|
||||
render_context.begin_pass(
|
||||
pass_descriptor,
|
||||
&global_render_resource_assignments,
|
||||
&mut |render_pass| {
|
||||
@ -346,14 +352,14 @@ impl WgpuRenderer {
|
||||
);
|
||||
}
|
||||
|
||||
let command_buffer = self.global_context.finish_encoder();
|
||||
let command_buffer = render_context.finish();
|
||||
if let Some(command_buffer) = command_buffer {
|
||||
self.queue.submit(&[command_buffer]);
|
||||
}
|
||||
|
||||
// clear primary swap chain texture
|
||||
if let Some(primary_window_id) = primary_window_id {
|
||||
self.global_context
|
||||
render_context
|
||||
.render_resources
|
||||
.drop_swap_chain_texture(primary_window_id);
|
||||
}
|
||||
|
||||
@ -1,7 +1,4 @@
|
||||
use crate::{
|
||||
renderer_2::{WgpuRenderResourceContext, WgpuTransactionalRenderResourceContext},
|
||||
wgpu_type_converter::WgpuInto,
|
||||
};
|
||||
use crate::{renderer_2::WgpuRenderResourceContext, wgpu_type_converter::WgpuInto};
|
||||
use bevy_asset::Handle;
|
||||
use bevy_render::{
|
||||
pipeline::{BindGroupDescriptorId, PipelineDescriptor},
|
||||
@ -13,85 +10,94 @@ use bevy_render::{
|
||||
texture::{SamplerDescriptor, TextureDescriptor},
|
||||
};
|
||||
use bevy_window::{Window, WindowId};
|
||||
use std::collections::HashMap;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, RwLock, RwLockReadGuard},
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct WgpuBindGroupInfo {
|
||||
pub bind_groups: HashMap<RenderResourceSetId, wgpu::BindGroup>,
|
||||
}
|
||||
|
||||
pub struct WgpuResourcesReadLock<'a> {
|
||||
pub buffers: RwLockReadGuard<'a, HashMap<RenderResource, wgpu::Buffer>>,
|
||||
pub textures: RwLockReadGuard<'a, HashMap<RenderResource, wgpu::TextureView>>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct WgpuResources {
|
||||
// TODO: remove this from WgpuResources. it doesn't need to be here
|
||||
pub asset_resources: AssetResources,
|
||||
pub window_surfaces: HashMap<WindowId, wgpu::Surface>,
|
||||
pub window_swap_chains: HashMap<WindowId, wgpu::SwapChain>,
|
||||
pub swap_chain_outputs: HashMap<WindowId, wgpu::SwapChainOutput>,
|
||||
pub buffers: HashMap<RenderResource, wgpu::Buffer>,
|
||||
pub textures: HashMap<RenderResource, wgpu::TextureView>,
|
||||
pub samplers: HashMap<RenderResource, wgpu::Sampler>,
|
||||
pub resource_info: HashMap<RenderResource, ResourceInfo>,
|
||||
pub shader_modules: HashMap<Handle<Shader>, wgpu::ShaderModule>,
|
||||
pub render_pipelines: HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>,
|
||||
pub bind_groups: HashMap<BindGroupDescriptorId, WgpuBindGroupInfo>,
|
||||
pub bind_group_layouts: HashMap<BindGroupDescriptorId, wgpu::BindGroupLayout>,
|
||||
pub window_surfaces: Arc<RwLock<HashMap<WindowId, wgpu::Surface>>>,
|
||||
pub window_swap_chains: Arc<RwLock<HashMap<WindowId, wgpu::SwapChain>>>,
|
||||
pub swap_chain_outputs: Arc<RwLock<HashMap<WindowId, wgpu::SwapChainOutput>>>,
|
||||
pub buffers: Arc<RwLock<HashMap<RenderResource, wgpu::Buffer>>>,
|
||||
pub textures: Arc<RwLock<HashMap<RenderResource, wgpu::TextureView>>>,
|
||||
pub samplers: Arc<RwLock<HashMap<RenderResource, wgpu::Sampler>>>,
|
||||
pub resource_info: Arc<RwLock<HashMap<RenderResource, ResourceInfo>>>,
|
||||
pub shader_modules: Arc<RwLock<HashMap<Handle<Shader>, wgpu::ShaderModule>>>,
|
||||
pub render_pipelines: Arc<RwLock<HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>>>,
|
||||
pub bind_groups: Arc<RwLock<HashMap<BindGroupDescriptorId, WgpuBindGroupInfo>>>,
|
||||
pub bind_group_layouts: Arc<RwLock<HashMap<BindGroupDescriptorId, wgpu::BindGroupLayout>>>,
|
||||
}
|
||||
|
||||
impl WgpuResources {
|
||||
pub fn consume(&mut self, wgpu_resources: WgpuResources) {
|
||||
// TODO: this is brittle. consider a single change-stream-based approach instead?
|
||||
self.asset_resources.consume(wgpu_resources.asset_resources);
|
||||
self.window_surfaces.extend(wgpu_resources.window_surfaces);
|
||||
self.window_swap_chains
|
||||
.extend(wgpu_resources.window_swap_chains);
|
||||
self.swap_chain_outputs
|
||||
.extend(wgpu_resources.swap_chain_outputs);
|
||||
self.buffers.extend(wgpu_resources.buffers);
|
||||
self.textures.extend(wgpu_resources.textures);
|
||||
self.samplers.extend(wgpu_resources.samplers);
|
||||
self.resource_info.extend(wgpu_resources.resource_info);
|
||||
self.shader_modules.extend(wgpu_resources.shader_modules);
|
||||
self.render_pipelines.extend(wgpu_resources.render_pipelines);
|
||||
self.bind_groups.extend(wgpu_resources.bind_groups);
|
||||
self.bind_group_layouts
|
||||
.extend(wgpu_resources.bind_group_layouts);
|
||||
pub fn read(&self) -> WgpuResourcesReadLock {
|
||||
WgpuResourcesReadLock {
|
||||
buffers: self.buffers.read().unwrap(),
|
||||
textures: self.textures.read().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_window_surface(&self, window_id: WindowId, surface: wgpu::Surface) {
|
||||
self.window_surfaces
|
||||
.write()
|
||||
.unwrap()
|
||||
.insert(window_id, surface);
|
||||
}
|
||||
|
||||
pub fn set_window_surface(&mut self, window_id: WindowId, surface: wgpu::Surface) {
|
||||
self.window_surfaces.insert(window_id, surface);
|
||||
}
|
||||
|
||||
pub fn get_window_surface(&mut self, window_id: WindowId) -> Option<&wgpu::Surface> {
|
||||
self.window_surfaces.get(&window_id)
|
||||
}
|
||||
|
||||
pub fn next_swap_chain_texture(&mut self, window_id: WindowId) -> Option<&wgpu::SwapChainOutput> {
|
||||
let swap_chain_output = self.window_swap_chains.get_mut(&window_id).unwrap();
|
||||
pub fn next_swap_chain_texture(&self, window_id: WindowId) {
|
||||
let mut swap_chain_outputs = self
|
||||
.window_swap_chains
|
||||
.write()
|
||||
.unwrap();
|
||||
let swap_chain_output = swap_chain_outputs
|
||||
.get_mut(&window_id)
|
||||
.unwrap();
|
||||
let next_texture = swap_chain_output.get_next_texture().unwrap();
|
||||
self.swap_chain_outputs.insert(window_id, next_texture);
|
||||
self.swap_chain_outputs.get(&window_id)
|
||||
self.swap_chain_outputs
|
||||
.write()
|
||||
.unwrap()
|
||||
.insert(window_id, next_texture);
|
||||
}
|
||||
|
||||
pub fn remove_swap_chain_texture(&mut self, window_id: WindowId) {
|
||||
self.swap_chain_outputs.remove(&window_id);
|
||||
pub fn remove_swap_chain_texture(&self, window_id: WindowId) {
|
||||
self.swap_chain_outputs.write().unwrap().remove(&window_id);
|
||||
}
|
||||
|
||||
pub fn remove_all_swap_chain_textures(&mut self) {
|
||||
self.swap_chain_outputs.clear();
|
||||
pub fn remove_all_swap_chain_textures(&self) {
|
||||
self.swap_chain_outputs.write().unwrap().clear();
|
||||
}
|
||||
|
||||
pub fn create_window_swap_chain(&mut self, device: &wgpu::Device, window: &Window) {
|
||||
pub fn create_window_swap_chain(&self, device: &wgpu::Device, window: &Window) {
|
||||
let swap_chain_descriptor: wgpu::SwapChainDescriptor = window.wgpu_into();
|
||||
let surface = self
|
||||
.window_surfaces
|
||||
let surfaces = self.window_surfaces.read().unwrap();
|
||||
let surface = surfaces
|
||||
.get(&window.id)
|
||||
.expect("No surface found for window");
|
||||
let swap_chain = device.create_swap_chain(surface, &swap_chain_descriptor);
|
||||
self.window_swap_chains.insert(window.id, swap_chain);
|
||||
self.window_swap_chains
|
||||
.write()
|
||||
.unwrap()
|
||||
.insert(window.id, swap_chain);
|
||||
}
|
||||
|
||||
pub fn add_resource_info(&mut self, resource: RenderResource, resource_info: ResourceInfo) {
|
||||
self.resource_info.insert(resource, resource_info);
|
||||
pub fn add_resource_info(&self, resource: RenderResource, resource_info: ResourceInfo) {
|
||||
self.resource_info
|
||||
.write()
|
||||
.unwrap()
|
||||
.insert(resource, resource_info);
|
||||
}
|
||||
|
||||
pub fn get_bind_group(
|
||||
@ -99,7 +105,12 @@ impl WgpuResources {
|
||||
bind_group_descriptor_id: BindGroupDescriptorId,
|
||||
render_resource_set_id: RenderResourceSetId,
|
||||
) -> Option<&wgpu::BindGroup> {
|
||||
if let Some(bind_group_info) = self.bind_groups.get(&bind_group_descriptor_id) {
|
||||
if let Some(bind_group_info) = self
|
||||
.bind_groups
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(&bind_group_descriptor_id)
|
||||
{
|
||||
bind_group_info.bind_groups.get(&render_resource_set_id)
|
||||
} else {
|
||||
None
|
||||
@ -121,13 +132,16 @@ impl WgpuResources {
|
||||
}
|
||||
|
||||
pub fn set_bind_group(
|
||||
&mut self,
|
||||
&self,
|
||||
bind_group_descriptor_id: BindGroupDescriptorId,
|
||||
render_resource_set_id: RenderResourceSetId,
|
||||
bind_group: wgpu::BindGroup,
|
||||
) {
|
||||
let bind_group_info = self
|
||||
let mut bind_groups = self
|
||||
.bind_groups
|
||||
.write()
|
||||
.unwrap();
|
||||
let bind_group_info = bind_groups
|
||||
.entry(bind_group_descriptor_id)
|
||||
.or_insert_with(|| WgpuBindGroupInfo::default());
|
||||
bind_group_info
|
||||
@ -135,11 +149,7 @@ impl WgpuResources {
|
||||
.insert(render_resource_set_id, bind_group);
|
||||
}
|
||||
|
||||
pub fn create_buffer(
|
||||
&mut self,
|
||||
device: &wgpu::Device,
|
||||
buffer_info: BufferInfo,
|
||||
) -> RenderResource {
|
||||
pub fn create_buffer(&self, device: &wgpu::Device, buffer_info: BufferInfo) -> RenderResource {
|
||||
let buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: None,
|
||||
size: buffer_info.size as u64,
|
||||
@ -149,12 +159,12 @@ impl WgpuResources {
|
||||
let resource = RenderResource::new();
|
||||
self.add_resource_info(resource, ResourceInfo::Buffer(buffer_info));
|
||||
|
||||
self.buffers.insert(resource, buffer);
|
||||
self.buffers.write().unwrap().insert(resource, buffer);
|
||||
resource
|
||||
}
|
||||
|
||||
pub fn create_buffer_with_data(
|
||||
&mut self,
|
||||
&self,
|
||||
device: &wgpu::Device,
|
||||
mut buffer_info: BufferInfo,
|
||||
data: &[u8],
|
||||
@ -165,22 +175,18 @@ impl WgpuResources {
|
||||
}
|
||||
|
||||
pub fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> {
|
||||
self.resource_info.get(&resource)
|
||||
self.resource_info.read().unwrap().get(&resource)
|
||||
}
|
||||
|
||||
pub fn remove_buffer(&mut self, resource: RenderResource) {
|
||||
self.buffers.remove(&resource);
|
||||
self.resource_info.remove(&resource);
|
||||
pub fn remove_buffer(&self, resource: RenderResource) {
|
||||
self.buffers.write().unwrap().remove(&resource);
|
||||
self.resource_info.write().unwrap().remove(&resource);
|
||||
}
|
||||
|
||||
pub fn assign_buffer(
|
||||
&mut self,
|
||||
buffer: wgpu::Buffer,
|
||||
buffer_info: BufferInfo,
|
||||
) -> RenderResource {
|
||||
pub fn assign_buffer(&self, buffer: wgpu::Buffer, buffer_info: BufferInfo) -> RenderResource {
|
||||
let resource = RenderResource::new();
|
||||
self.add_resource_info(resource, ResourceInfo::Buffer(buffer_info));
|
||||
self.buffers.insert(resource, buffer);
|
||||
self.buffers.write().unwrap().insert(resource, buffer);
|
||||
resource
|
||||
}
|
||||
|
||||
@ -200,23 +206,8 @@ impl WgpuResources {
|
||||
mapped.finish()
|
||||
}
|
||||
|
||||
pub fn begin_create_buffer_mapped_transactional_render_context(
|
||||
buffer_info: &BufferInfo,
|
||||
render_resources: &mut WgpuTransactionalRenderResourceContext,
|
||||
setup_data: &mut dyn FnMut(&mut [u8], &mut dyn RenderResourceContext),
|
||||
) -> wgpu::Buffer {
|
||||
let device = render_resources.device.clone();
|
||||
let mut mapped = device.create_buffer_mapped(&wgpu::BufferDescriptor {
|
||||
size: buffer_info.size as u64,
|
||||
usage: buffer_info.buffer_usage.wgpu_into(),
|
||||
label: None,
|
||||
});
|
||||
setup_data(&mut mapped.data, render_resources);
|
||||
mapped.finish()
|
||||
}
|
||||
|
||||
pub fn copy_buffer_to_buffer(
|
||||
&mut self,
|
||||
&self,
|
||||
encoder: &mut wgpu::CommandEncoder,
|
||||
source_buffer: RenderResource,
|
||||
source_offset: u64,
|
||||
@ -224,36 +215,40 @@ impl WgpuResources {
|
||||
destination_offset: u64,
|
||||
size: u64,
|
||||
) {
|
||||
let source = self.buffers.get(&source_buffer).unwrap();
|
||||
let destination = self.buffers.get(&destination_buffer).unwrap();
|
||||
let buffers = self.buffers.read().unwrap();
|
||||
let source = buffers.get(&source_buffer).unwrap();
|
||||
let destination = buffers.get(&destination_buffer).unwrap();
|
||||
encoder.copy_buffer_to_buffer(source, source_offset, destination, destination_offset, size);
|
||||
}
|
||||
|
||||
pub fn create_shader_module(
|
||||
&mut self,
|
||||
&self,
|
||||
device: &wgpu::Device,
|
||||
shader_handle: Handle<Shader>,
|
||||
shader: &Shader,
|
||||
) {
|
||||
let shader_module = device.create_shader_module(&shader.get_spirv(None));
|
||||
self.shader_modules.insert(shader_handle, shader_module);
|
||||
self.shader_modules
|
||||
.write()
|
||||
.unwrap()
|
||||
.insert(shader_handle, shader_module);
|
||||
}
|
||||
|
||||
pub fn create_sampler(
|
||||
&mut self,
|
||||
&self,
|
||||
device: &wgpu::Device,
|
||||
sampler_descriptor: &SamplerDescriptor,
|
||||
) -> RenderResource {
|
||||
let descriptor: wgpu::SamplerDescriptor = (*sampler_descriptor).wgpu_into();
|
||||
let sampler = device.create_sampler(&descriptor);
|
||||
let resource = RenderResource::new();
|
||||
self.samplers.insert(resource, sampler);
|
||||
self.samplers.write().unwrap().insert(resource, sampler);
|
||||
self.add_resource_info(resource, ResourceInfo::Sampler);
|
||||
resource
|
||||
}
|
||||
|
||||
pub fn create_texture(
|
||||
&mut self,
|
||||
&self,
|
||||
device: &wgpu::Device,
|
||||
texture_descriptor: &TextureDescriptor,
|
||||
) -> RenderResource {
|
||||
@ -262,12 +257,15 @@ impl WgpuResources {
|
||||
let texture_view = texture.create_default_view();
|
||||
let resource = RenderResource::new();
|
||||
self.add_resource_info(resource, ResourceInfo::Texture);
|
||||
self.textures.insert(resource, texture_view);
|
||||
self.textures
|
||||
.write()
|
||||
.unwrap()
|
||||
.insert(resource, texture_view);
|
||||
resource
|
||||
}
|
||||
|
||||
pub fn create_texture_with_data(
|
||||
&mut self,
|
||||
&self,
|
||||
device: &wgpu::Device,
|
||||
encoder: &mut wgpu::CommandEncoder,
|
||||
texture_descriptor: &TextureDescriptor,
|
||||
@ -295,18 +293,21 @@ impl WgpuResources {
|
||||
|
||||
let resource = RenderResource::new();
|
||||
self.add_resource_info(resource, ResourceInfo::Texture);
|
||||
self.textures.insert(resource, texture_view);
|
||||
self.textures
|
||||
.write()
|
||||
.unwrap()
|
||||
.insert(resource, texture_view);
|
||||
resource
|
||||
}
|
||||
|
||||
pub fn remove_texture(&mut self, resource: RenderResource) {
|
||||
self.textures.remove(&resource);
|
||||
self.resource_info.remove(&resource);
|
||||
pub fn remove_texture(&self, resource: RenderResource) {
|
||||
self.textures.write().unwrap().remove(&resource);
|
||||
self.resource_info.write().unwrap().remove(&resource);
|
||||
}
|
||||
|
||||
pub fn remove_sampler(&mut self, resource: RenderResource) {
|
||||
self.samplers.remove(&resource);
|
||||
self.resource_info.remove(&resource);
|
||||
pub fn remove_sampler(&self, resource: RenderResource) {
|
||||
self.samplers.write().unwrap().remove(&resource);
|
||||
self.resource_info.write().unwrap().remove(&resource);
|
||||
}
|
||||
|
||||
pub fn get_render_resources(&self) -> &AssetResources {
|
||||
@ -318,13 +319,15 @@ impl WgpuResources {
|
||||
}
|
||||
|
||||
pub fn create_bind_group_layout(
|
||||
&mut self,
|
||||
&self,
|
||||
device: &wgpu::Device,
|
||||
bind_group_id: BindGroupDescriptorId,
|
||||
descriptor: &wgpu::BindGroupLayoutDescriptor,
|
||||
) {
|
||||
let wgpu_bind_group_layout = device.create_bind_group_layout(descriptor);
|
||||
self.bind_group_layouts
|
||||
.write()
|
||||
.unwrap()
|
||||
.insert(bind_group_id, wgpu_bind_group_layout);
|
||||
}
|
||||
|
||||
@ -337,11 +340,13 @@ impl WgpuResources {
|
||||
}
|
||||
|
||||
pub fn set_render_pipeline(
|
||||
&mut self,
|
||||
&self,
|
||||
pipeline_handle: Handle<PipelineDescriptor>,
|
||||
render_pipeline: wgpu::RenderPipeline,
|
||||
) {
|
||||
self.render_pipelines
|
||||
.write()
|
||||
.unwrap()
|
||||
.insert(pipeline_handle, render_pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user