simplify / consolidate wgpu resource mangement
This commit is contained in:
parent
012a33ed32
commit
0d87ebe866
@ -101,7 +101,7 @@ impl DrawTarget for AssignedMeshesDrawTarget {
|
|||||||
pipeline_assignments.assignments.get(&pipeline_handle);
|
pipeline_assignments.assignments.get(&pipeline_handle);
|
||||||
let global_render_resource_assignments =
|
let global_render_resource_assignments =
|
||||||
resources.get::<RenderResourceAssignments>().unwrap();
|
resources.get::<RenderResourceAssignments>().unwrap();
|
||||||
render_context.setup_bind_groups(pipeline_descriptor, &global_render_resource_assignments);
|
render_context.resources().setup_bind_groups(pipeline_descriptor, &global_render_resource_assignments);
|
||||||
if let Some(assigned_render_resource_assignments) = assigned_render_resource_assignments {
|
if let Some(assigned_render_resource_assignments) = assigned_render_resource_assignments {
|
||||||
for assignment_id in assigned_render_resource_assignments.iter() {
|
for assignment_id in assigned_render_resource_assignments.iter() {
|
||||||
let entity = entity_render_resource_assignments
|
let entity = entity_render_resource_assignments
|
||||||
@ -112,7 +112,7 @@ impl DrawTarget for AssignedMeshesDrawTarget {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
render_context.setup_bind_groups(
|
render_context.resources().setup_bind_groups(
|
||||||
pipeline_descriptor,
|
pipeline_descriptor,
|
||||||
&renderable.render_resource_assignments,
|
&renderable.render_resource_assignments,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
mod assigned_meshes_draw_target;
|
mod assigned_meshes_draw_target;
|
||||||
mod meshes_draw_target;
|
mod meshes_draw_target;
|
||||||
mod ui_draw_target;
|
|
||||||
|
|
||||||
pub use assigned_meshes_draw_target::*;
|
pub use assigned_meshes_draw_target::*;
|
||||||
pub use meshes_draw_target::*;
|
pub use meshes_draw_target::*;
|
||||||
pub use ui_draw_target::*;
|
|
||||||
|
|||||||
@ -1,126 +0,0 @@
|
|||||||
use crate::{
|
|
||||||
draw_target::DrawTarget,
|
|
||||||
mesh::{shape::Quad, Mesh},
|
|
||||||
pass::RenderPass,
|
|
||||||
pipeline::PipelineDescriptor,
|
|
||||||
render_resource::{
|
|
||||||
resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments,
|
|
||||||
ResourceInfo,
|
|
||||||
},
|
|
||||||
renderer::RenderContext,
|
|
||||||
};
|
|
||||||
use bevy_asset::Handle;
|
|
||||||
use legion::prelude::*;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct UiDrawTarget {
|
|
||||||
pub mesh_vertex_buffer: Option<RenderResource>,
|
|
||||||
pub mesh_index_buffer: Option<RenderResource>,
|
|
||||||
pub mesh_index_length: usize,
|
|
||||||
pub mesh: Option<Handle<Mesh>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DrawTarget for UiDrawTarget {
|
|
||||||
fn draw(
|
|
||||||
&self,
|
|
||||||
_world: &World,
|
|
||||||
resources: &Resources,
|
|
||||||
render_pass: &mut dyn RenderPass,
|
|
||||||
_pipeline_handle: Handle<PipelineDescriptor>,
|
|
||||||
pipeline_descriptor: &PipelineDescriptor,
|
|
||||||
) {
|
|
||||||
let render_resource_assignments = resources.get::<RenderResourceAssignments>().unwrap();
|
|
||||||
let ui_instances_buffer = {
|
|
||||||
match render_resource_assignments.get(resource_name::buffer::UI_INSTANCES) {
|
|
||||||
Some(buffer) => buffer,
|
|
||||||
None => return,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let index_count = {
|
|
||||||
let mut index_count = None;
|
|
||||||
let render_context = render_pass.get_render_context();
|
|
||||||
render_context.resources().get_resource_info(
|
|
||||||
ui_instances_buffer,
|
|
||||||
&mut |resource_info| {
|
|
||||||
if let Some(ResourceInfo::Buffer(BufferInfo {
|
|
||||||
array_info: Some(array_info),
|
|
||||||
..
|
|
||||||
})) = resource_info
|
|
||||||
{
|
|
||||||
index_count = Some(array_info.item_capacity);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
index_count
|
|
||||||
};
|
|
||||||
|
|
||||||
let global_render_resource_assignments =
|
|
||||||
resources.get::<RenderResourceAssignments>().unwrap();
|
|
||||||
render_pass.set_render_resources(pipeline_descriptor, &global_render_resource_assignments);
|
|
||||||
render_pass.set_index_buffer(self.mesh_index_buffer.unwrap(), 0);
|
|
||||||
render_pass.set_vertex_buffer(0, self.mesh_vertex_buffer.unwrap(), 0);
|
|
||||||
render_pass.set_vertex_buffer(1, ui_instances_buffer, 0);
|
|
||||||
render_pass.draw_indexed(
|
|
||||||
0..self.mesh_index_length as u32,
|
|
||||||
0,
|
|
||||||
0..(index_count.unwrap() as u32),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn setup(
|
|
||||||
&mut self,
|
|
||||||
_world: &World,
|
|
||||||
resources: &Resources,
|
|
||||||
render_context: &mut dyn RenderContext,
|
|
||||||
_pipeline_handle: Handle<PipelineDescriptor>,
|
|
||||||
pipeline_descriptor: &PipelineDescriptor,
|
|
||||||
) {
|
|
||||||
// don't create meshes if they have already been created
|
|
||||||
if let Some(_) = self.mesh_vertex_buffer {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let quad = Mesh::from(Quad {
|
|
||||||
size: glam::vec2(1.0, 1.0),
|
|
||||||
});
|
|
||||||
let vertex_buffer_bytes = quad
|
|
||||||
.get_vertex_buffer_bytes(
|
|
||||||
pipeline_descriptor
|
|
||||||
.get_layout()
|
|
||||||
.unwrap()
|
|
||||||
.vertex_buffer_descriptors
|
|
||||||
.first()
|
|
||||||
.as_ref()
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
self.mesh_vertex_buffer = Some(render_context.resources_mut().create_buffer_with_data(
|
|
||||||
BufferInfo {
|
|
||||||
buffer_usage: BufferUsage::VERTEX,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
&vertex_buffer_bytes,
|
|
||||||
));
|
|
||||||
|
|
||||||
let index_buffer_bytes = quad
|
|
||||||
.get_index_buffer_bytes(pipeline_descriptor.index_format)
|
|
||||||
.unwrap();
|
|
||||||
self.mesh_index_buffer = Some(render_context.resources_mut().create_buffer_with_data(
|
|
||||||
BufferInfo {
|
|
||||||
buffer_usage: BufferUsage::INDEX,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
&index_buffer_bytes,
|
|
||||||
));
|
|
||||||
|
|
||||||
self.mesh_index_length = quad.indices.as_ref().unwrap().len();
|
|
||||||
|
|
||||||
let global_render_resource_assignments =
|
|
||||||
resources.get::<RenderResourceAssignments>().unwrap();
|
|
||||||
render_context.setup_bind_groups(pipeline_descriptor, &global_render_resource_assignments);
|
|
||||||
}
|
|
||||||
fn get_name(&self) -> String {
|
|
||||||
resource_name::draw_target::UI.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -114,7 +114,7 @@ impl Node for PassNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render_context.create_render_pipeline(
|
render_context.resources().create_render_pipeline(
|
||||||
*compiled_pipeline_handle,
|
*compiled_pipeline_handle,
|
||||||
&compiled_pipeline_descriptor,
|
&compiled_pipeline_descriptor,
|
||||||
&shader_storage,
|
&shader_storage,
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
use super::RenderResourceContext;
|
use super::RenderResourceContext;
|
||||||
use crate::{
|
use crate::{
|
||||||
render_resource::{BufferInfo, RenderResource, ResourceInfo},
|
pipeline::{BindGroupDescriptor, PipelineDescriptor},
|
||||||
|
render_resource::{
|
||||||
|
BufferInfo, RenderResource, RenderResourceAssignments, RenderResourceSetId, ResourceInfo,
|
||||||
|
},
|
||||||
shader::Shader,
|
shader::Shader,
|
||||||
texture::{SamplerDescriptor, TextureDescriptor},
|
texture::{SamplerDescriptor, TextureDescriptor},
|
||||||
};
|
};
|
||||||
@ -63,7 +66,7 @@ impl RenderResourceContext for HeadlessRenderResourceContext {
|
|||||||
resource
|
resource
|
||||||
}
|
}
|
||||||
fn create_shader_module(
|
fn create_shader_module(
|
||||||
&mut self,
|
&self,
|
||||||
_shader_handle: Handle<Shader>,
|
_shader_handle: Handle<Shader>,
|
||||||
_shader_storage: &AssetStorage<Shader>,
|
_shader_storage: &AssetStorage<Shader>,
|
||||||
) {
|
) {
|
||||||
@ -106,4 +109,24 @@ impl RenderResourceContext for HeadlessRenderResourceContext {
|
|||||||
.get(&(handle, index))
|
.get(&(handle, index))
|
||||||
.cloned()
|
.cloned()
|
||||||
}
|
}
|
||||||
|
fn create_render_pipeline(
|
||||||
|
&self,
|
||||||
|
_pipeline_handle: Handle<PipelineDescriptor>,
|
||||||
|
_pipeline_descriptor: &PipelineDescriptor,
|
||||||
|
_shader_storage: &AssetStorage<Shader>,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
fn create_bind_group(
|
||||||
|
&self,
|
||||||
|
bind_group_descriptor: &BindGroupDescriptor,
|
||||||
|
render_resource_assignments: &RenderResourceAssignments,
|
||||||
|
) -> Option<RenderResourceSetId> {
|
||||||
|
if let Some((render_resource_set_id, _indices)) =
|
||||||
|
render_resource_assignments.get_render_resource_set_id(bind_group_descriptor.id)
|
||||||
|
{
|
||||||
|
Some(*render_resource_set_id)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,9 @@
|
|||||||
use super::RenderResourceContext;
|
use super::RenderResourceContext;
|
||||||
use crate::{
|
use crate::{
|
||||||
pass::{PassDescriptor, RenderPass},
|
pass::{PassDescriptor, RenderPass},
|
||||||
pipeline::{BindGroupDescriptor, PipelineDescriptor},
|
render_resource::{RenderResource, RenderResourceAssignments},
|
||||||
render_resource::{RenderResource, RenderResourceAssignments, RenderResourceSetId},
|
|
||||||
shader::Shader,
|
|
||||||
texture::{Extent3d, TextureDescriptor},
|
texture::{Extent3d, TextureDescriptor},
|
||||||
};
|
};
|
||||||
use bevy_asset::{AssetStorage, Handle};
|
|
||||||
|
|
||||||
pub trait RenderContext {
|
pub trait RenderContext {
|
||||||
fn resources(&self) -> &dyn RenderResourceContext;
|
fn resources(&self) -> &dyn RenderResourceContext;
|
||||||
@ -36,27 +33,6 @@ pub trait RenderContext {
|
|||||||
destination_array_layer: u32,
|
destination_array_layer: u32,
|
||||||
size: Extent3d,
|
size: Extent3d,
|
||||||
);
|
);
|
||||||
fn create_bind_group(
|
|
||||||
&mut self,
|
|
||||||
bind_group_descriptor: &BindGroupDescriptor,
|
|
||||||
render_resource_assignments: &RenderResourceAssignments,
|
|
||||||
) -> Option<RenderResourceSetId>;
|
|
||||||
fn create_render_pipeline(
|
|
||||||
&mut self,
|
|
||||||
pipeline_handle: Handle<PipelineDescriptor>,
|
|
||||||
pipeline_descriptor: &PipelineDescriptor,
|
|
||||||
shader_storage: &AssetStorage<Shader>,
|
|
||||||
);
|
|
||||||
fn setup_bind_groups(
|
|
||||||
&mut self,
|
|
||||||
pipeline_descriptor: &PipelineDescriptor,
|
|
||||||
render_resource_assignments: &RenderResourceAssignments,
|
|
||||||
) {
|
|
||||||
let pipeline_layout = pipeline_descriptor.get_layout().unwrap();
|
|
||||||
for bind_group in pipeline_layout.bind_groups.iter() {
|
|
||||||
self.create_bind_group(bind_group, render_resource_assignments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn begin_pass(
|
fn begin_pass(
|
||||||
&mut self,
|
&mut self,
|
||||||
pass_descriptor: &PassDescriptor,
|
pass_descriptor: &PassDescriptor,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
render_resource::{BufferInfo, RenderResource, ResourceInfo},
|
render_resource::{BufferInfo, RenderResource, ResourceInfo, RenderResourceAssignments, RenderResourceSetId},
|
||||||
shader::Shader,
|
shader::Shader,
|
||||||
texture::{SamplerDescriptor, TextureDescriptor},
|
texture::{SamplerDescriptor, TextureDescriptor}, pipeline::{BindGroupDescriptor, PipelineDescriptor},
|
||||||
};
|
};
|
||||||
use bevy_asset::{AssetStorage, Handle, HandleUntyped};
|
use bevy_asset::{AssetStorage, Handle, HandleUntyped};
|
||||||
use bevy_window::{Window, WindowId};
|
use bevy_window::{Window, WindowId};
|
||||||
@ -38,7 +38,7 @@ pub trait RenderResourceContext: Downcast + Send + Sync + 'static {
|
|||||||
) -> RenderResource;
|
) -> RenderResource;
|
||||||
fn create_buffer_with_data(&self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource;
|
fn create_buffer_with_data(&self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource;
|
||||||
fn create_shader_module(
|
fn create_shader_module(
|
||||||
&mut self,
|
&self,
|
||||||
shader_handle: Handle<Shader>,
|
shader_handle: Handle<Shader>,
|
||||||
shader_storage: &AssetStorage<Shader>,
|
shader_storage: &AssetStorage<Shader>,
|
||||||
);
|
);
|
||||||
@ -61,6 +61,27 @@ pub trait RenderResourceContext: Downcast + Send + Sync + 'static {
|
|||||||
handle: HandleUntyped,
|
handle: HandleUntyped,
|
||||||
index: usize,
|
index: usize,
|
||||||
) -> Option<RenderResource>;
|
) -> Option<RenderResource>;
|
||||||
|
fn create_render_pipeline(
|
||||||
|
&self,
|
||||||
|
pipeline_handle: Handle<PipelineDescriptor>,
|
||||||
|
pipeline_descriptor: &PipelineDescriptor,
|
||||||
|
shader_storage: &AssetStorage<Shader>,
|
||||||
|
);
|
||||||
|
fn create_bind_group(
|
||||||
|
&self,
|
||||||
|
bind_group_descriptor: &BindGroupDescriptor,
|
||||||
|
render_resource_assignments: &RenderResourceAssignments,
|
||||||
|
) -> Option<RenderResourceSetId>;
|
||||||
|
fn setup_bind_groups(
|
||||||
|
&self,
|
||||||
|
pipeline_descriptor: &PipelineDescriptor,
|
||||||
|
render_resource_assignments: &RenderResourceAssignments,
|
||||||
|
) {
|
||||||
|
let pipeline_layout = pipeline_descriptor.get_layout().unwrap();
|
||||||
|
for bind_group in pipeline_layout.bind_groups.iter() {
|
||||||
|
self.create_bind_group(bind_group, render_resource_assignments);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl dyn RenderResourceContext {
|
impl dyn RenderResourceContext {
|
||||||
|
|||||||
@ -128,7 +128,7 @@ impl WgpuResourceDiagnosticsPlugin {
|
|||||||
diagnostics.add_measurement(
|
diagnostics.add_measurement(
|
||||||
Self::WINDOW_SURFACES,
|
Self::WINDOW_SURFACES,
|
||||||
render_resource_context
|
render_resource_context
|
||||||
.wgpu_resources
|
.resources
|
||||||
.window_surfaces
|
.window_surfaces
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -138,7 +138,7 @@ impl WgpuResourceDiagnosticsPlugin {
|
|||||||
diagnostics.add_measurement(
|
diagnostics.add_measurement(
|
||||||
Self::SWAP_CHAINS,
|
Self::SWAP_CHAINS,
|
||||||
render_resource_context
|
render_resource_context
|
||||||
.wgpu_resources
|
.resources
|
||||||
.window_swap_chains
|
.window_swap_chains
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -148,7 +148,7 @@ impl WgpuResourceDiagnosticsPlugin {
|
|||||||
diagnostics.add_measurement(
|
diagnostics.add_measurement(
|
||||||
Self::SWAP_CHAIN_OUTPUTS,
|
Self::SWAP_CHAIN_OUTPUTS,
|
||||||
render_resource_context
|
render_resource_context
|
||||||
.wgpu_resources
|
.resources
|
||||||
.swap_chain_outputs
|
.swap_chain_outputs
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -158,7 +158,7 @@ impl WgpuResourceDiagnosticsPlugin {
|
|||||||
diagnostics.add_measurement(
|
diagnostics.add_measurement(
|
||||||
Self::BUFFERS,
|
Self::BUFFERS,
|
||||||
render_resource_context
|
render_resource_context
|
||||||
.wgpu_resources
|
.resources
|
||||||
.buffers
|
.buffers
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -168,7 +168,7 @@ impl WgpuResourceDiagnosticsPlugin {
|
|||||||
diagnostics.add_measurement(
|
diagnostics.add_measurement(
|
||||||
Self::TEXTURES,
|
Self::TEXTURES,
|
||||||
render_resource_context
|
render_resource_context
|
||||||
.wgpu_resources
|
.resources
|
||||||
.textures
|
.textures
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -178,7 +178,7 @@ impl WgpuResourceDiagnosticsPlugin {
|
|||||||
diagnostics.add_measurement(
|
diagnostics.add_measurement(
|
||||||
Self::TEXTURE_VIEWS,
|
Self::TEXTURE_VIEWS,
|
||||||
render_resource_context
|
render_resource_context
|
||||||
.wgpu_resources
|
.resources
|
||||||
.texture_views
|
.texture_views
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -188,7 +188,7 @@ impl WgpuResourceDiagnosticsPlugin {
|
|||||||
diagnostics.add_measurement(
|
diagnostics.add_measurement(
|
||||||
Self::SAMPLERS,
|
Self::SAMPLERS,
|
||||||
render_resource_context
|
render_resource_context
|
||||||
.wgpu_resources
|
.resources
|
||||||
.samplers
|
.samplers
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -198,7 +198,7 @@ impl WgpuResourceDiagnosticsPlugin {
|
|||||||
diagnostics.add_measurement(
|
diagnostics.add_measurement(
|
||||||
Self::BIND_GROUPS,
|
Self::BIND_GROUPS,
|
||||||
render_resource_context
|
render_resource_context
|
||||||
.wgpu_resources
|
.resources
|
||||||
.bind_groups
|
.bind_groups
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -208,7 +208,7 @@ impl WgpuResourceDiagnosticsPlugin {
|
|||||||
diagnostics.add_measurement(
|
diagnostics.add_measurement(
|
||||||
Self::BIND_GROUP_LAYOUTS,
|
Self::BIND_GROUP_LAYOUTS,
|
||||||
render_resource_context
|
render_resource_context
|
||||||
.wgpu_resources
|
.resources
|
||||||
.bind_group_layouts
|
.bind_group_layouts
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -218,7 +218,7 @@ impl WgpuResourceDiagnosticsPlugin {
|
|||||||
diagnostics.add_measurement(
|
diagnostics.add_measurement(
|
||||||
Self::SHADER_MODULES,
|
Self::SHADER_MODULES,
|
||||||
render_resource_context
|
render_resource_context
|
||||||
.wgpu_resources
|
.resources
|
||||||
.shader_modules
|
.shader_modules
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -228,7 +228,7 @@ impl WgpuResourceDiagnosticsPlugin {
|
|||||||
diagnostics.add_measurement(
|
diagnostics.add_measurement(
|
||||||
Self::RENDER_PIPELINES,
|
Self::RENDER_PIPELINES,
|
||||||
render_resource_context
|
render_resource_context
|
||||||
.wgpu_resources
|
.resources
|
||||||
.render_pipelines
|
.render_pipelines
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|||||||
@ -1,20 +1,13 @@
|
|||||||
use super::WgpuRenderResourceContext;
|
use super::WgpuRenderResourceContext;
|
||||||
use crate::{
|
use crate::{wgpu_type_converter::WgpuInto, WgpuRenderPass, WgpuResourceRefs};
|
||||||
wgpu_type_converter::{OwnedWgpuVertexBufferDescriptor, WgpuInto},
|
|
||||||
WgpuRenderPass, WgpuResourceRefs,
|
|
||||||
};
|
|
||||||
use bevy_asset::{AssetStorage, Handle};
|
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
pass::{
|
pass::{
|
||||||
PassDescriptor, RenderPass, RenderPassColorAttachmentDescriptor,
|
PassDescriptor, RenderPass, RenderPassColorAttachmentDescriptor,
|
||||||
RenderPassDepthStencilAttachmentDescriptor, TextureAttachment,
|
RenderPassDepthStencilAttachmentDescriptor, TextureAttachment,
|
||||||
},
|
},
|
||||||
pipeline::{BindGroupDescriptor, BindType, PipelineDescriptor},
|
render_resource::{RenderResource, RenderResourceAssignments},
|
||||||
render_resource::{
|
|
||||||
RenderResource, RenderResourceAssignments, RenderResourceSetId, ResourceInfo,
|
|
||||||
},
|
|
||||||
renderer::{RenderContext, RenderResourceContext},
|
renderer::{RenderContext, RenderResourceContext},
|
||||||
shader::Shader,
|
|
||||||
texture::{Extent3d, TextureDescriptor},
|
texture::{Extent3d, TextureDescriptor},
|
||||||
};
|
};
|
||||||
use bevy_window::WindowId;
|
use bevy_window::WindowId;
|
||||||
@ -86,14 +79,11 @@ impl RenderContext for WgpuRenderContext {
|
|||||||
texture_descriptor: &TextureDescriptor,
|
texture_descriptor: &TextureDescriptor,
|
||||||
bytes: &[u8],
|
bytes: &[u8],
|
||||||
) -> RenderResource {
|
) -> RenderResource {
|
||||||
self.render_resources
|
self.render_resources.create_texture_with_data(
|
||||||
.wgpu_resources
|
self.command_encoder.get_or_create(&self.device),
|
||||||
.create_texture_with_data(
|
texture_descriptor,
|
||||||
&self.device,
|
bytes,
|
||||||
self.command_encoder.get_or_create(&self.device),
|
)
|
||||||
texture_descriptor,
|
|
||||||
bytes,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
fn copy_buffer_to_buffer(
|
fn copy_buffer_to_buffer(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -103,9 +93,8 @@ impl RenderContext for WgpuRenderContext {
|
|||||||
destination_offset: u64,
|
destination_offset: u64,
|
||||||
size: u64,
|
size: u64,
|
||||||
) {
|
) {
|
||||||
let command_encoder = self.command_encoder.get_or_create(&self.device);
|
self.render_resources.copy_buffer_to_buffer(
|
||||||
self.render_resources.wgpu_resources.copy_buffer_to_buffer(
|
self.command_encoder.get_or_create(&self.device),
|
||||||
command_encoder,
|
|
||||||
source_buffer,
|
source_buffer,
|
||||||
source_offset,
|
source_offset,
|
||||||
destination_buffer,
|
destination_buffer,
|
||||||
@ -113,305 +102,38 @@ impl RenderContext for WgpuRenderContext {
|
|||||||
size,
|
size,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn copy_buffer_to_texture(
|
||||||
|
&mut self,
|
||||||
|
source_buffer: RenderResource,
|
||||||
|
source_offset: u64,
|
||||||
|
source_bytes_per_row: u32,
|
||||||
|
destination_texture: RenderResource,
|
||||||
|
destination_origin: [u32; 3],
|
||||||
|
destination_mip_level: u32,
|
||||||
|
destination_array_layer: u32,
|
||||||
|
size: Extent3d,
|
||||||
|
) {
|
||||||
|
self.render_resources.copy_buffer_to_texture(
|
||||||
|
self.command_encoder.get_or_create(&self.device),
|
||||||
|
source_buffer,
|
||||||
|
source_offset,
|
||||||
|
source_bytes_per_row,
|
||||||
|
destination_texture,
|
||||||
|
destination_origin,
|
||||||
|
destination_mip_level,
|
||||||
|
destination_array_layer,
|
||||||
|
size,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn resources(&self) -> &dyn RenderResourceContext {
|
fn resources(&self) -> &dyn RenderResourceContext {
|
||||||
&self.render_resources
|
&self.render_resources
|
||||||
}
|
}
|
||||||
fn resources_mut(&mut self) -> &mut dyn RenderResourceContext {
|
fn resources_mut(&mut self) -> &mut dyn RenderResourceContext {
|
||||||
&mut self.render_resources
|
&mut self.render_resources
|
||||||
}
|
}
|
||||||
fn create_bind_group(
|
|
||||||
&mut self,
|
|
||||||
bind_group_descriptor: &BindGroupDescriptor,
|
|
||||||
render_resource_assignments: &RenderResourceAssignments,
|
|
||||||
) -> Option<RenderResourceSetId> {
|
|
||||||
if let Some((render_resource_set_id, _indices)) =
|
|
||||||
render_resource_assignments.get_render_resource_set_id(bind_group_descriptor.id)
|
|
||||||
{
|
|
||||||
if !self
|
|
||||||
.render_resources
|
|
||||||
.wgpu_resources
|
|
||||||
.has_bind_group(bind_group_descriptor.id, *render_resource_set_id)
|
|
||||||
{
|
|
||||||
log::trace!(
|
|
||||||
"start creating bind group for RenderResourceSet {:?}",
|
|
||||||
render_resource_set_id
|
|
||||||
);
|
|
||||||
let wgpu_bind_group = {
|
|
||||||
let textures = self
|
|
||||||
.render_resources
|
|
||||||
.wgpu_resources
|
|
||||||
.texture_views
|
|
||||||
.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()
|
|
||||||
.map(|binding| {
|
|
||||||
if let Some(resource) = render_resource_assignments.get(&binding.name) {
|
|
||||||
let mut wgpu_resource = None;
|
|
||||||
self.resources().get_resource_info(
|
|
||||||
resource,
|
|
||||||
&mut |resource_info| {
|
|
||||||
log::trace!(
|
|
||||||
"found binding {} ({}) resource: {:?} {:?}",
|
|
||||||
binding.index,
|
|
||||||
binding.name,
|
|
||||||
resource,
|
|
||||||
resource_info
|
|
||||||
);
|
|
||||||
wgpu_resource = match &binding.bind_type {
|
|
||||||
BindType::SampledTexture { .. } => {
|
|
||||||
if let Some(ResourceInfo::Texture) = resource_info {
|
|
||||||
let texture = textures.get(&resource).unwrap();
|
|
||||||
Some(wgpu::BindingResource::TextureView(
|
|
||||||
texture,
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
panic!("expected a Texture resource");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BindType::Sampler { .. } => {
|
|
||||||
if let Some(ResourceInfo::Sampler) = resource_info {
|
|
||||||
let sampler = samplers.get(&resource).unwrap();
|
|
||||||
Some(wgpu::BindingResource::Sampler(sampler))
|
|
||||||
} else {
|
|
||||||
panic!("expected a Sampler resource");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BindType::Uniform { .. } => {
|
|
||||||
if let Some(ResourceInfo::Buffer(buffer_info)) =
|
|
||||||
resource_info
|
|
||||||
{
|
|
||||||
let buffer = buffers.get(&resource).unwrap();
|
|
||||||
Some(wgpu::BindingResource::Buffer {
|
|
||||||
buffer,
|
|
||||||
range: 0..buffer_info.size as u64,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
panic!("expected a Buffer resource");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => panic!("unsupported bind type"),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
wgpu::Binding {
|
|
||||||
binding: binding.index,
|
|
||||||
resource: wgpu_resource.expect("No resource binding found"),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic!(
|
|
||||||
"No resource assigned to uniform \"{}\" for RenderResourceAssignments {:?}",
|
|
||||||
binding.name,
|
|
||||||
render_resource_assignments.id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<wgpu::Binding>>();
|
|
||||||
let bind_group_layouts = self
|
|
||||||
.render_resources
|
|
||||||
.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.wgpu_resources.create_bind_group(
|
|
||||||
&self.device,
|
|
||||||
*render_resource_set_id,
|
|
||||||
&wgpu_bind_group_descriptor,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
self.render_resources.wgpu_resources.set_bind_group(
|
|
||||||
bind_group_descriptor.id,
|
|
||||||
*render_resource_set_id,
|
|
||||||
wgpu_bind_group,
|
|
||||||
);
|
|
||||||
return Some(*render_resource_set_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
fn create_render_pipeline(
|
|
||||||
&mut self,
|
|
||||||
pipeline_handle: Handle<PipelineDescriptor>,
|
|
||||||
pipeline_descriptor: &PipelineDescriptor,
|
|
||||||
shader_storage: &AssetStorage<Shader>,
|
|
||||||
) {
|
|
||||||
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 self
|
|
||||||
.render_resources
|
|
||||||
.wgpu_resources
|
|
||||||
.bind_group_layouts
|
|
||||||
.read()
|
|
||||||
.unwrap()
|
|
||||||
.get(&bind_group.id)
|
|
||||||
.is_none()
|
|
||||||
{
|
|
||||||
let bind_group_layout_binding = bind_group
|
|
||||||
.bindings
|
|
||||||
.iter()
|
|
||||||
.map(|binding| wgpu::BindGroupLayoutEntry {
|
|
||||||
binding: binding.index,
|
|
||||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
|
||||||
ty: (&binding.bind_type).wgpu_into(),
|
|
||||||
})
|
|
||||||
.collect::<Vec<wgpu::BindGroupLayoutEntry>>();
|
|
||||||
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,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
.iter()
|
|
||||||
.map(|v| v.wgpu_into())
|
|
||||||
.collect::<Vec<OwnedWgpuVertexBufferDescriptor>>();
|
|
||||||
|
|
||||||
let color_states = pipeline_descriptor
|
|
||||||
.color_states
|
|
||||||
.iter()
|
|
||||||
.map(|c| c.wgpu_into())
|
|
||||||
.collect::<Vec<wgpu::ColorStateDescriptor>>();
|
|
||||||
|
|
||||||
if self
|
|
||||||
.render_resources
|
|
||||||
.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 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 shader_modules = self
|
|
||||||
.render_resources
|
|
||||||
.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(shader_modules.get(&fragment_handle).unwrap()),
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let render_pipeline_descriptor = wgpu::RenderPipelineDescriptor {
|
|
||||||
layout: &pipeline_layout,
|
|
||||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
|
||||||
module: &vertex_shader_module,
|
|
||||||
entry_point: "main",
|
|
||||||
},
|
|
||||||
fragment_stage: match pipeline_descriptor.shader_stages.fragment {
|
|
||||||
Some(_) => Some(wgpu::ProgrammableStageDescriptor {
|
|
||||||
entry_point: "main",
|
|
||||||
module: fragment_shader_module.as_ref().unwrap(),
|
|
||||||
}),
|
|
||||||
None => None,
|
|
||||||
},
|
|
||||||
rasterization_state: pipeline_descriptor
|
|
||||||
.rasterization_state
|
|
||||||
.as_ref()
|
|
||||||
.map(|r| r.wgpu_into()),
|
|
||||||
primitive_topology: pipeline_descriptor.primitive_topology.wgpu_into(),
|
|
||||||
color_states: &color_states,
|
|
||||||
depth_stencil_state: pipeline_descriptor
|
|
||||||
.depth_stencil_state
|
|
||||||
.as_ref()
|
|
||||||
.map(|d| d.wgpu_into()),
|
|
||||||
vertex_state: wgpu::VertexStateDescriptor {
|
|
||||||
index_format: pipeline_descriptor.index_format.wgpu_into(),
|
|
||||||
vertex_buffers: &owned_vertex_buffer_descriptors
|
|
||||||
.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,
|
|
||||||
};
|
|
||||||
|
|
||||||
self.render_resources
|
|
||||||
.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(
|
fn begin_pass(
|
||||||
&mut self,
|
&mut self,
|
||||||
pass_descriptor: &PassDescriptor,
|
pass_descriptor: &PassDescriptor,
|
||||||
@ -421,7 +143,7 @@ impl RenderContext for WgpuRenderContext {
|
|||||||
if !self.command_encoder.is_some() {
|
if !self.command_encoder.is_some() {
|
||||||
self.command_encoder.create(&self.device);
|
self.command_encoder.create(&self.device);
|
||||||
}
|
}
|
||||||
let resource_lock = self.render_resources.wgpu_resources.read();
|
let resource_lock = self.render_resources.resources.read();
|
||||||
let refs = resource_lock.refs();
|
let refs = resource_lock.refs();
|
||||||
let mut encoder = self.command_encoder.take().unwrap();
|
let mut encoder = self.command_encoder.take().unwrap();
|
||||||
{
|
{
|
||||||
@ -443,29 +165,6 @@ impl RenderContext for WgpuRenderContext {
|
|||||||
|
|
||||||
self.command_encoder.set(encoder);
|
self.command_encoder.set(encoder);
|
||||||
}
|
}
|
||||||
fn copy_buffer_to_texture(
|
|
||||||
&mut self,
|
|
||||||
source_buffer: RenderResource,
|
|
||||||
source_offset: u64,
|
|
||||||
source_bytes_per_row: u32,
|
|
||||||
destination_texture: RenderResource,
|
|
||||||
destination_origin: [u32; 3],
|
|
||||||
destination_mip_level: u32,
|
|
||||||
destination_array_layer: u32,
|
|
||||||
size: Extent3d,
|
|
||||||
) {
|
|
||||||
self.render_resources.wgpu_resources.copy_buffer_to_texture(
|
|
||||||
self.command_encoder.get_or_create(&self.device),
|
|
||||||
source_buffer,
|
|
||||||
source_offset,
|
|
||||||
source_bytes_per_row,
|
|
||||||
destination_texture,
|
|
||||||
destination_origin,
|
|
||||||
destination_mip_level,
|
|
||||||
destination_array_layer,
|
|
||||||
size,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_render_pass<'a, 'b>(
|
pub fn create_render_pass<'a, 'b>(
|
||||||
|
|||||||
@ -1,70 +1,282 @@
|
|||||||
use crate::WgpuResources;
|
use crate::{
|
||||||
|
wgpu_type_converter::{OwnedWgpuVertexBufferDescriptor, WgpuInto},
|
||||||
|
WgpuBindGroupInfo, WgpuResources,
|
||||||
|
};
|
||||||
|
|
||||||
use bevy_asset::{AssetStorage, Handle, HandleUntyped};
|
use bevy_asset::{AssetStorage, Handle, HandleUntyped};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
render_resource::{BufferInfo, RenderResource, ResourceInfo},
|
pipeline::{BindGroupDescriptor, BindType, PipelineDescriptor},
|
||||||
|
render_resource::{
|
||||||
|
BufferInfo, RenderResource, RenderResourceAssignments, RenderResourceSetId, ResourceInfo,
|
||||||
|
},
|
||||||
renderer::RenderResourceContext,
|
renderer::RenderResourceContext,
|
||||||
shader::Shader,
|
shader::Shader,
|
||||||
texture::{SamplerDescriptor, TextureDescriptor},
|
texture::{Extent3d, SamplerDescriptor, TextureDescriptor},
|
||||||
};
|
};
|
||||||
use bevy_window::Window;
|
use bevy_window::{Window, WindowId};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct WgpuRenderResourceContext {
|
pub struct WgpuRenderResourceContext {
|
||||||
pub device: Arc<wgpu::Device>,
|
pub device: Arc<wgpu::Device>,
|
||||||
pub wgpu_resources: WgpuResources,
|
pub resources: WgpuResources,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WgpuRenderResourceContext {
|
impl WgpuRenderResourceContext {
|
||||||
pub fn new(device: Arc<wgpu::Device>) -> Self {
|
pub fn new(device: Arc<wgpu::Device>) -> Self {
|
||||||
WgpuRenderResourceContext {
|
WgpuRenderResourceContext {
|
||||||
device,
|
device,
|
||||||
wgpu_resources: WgpuResources::default(),
|
resources: WgpuResources::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_window_surface(&self, window_id: WindowId, surface: wgpu::Surface) {
|
||||||
|
let mut window_surfaces = self.resources.window_surfaces.write().unwrap();
|
||||||
|
window_surfaces.insert(window_id, surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_texture_with_data(
|
||||||
|
&mut self,
|
||||||
|
command_encoder: &mut wgpu::CommandEncoder,
|
||||||
|
texture_descriptor: &TextureDescriptor,
|
||||||
|
bytes: &[u8],
|
||||||
|
) -> RenderResource {
|
||||||
|
let mut resource_info = self.resources.resource_info.write().unwrap();
|
||||||
|
let mut texture_views = self.resources.texture_views.write().unwrap();
|
||||||
|
let mut textures = self.resources.textures.write().unwrap();
|
||||||
|
|
||||||
|
let descriptor: wgpu::TextureDescriptor = (*texture_descriptor).wgpu_into();
|
||||||
|
let texture = self.device.create_texture(&descriptor);
|
||||||
|
let texture_view = texture.create_default_view();
|
||||||
|
let temp_buf = self
|
||||||
|
.device
|
||||||
|
.create_buffer_with_data(bytes, wgpu::BufferUsage::COPY_SRC);
|
||||||
|
command_encoder.copy_buffer_to_texture(
|
||||||
|
wgpu::BufferCopyView {
|
||||||
|
buffer: &temp_buf,
|
||||||
|
offset: 0,
|
||||||
|
bytes_per_row: 4 * descriptor.size.width,
|
||||||
|
rows_per_image: 0, // NOTE: Example sets this to 0, but should it be height?
|
||||||
|
},
|
||||||
|
wgpu::TextureCopyView {
|
||||||
|
texture: &texture,
|
||||||
|
mip_level: 0,
|
||||||
|
array_layer: 0,
|
||||||
|
origin: wgpu::Origin3d { x: 0, y: 0, z: 0 },
|
||||||
|
},
|
||||||
|
descriptor.size,
|
||||||
|
);
|
||||||
|
|
||||||
|
let resource = RenderResource::new();
|
||||||
|
resource_info.insert(resource, ResourceInfo::Texture);
|
||||||
|
texture_views.insert(resource, texture_view);
|
||||||
|
textures.insert(resource, texture);
|
||||||
|
|
||||||
|
resource
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn copy_buffer_to_buffer(
|
||||||
|
&self,
|
||||||
|
command_encoder: &mut wgpu::CommandEncoder,
|
||||||
|
source_buffer: RenderResource,
|
||||||
|
source_offset: u64,
|
||||||
|
destination_buffer: RenderResource,
|
||||||
|
destination_offset: u64,
|
||||||
|
size: u64,
|
||||||
|
) {
|
||||||
|
let buffers = self.resources.buffers.read().unwrap();
|
||||||
|
|
||||||
|
let source = buffers.get(&source_buffer).unwrap();
|
||||||
|
let destination = buffers.get(&destination_buffer).unwrap();
|
||||||
|
command_encoder.copy_buffer_to_buffer(
|
||||||
|
source,
|
||||||
|
source_offset,
|
||||||
|
destination,
|
||||||
|
destination_offset,
|
||||||
|
size,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn copy_buffer_to_texture(
|
||||||
|
&self,
|
||||||
|
command_encoder: &mut wgpu::CommandEncoder,
|
||||||
|
source_buffer: RenderResource,
|
||||||
|
source_offset: u64,
|
||||||
|
source_bytes_per_row: u32,
|
||||||
|
destination_texture: RenderResource,
|
||||||
|
destination_origin: [u32; 3], // TODO: replace with math type
|
||||||
|
destination_mip_level: u32,
|
||||||
|
destination_array_layer: u32,
|
||||||
|
size: Extent3d,
|
||||||
|
) {
|
||||||
|
let buffers = self.resources.buffers.read().unwrap();
|
||||||
|
let textures = self.resources.textures.read().unwrap();
|
||||||
|
|
||||||
|
let source = buffers.get(&source_buffer).unwrap();
|
||||||
|
let destination = textures.get(&destination_texture).unwrap();
|
||||||
|
command_encoder.copy_buffer_to_texture(
|
||||||
|
wgpu::BufferCopyView {
|
||||||
|
buffer: source,
|
||||||
|
offset: source_offset,
|
||||||
|
bytes_per_row: source_bytes_per_row,
|
||||||
|
rows_per_image: 0, // NOTE: Example sets this to 0, but should it be height?
|
||||||
|
},
|
||||||
|
wgpu::TextureCopyView {
|
||||||
|
texture: destination,
|
||||||
|
mip_level: destination_mip_level,
|
||||||
|
array_layer: destination_array_layer,
|
||||||
|
origin: wgpu::Origin3d {
|
||||||
|
x: destination_origin[0],
|
||||||
|
y: destination_origin[1],
|
||||||
|
z: destination_origin[2],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
size.wgpu_into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_bind_group_layout(&self, descriptor: &BindGroupDescriptor) {
|
||||||
|
if self
|
||||||
|
.resources
|
||||||
|
.bind_group_layouts
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.get(&descriptor.id)
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut bind_group_layouts = self.resources.bind_group_layouts.write().unwrap();
|
||||||
|
// TODO: consider re-checking existence here
|
||||||
|
let bind_group_layout_binding = descriptor
|
||||||
|
.bindings
|
||||||
|
.iter()
|
||||||
|
.map(|binding| wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: binding.index,
|
||||||
|
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||||
|
ty: (&binding.bind_type).wgpu_into(),
|
||||||
|
})
|
||||||
|
.collect::<Vec<wgpu::BindGroupLayoutEntry>>();
|
||||||
|
let wgpu_descriptor = wgpu::BindGroupLayoutDescriptor {
|
||||||
|
bindings: bind_group_layout_binding.as_slice(),
|
||||||
|
label: None,
|
||||||
|
};
|
||||||
|
let bind_group_layout = self.device.create_bind_group_layout(&wgpu_descriptor);
|
||||||
|
bind_group_layouts.insert(descriptor.id, bind_group_layout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderResourceContext for WgpuRenderResourceContext {
|
impl RenderResourceContext for WgpuRenderResourceContext {
|
||||||
fn create_sampler(&self, sampler_descriptor: &SamplerDescriptor) -> RenderResource {
|
fn create_sampler(&self, sampler_descriptor: &SamplerDescriptor) -> RenderResource {
|
||||||
self.wgpu_resources
|
let mut samplers = self.resources.samplers.write().unwrap();
|
||||||
.create_sampler(&self.device, sampler_descriptor)
|
let mut resource_info = self.resources.resource_info.write().unwrap();
|
||||||
}
|
|
||||||
fn create_texture(&self, texture_descriptor: &TextureDescriptor) -> RenderResource {
|
let descriptor: wgpu::SamplerDescriptor = (*sampler_descriptor).wgpu_into();
|
||||||
self.wgpu_resources
|
let sampler = self.device.create_sampler(&descriptor);
|
||||||
.create_texture(&self.device, texture_descriptor)
|
|
||||||
}
|
let resource = RenderResource::new();
|
||||||
fn create_buffer(&self, buffer_info: BufferInfo) -> RenderResource {
|
samplers.insert(resource, sampler);
|
||||||
self.wgpu_resources.create_buffer(&self.device, buffer_info)
|
resource_info.insert(resource, ResourceInfo::Sampler);
|
||||||
|
resource
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_texture(&self, texture_descriptor: &TextureDescriptor) -> RenderResource {
|
||||||
|
let mut textures = self.resources.textures.write().unwrap();
|
||||||
|
let mut texture_views = self.resources.texture_views.write().unwrap();
|
||||||
|
let mut resource_info = self.resources.resource_info.write().unwrap();
|
||||||
|
|
||||||
|
let descriptor: wgpu::TextureDescriptor = (*texture_descriptor).wgpu_into();
|
||||||
|
let texture = self.device.create_texture(&descriptor);
|
||||||
|
let texture_view = texture.create_default_view();
|
||||||
|
|
||||||
|
let resource = RenderResource::new();
|
||||||
|
resource_info.insert(resource, ResourceInfo::Texture);
|
||||||
|
texture_views.insert(resource, texture_view);
|
||||||
|
textures.insert(resource, texture);
|
||||||
|
resource
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_buffer(&self, buffer_info: BufferInfo) -> RenderResource {
|
||||||
|
// TODO: consider moving this below "create" for efficiency
|
||||||
|
let mut resource_info = self.resources.resource_info.write().unwrap();
|
||||||
|
let mut buffers = self.resources.buffers.write().unwrap();
|
||||||
|
|
||||||
|
let buffer = self.device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
|
label: None,
|
||||||
|
size: buffer_info.size as u64,
|
||||||
|
usage: buffer_info.buffer_usage.wgpu_into(),
|
||||||
|
});
|
||||||
|
|
||||||
|
let resource = RenderResource::new();
|
||||||
|
resource_info.insert(resource, ResourceInfo::Buffer(buffer_info));
|
||||||
|
buffers.insert(resource, buffer);
|
||||||
|
resource
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: clean this up
|
|
||||||
fn create_buffer_mapped(
|
fn create_buffer_mapped(
|
||||||
&self,
|
&self,
|
||||||
buffer_info: BufferInfo,
|
buffer_info: BufferInfo,
|
||||||
setup_data: &mut dyn FnMut(&mut [u8], &dyn RenderResourceContext),
|
setup_data: &mut dyn FnMut(&mut [u8], &dyn RenderResourceContext),
|
||||||
) -> RenderResource {
|
) -> RenderResource {
|
||||||
let buffer = WgpuResources::begin_create_buffer_mapped_render_context(
|
// TODO: consider moving this below "create" for efficiency
|
||||||
&buffer_info,
|
|
||||||
self,
|
let mut mapped = self.device.create_buffer_mapped(&wgpu::BufferDescriptor {
|
||||||
setup_data,
|
size: buffer_info.size as u64,
|
||||||
);
|
usage: buffer_info.buffer_usage.wgpu_into(),
|
||||||
self.wgpu_resources.assign_buffer(buffer, buffer_info)
|
label: None,
|
||||||
|
});
|
||||||
|
setup_data(&mut mapped.data(), self);
|
||||||
|
let buffer = mapped.finish();
|
||||||
|
|
||||||
|
let resource = RenderResource::new();
|
||||||
|
let mut resource_info = self.resources.resource_info.write().unwrap();
|
||||||
|
let mut buffers = self.resources.buffers.write().unwrap();
|
||||||
|
resource_info.insert(resource, ResourceInfo::Buffer(buffer_info));
|
||||||
|
buffers.insert(resource, buffer);
|
||||||
|
resource
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_buffer_with_data(&self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource {
|
fn create_buffer_with_data(&self, mut buffer_info: BufferInfo, data: &[u8]) -> RenderResource {
|
||||||
self.wgpu_resources
|
// TODO: consider moving this below "create" for efficiency
|
||||||
.create_buffer_with_data(&self.device, buffer_info, data)
|
let mut resource_info = self.resources.resource_info.write().unwrap();
|
||||||
|
let mut buffers = self.resources.buffers.write().unwrap();
|
||||||
|
|
||||||
|
buffer_info.size = data.len();
|
||||||
|
let buffer = self
|
||||||
|
.device
|
||||||
|
.create_buffer_with_data(data, buffer_info.buffer_usage.wgpu_into());
|
||||||
|
|
||||||
|
let resource = RenderResource::new();
|
||||||
|
resource_info.insert(resource, ResourceInfo::Buffer(buffer_info));
|
||||||
|
buffers.insert(resource, buffer);
|
||||||
|
resource
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_buffer(&self, resource: RenderResource) {
|
fn remove_buffer(&self, resource: RenderResource) {
|
||||||
self.wgpu_resources.remove_buffer(resource);
|
let mut buffers = self.resources.buffers.write().unwrap();
|
||||||
|
let mut resource_info = self.resources.resource_info.write().unwrap();
|
||||||
|
|
||||||
|
buffers.remove(&resource);
|
||||||
|
resource_info.remove(&resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_texture(&self, resource: RenderResource) {
|
fn remove_texture(&self, resource: RenderResource) {
|
||||||
self.wgpu_resources.remove_texture(resource);
|
let mut textures = self.resources.textures.write().unwrap();
|
||||||
|
let mut texture_views = self.resources.texture_views.write().unwrap();
|
||||||
|
let mut resource_info = self.resources.resource_info.write().unwrap();
|
||||||
|
|
||||||
|
textures.remove(&resource);
|
||||||
|
texture_views.remove(&resource);
|
||||||
|
resource_info.remove(&resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_sampler(&self, resource: RenderResource) {
|
fn remove_sampler(&self, resource: RenderResource) {
|
||||||
self.wgpu_resources.remove_sampler(resource);
|
let mut samplers = self.resources.samplers.write().unwrap();
|
||||||
|
let mut resource_info = self.resources.resource_info.write().unwrap();
|
||||||
|
|
||||||
|
samplers.remove(&resource);
|
||||||
|
resource_info.remove(&resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_resource_info(
|
fn get_resource_info(
|
||||||
@ -72,16 +284,18 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||||||
resource: RenderResource,
|
resource: RenderResource,
|
||||||
handle_info: &mut dyn FnMut(Option<&ResourceInfo>),
|
handle_info: &mut dyn FnMut(Option<&ResourceInfo>),
|
||||||
) {
|
) {
|
||||||
self.wgpu_resources.get_resource_info(resource, handle_info);
|
let resource_info = self.resources.resource_info.read().unwrap();
|
||||||
|
let info = resource_info.get(&resource);
|
||||||
|
handle_info(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_shader_module(
|
fn create_shader_module(
|
||||||
&mut self,
|
&self,
|
||||||
shader_handle: Handle<Shader>,
|
shader_handle: Handle<Shader>,
|
||||||
shader_storage: &AssetStorage<Shader>,
|
shader_storage: &AssetStorage<Shader>,
|
||||||
) {
|
) {
|
||||||
if self
|
if self
|
||||||
.wgpu_resources
|
.resources
|
||||||
.shader_modules
|
.shader_modules
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -91,39 +305,281 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut shader_modules = self.resources.shader_modules.write().unwrap();
|
||||||
|
// TODO: consider re-checking existence here
|
||||||
|
|
||||||
let shader = shader_storage.get(&shader_handle).unwrap();
|
let shader = shader_storage.get(&shader_handle).unwrap();
|
||||||
self.wgpu_resources
|
let shader_module = self.device.create_shader_module(&shader.get_spirv(None));
|
||||||
.create_shader_module(&self.device, shader_handle, shader);
|
shader_modules.insert(shader_handle, shader_module);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_swap_chain(&self, window: &Window) {
|
fn create_swap_chain(&self, window: &Window) {
|
||||||
self.wgpu_resources
|
let surfaces = self.resources.window_surfaces.read().unwrap();
|
||||||
.create_window_swap_chain(&self.device, window)
|
let mut window_swap_chains = self.resources.window_swap_chains.write().unwrap();
|
||||||
|
|
||||||
|
let swap_chain_descriptor: wgpu::SwapChainDescriptor = window.wgpu_into();
|
||||||
|
let surface = surfaces
|
||||||
|
.get(&window.id)
|
||||||
|
.expect("No surface found for window");
|
||||||
|
let swap_chain = self
|
||||||
|
.device
|
||||||
|
.create_swap_chain(surface, &swap_chain_descriptor);
|
||||||
|
|
||||||
|
window_swap_chains.insert(window.id, swap_chain);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_swap_chain_texture(&self, window_id: bevy_window::WindowId) -> RenderResource {
|
fn next_swap_chain_texture(&self, window_id: bevy_window::WindowId) -> RenderResource {
|
||||||
self.wgpu_resources.next_swap_chain_texture(window_id)
|
let mut window_swap_chains = self.resources.window_swap_chains.write().unwrap();
|
||||||
|
let mut swap_chain_outputs = self.resources.swap_chain_outputs.write().unwrap();
|
||||||
|
|
||||||
|
let window_swap_chain = window_swap_chains.get_mut(&window_id).unwrap();
|
||||||
|
let next_texture = window_swap_chain.get_next_texture().unwrap();
|
||||||
|
|
||||||
|
// TODO: Add ResourceInfo
|
||||||
|
let render_resource = RenderResource::new();
|
||||||
|
swap_chain_outputs.insert(render_resource, next_texture);
|
||||||
|
render_resource
|
||||||
}
|
}
|
||||||
|
|
||||||
fn drop_swap_chain_texture(&self, render_resource: RenderResource) {
|
fn drop_swap_chain_texture(&self, render_resource: RenderResource) {
|
||||||
self.wgpu_resources
|
let mut swap_chain_outputs = self.resources.swap_chain_outputs.write().unwrap();
|
||||||
.remove_swap_chain_texture(render_resource);
|
swap_chain_outputs.remove(&render_resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn drop_all_swap_chain_textures(&self) {
|
fn drop_all_swap_chain_textures(&self) {
|
||||||
self.wgpu_resources.remove_all_swap_chain_textures();
|
let mut swap_chain_outputs = self.resources.swap_chain_outputs.write().unwrap();
|
||||||
|
swap_chain_outputs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_asset_resource_untyped(
|
fn set_asset_resource_untyped(
|
||||||
&self,
|
&self,
|
||||||
handle: HandleUntyped,
|
handle: HandleUntyped,
|
||||||
render_resource: RenderResource,
|
render_resource: RenderResource,
|
||||||
index: usize,
|
index: usize,
|
||||||
) {
|
) {
|
||||||
self.wgpu_resources
|
let mut asset_resources = self.resources.asset_resources.write().unwrap();
|
||||||
.set_asset_resource_untyped(handle, render_resource, index);
|
asset_resources.insert((handle, index), render_resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_asset_resource_untyped(
|
fn get_asset_resource_untyped(
|
||||||
&self,
|
&self,
|
||||||
handle: HandleUntyped,
|
handle: HandleUntyped,
|
||||||
index: usize,
|
index: usize,
|
||||||
) -> Option<RenderResource> {
|
) -> Option<RenderResource> {
|
||||||
self.wgpu_resources
|
let asset_resources = self.resources.asset_resources.read().unwrap();
|
||||||
.get_asset_resource_untyped(handle, index)
|
asset_resources.get(&(handle, index)).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_render_pipeline(
|
||||||
|
&self,
|
||||||
|
pipeline_handle: Handle<PipelineDescriptor>,
|
||||||
|
pipeline_descriptor: &PipelineDescriptor,
|
||||||
|
shaders: &AssetStorage<Shader>,
|
||||||
|
) {
|
||||||
|
if self
|
||||||
|
.resources
|
||||||
|
.render_pipelines
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.get(&pipeline_handle)
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let layout = pipeline_descriptor.get_layout().unwrap();
|
||||||
|
for bind_group_descriptor in layout.bind_groups.iter() {
|
||||||
|
self.create_bind_group_layout(&bind_group_descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
let bind_group_layouts = self.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>>();
|
||||||
|
|
||||||
|
let pipeline_layout = self
|
||||||
|
.device
|
||||||
|
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
|
bind_group_layouts: bind_group_layouts.as_slice(),
|
||||||
|
});
|
||||||
|
|
||||||
|
let owned_vertex_buffer_descriptors = layout
|
||||||
|
.vertex_buffer_descriptors
|
||||||
|
.iter()
|
||||||
|
.map(|v| v.wgpu_into())
|
||||||
|
.collect::<Vec<OwnedWgpuVertexBufferDescriptor>>();
|
||||||
|
|
||||||
|
let color_states = pipeline_descriptor
|
||||||
|
.color_states
|
||||||
|
.iter()
|
||||||
|
.map(|c| c.wgpu_into())
|
||||||
|
.collect::<Vec<wgpu::ColorStateDescriptor>>();
|
||||||
|
|
||||||
|
self.create_shader_module(pipeline_descriptor.shader_stages.vertex, shaders);
|
||||||
|
|
||||||
|
if let Some(fragment_handle) = pipeline_descriptor.shader_stages.fragment {
|
||||||
|
self.create_shader_module(fragment_handle, shaders);
|
||||||
|
}
|
||||||
|
|
||||||
|
let shader_modules = self.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(shader_modules.get(&fragment_handle).unwrap()),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let render_pipeline_descriptor = wgpu::RenderPipelineDescriptor {
|
||||||
|
layout: &pipeline_layout,
|
||||||
|
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||||
|
module: &vertex_shader_module,
|
||||||
|
entry_point: "main",
|
||||||
|
},
|
||||||
|
fragment_stage: match pipeline_descriptor.shader_stages.fragment {
|
||||||
|
Some(_) => Some(wgpu::ProgrammableStageDescriptor {
|
||||||
|
entry_point: "main",
|
||||||
|
module: fragment_shader_module.as_ref().unwrap(),
|
||||||
|
}),
|
||||||
|
None => None,
|
||||||
|
},
|
||||||
|
rasterization_state: pipeline_descriptor
|
||||||
|
.rasterization_state
|
||||||
|
.as_ref()
|
||||||
|
.map(|r| r.wgpu_into()),
|
||||||
|
primitive_topology: pipeline_descriptor.primitive_topology.wgpu_into(),
|
||||||
|
color_states: &color_states,
|
||||||
|
depth_stencil_state: pipeline_descriptor
|
||||||
|
.depth_stencil_state
|
||||||
|
.as_ref()
|
||||||
|
.map(|d| d.wgpu_into()),
|
||||||
|
vertex_state: wgpu::VertexStateDescriptor {
|
||||||
|
index_format: pipeline_descriptor.index_format.wgpu_into(),
|
||||||
|
vertex_buffers: &owned_vertex_buffer_descriptors
|
||||||
|
.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,
|
||||||
|
};
|
||||||
|
|
||||||
|
let render_pipeline = self
|
||||||
|
.device
|
||||||
|
.create_render_pipeline(&render_pipeline_descriptor);
|
||||||
|
let mut render_pipelines = self.resources.render_pipelines.write().unwrap();
|
||||||
|
render_pipelines.insert(pipeline_handle, render_pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_bind_group(
|
||||||
|
&self,
|
||||||
|
bind_group_descriptor: &BindGroupDescriptor,
|
||||||
|
render_resource_assignments: &RenderResourceAssignments,
|
||||||
|
) -> Option<RenderResourceSetId> {
|
||||||
|
if let Some((render_resource_set_id, _indices)) =
|
||||||
|
render_resource_assignments.get_render_resource_set_id(bind_group_descriptor.id)
|
||||||
|
{
|
||||||
|
if !self
|
||||||
|
.resources
|
||||||
|
.has_bind_group(bind_group_descriptor.id, *render_resource_set_id)
|
||||||
|
{
|
||||||
|
log::trace!(
|
||||||
|
"start creating bind group for RenderResourceSet {:?}",
|
||||||
|
render_resource_set_id
|
||||||
|
);
|
||||||
|
let texture_views = self.resources.texture_views.read().unwrap();
|
||||||
|
let samplers = self.resources.samplers.read().unwrap();
|
||||||
|
let buffers = self.resources.buffers.read().unwrap();
|
||||||
|
let resource_info = self.resources.resource_info.read().unwrap();
|
||||||
|
let bind_group_layouts = self.resources.bind_group_layouts.read().unwrap();
|
||||||
|
let mut bind_groups = self.resources.bind_groups.write().unwrap();
|
||||||
|
|
||||||
|
let bindings = bind_group_descriptor
|
||||||
|
.bindings
|
||||||
|
.iter()
|
||||||
|
.map(|binding| {
|
||||||
|
if let Some(resource) = render_resource_assignments.get(&binding.name) {
|
||||||
|
let info = resource_info
|
||||||
|
.get(&resource)
|
||||||
|
.expect("referenced resource does not exist");
|
||||||
|
log::trace!(
|
||||||
|
"found binding {} ({}) resource: {:?} {:?}",
|
||||||
|
binding.index,
|
||||||
|
binding.name,
|
||||||
|
resource,
|
||||||
|
resource_info
|
||||||
|
);
|
||||||
|
let wgpu_resource = match &binding.bind_type {
|
||||||
|
BindType::SampledTexture { .. } => {
|
||||||
|
if let ResourceInfo::Texture = info {
|
||||||
|
let texture = texture_views.get(&resource).unwrap();
|
||||||
|
wgpu::BindingResource::TextureView(texture)
|
||||||
|
} else {
|
||||||
|
panic!("expected a Texture resource");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BindType::Sampler { .. } => {
|
||||||
|
if let ResourceInfo::Sampler = info {
|
||||||
|
let sampler = samplers.get(&resource).unwrap();
|
||||||
|
wgpu::BindingResource::Sampler(sampler)
|
||||||
|
} else {
|
||||||
|
panic!("expected a Sampler resource");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BindType::Uniform { .. } => {
|
||||||
|
if let ResourceInfo::Buffer(buffer_info) = info {
|
||||||
|
let buffer = buffers.get(&resource).unwrap();
|
||||||
|
wgpu::BindingResource::Buffer {
|
||||||
|
buffer,
|
||||||
|
range: 0..buffer_info.size as u64,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("expected a Buffer resource");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!("unsupported bind type"),
|
||||||
|
};
|
||||||
|
wgpu::Binding {
|
||||||
|
binding: binding.index,
|
||||||
|
resource: wgpu_resource,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!(
|
||||||
|
"No resource assigned to uniform \"{}\" for RenderResourceAssignments {:?}",
|
||||||
|
binding.name,
|
||||||
|
render_resource_assignments.id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<wgpu::Binding>>();
|
||||||
|
|
||||||
|
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(),
|
||||||
|
};
|
||||||
|
let wgpu_bind_group = self.device.create_bind_group(&wgpu_bind_group_descriptor);
|
||||||
|
|
||||||
|
let bind_group_info = bind_groups
|
||||||
|
.entry(bind_group_descriptor.id)
|
||||||
|
.or_insert_with(|| WgpuBindGroupInfo::default());
|
||||||
|
bind_group_info
|
||||||
|
.bind_groups
|
||||||
|
.insert(*render_resource_set_id, wgpu_bind_group);
|
||||||
|
log::trace!(
|
||||||
|
"created bind group for RenderResourceSet {:?}",
|
||||||
|
render_resource_set_id
|
||||||
|
);
|
||||||
|
return Some(*render_resource_set_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -79,9 +79,7 @@ impl WgpuRenderer {
|
|||||||
let winit_windows = resources.get::<bevy_winit::WinitWindows>().unwrap();
|
let winit_windows = resources.get::<bevy_winit::WinitWindows>().unwrap();
|
||||||
let winit_window = winit_windows.get_window(window.id).unwrap();
|
let winit_window = winit_windows.get_window(window.id).unwrap();
|
||||||
let surface = unsafe { self.instance.create_surface(winit_window.deref()) };
|
let surface = unsafe { self.instance.create_surface(winit_window.deref()) };
|
||||||
render_resource_context
|
render_resource_context.set_window_surface(window.id, surface);
|
||||||
.wgpu_resources
|
|
||||||
.set_window_surface(window.id, surface);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,10 @@
|
|||||||
use crate::{renderer::WgpuRenderResourceContext, wgpu_type_converter::WgpuInto};
|
|
||||||
use bevy_asset::{Handle, HandleUntyped};
|
use bevy_asset::{Handle, HandleUntyped};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
pipeline::{BindGroupDescriptorId, PipelineDescriptor},
|
pipeline::{BindGroupDescriptorId, PipelineDescriptor},
|
||||||
render_resource::{BufferInfo, RenderResource, RenderResourceSetId, ResourceInfo},
|
render_resource::{RenderResource, RenderResourceSetId, ResourceInfo},
|
||||||
renderer::RenderResourceContext,
|
|
||||||
shader::Shader,
|
shader::Shader,
|
||||||
texture::{Extent3d, SamplerDescriptor, TextureDescriptor},
|
|
||||||
};
|
};
|
||||||
use bevy_window::{Window, WindowId};
|
use bevy_window::WindowId;
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
sync::{Arc, RwLock, RwLockReadGuard},
|
sync::{Arc, RwLock, RwLockReadGuard},
|
||||||
@ -98,57 +95,6 @@ impl WgpuResources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_window_surface(&self, window_id: WindowId, surface: wgpu::Surface) {
|
|
||||||
self.window_surfaces
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.insert(window_id, surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn next_swap_chain_texture(&self, window_id: WindowId) -> RenderResource {
|
|
||||||
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();
|
|
||||||
let render_resource = RenderResource::new();
|
|
||||||
// TODO: Add ResourceInfo
|
|
||||||
self.swap_chain_outputs
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.insert(render_resource, next_texture);
|
|
||||||
render_resource
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove_swap_chain_texture(&self, render_resource: RenderResource) {
|
|
||||||
self.swap_chain_outputs
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.remove(&render_resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove_all_swap_chain_textures(&self) {
|
|
||||||
self.swap_chain_outputs.write().unwrap().clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_window_swap_chain(&self, device: &wgpu::Device, window: &Window) {
|
|
||||||
let swap_chain_descriptor: wgpu::SwapChainDescriptor = window.wgpu_into();
|
|
||||||
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
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.insert(window.id, swap_chain);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_resource_info(&self, resource: RenderResource, resource_info: ResourceInfo) {
|
|
||||||
self.resource_info
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.insert(resource, resource_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn has_bind_group(
|
pub fn has_bind_group(
|
||||||
&self,
|
&self,
|
||||||
bind_group_descriptor_id: BindGroupDescriptorId,
|
bind_group_descriptor_id: BindGroupDescriptorId,
|
||||||
@ -168,324 +114,4 @@ impl WgpuResources {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_bind_group(
|
|
||||||
&self,
|
|
||||||
device: &wgpu::Device,
|
|
||||||
render_resource_set_id: RenderResourceSetId,
|
|
||||||
bind_group_descriptor: &wgpu::BindGroupDescriptor,
|
|
||||||
) -> wgpu::BindGroup {
|
|
||||||
log::trace!(
|
|
||||||
"created bind group for RenderResourceSet {:?}",
|
|
||||||
render_resource_set_id
|
|
||||||
);
|
|
||||||
device.create_bind_group(bind_group_descriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_bind_group(
|
|
||||||
&self,
|
|
||||||
bind_group_descriptor_id: BindGroupDescriptorId,
|
|
||||||
render_resource_set_id: RenderResourceSetId,
|
|
||||||
bind_group: wgpu::BindGroup,
|
|
||||||
) {
|
|
||||||
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
|
|
||||||
.bind_groups
|
|
||||||
.insert(render_resource_set_id, bind_group);
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
usage: buffer_info.buffer_usage.wgpu_into(),
|
|
||||||
});
|
|
||||||
|
|
||||||
let resource = RenderResource::new();
|
|
||||||
self.add_resource_info(resource, ResourceInfo::Buffer(buffer_info));
|
|
||||||
|
|
||||||
self.buffers.write().unwrap().insert(resource, buffer);
|
|
||||||
resource
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_buffer_with_data(
|
|
||||||
&self,
|
|
||||||
device: &wgpu::Device,
|
|
||||||
mut buffer_info: BufferInfo,
|
|
||||||
data: &[u8],
|
|
||||||
) -> RenderResource {
|
|
||||||
buffer_info.size = data.len();
|
|
||||||
let buffer = device.create_buffer_with_data(data, buffer_info.buffer_usage.wgpu_into());
|
|
||||||
self.assign_buffer(buffer, buffer_info)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: taking a closure isn't fantastic. is there any way to make this better without exposing the lock in the interface?
|
|
||||||
pub fn get_resource_info(
|
|
||||||
&self,
|
|
||||||
resource: RenderResource,
|
|
||||||
handle_info: &mut dyn FnMut(Option<&ResourceInfo>),
|
|
||||||
) {
|
|
||||||
let resource_info = self.resource_info.read().unwrap();
|
|
||||||
let info = resource_info.get(&resource);
|
|
||||||
handle_info(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove_buffer(&self, resource: RenderResource) {
|
|
||||||
self.buffers.write().unwrap().remove(&resource);
|
|
||||||
self.resource_info.write().unwrap().remove(&resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
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.write().unwrap().insert(resource, buffer);
|
|
||||||
resource
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: clean this up
|
|
||||||
pub fn begin_create_buffer_mapped_render_context(
|
|
||||||
buffer_info: &BufferInfo,
|
|
||||||
render_resources: &WgpuRenderResourceContext,
|
|
||||||
setup_data: &mut dyn FnMut(&mut [u8], &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(
|
|
||||||
&self,
|
|
||||||
encoder: &mut wgpu::CommandEncoder,
|
|
||||||
source_buffer: RenderResource,
|
|
||||||
source_offset: u64,
|
|
||||||
destination_buffer: RenderResource,
|
|
||||||
destination_offset: u64,
|
|
||||||
size: u64,
|
|
||||||
) {
|
|
||||||
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 copy_buffer_to_texture(
|
|
||||||
&self,
|
|
||||||
encoder: &mut wgpu::CommandEncoder,
|
|
||||||
source_buffer: RenderResource,
|
|
||||||
source_offset: u64,
|
|
||||||
source_bytes_per_row: u32,
|
|
||||||
destination_texture: RenderResource,
|
|
||||||
destination_origin: [u32; 3], // TODO: replace with math type
|
|
||||||
destination_mip_level: u32,
|
|
||||||
destination_array_layer: u32,
|
|
||||||
size: Extent3d,
|
|
||||||
) {
|
|
||||||
let buffers = self.buffers.read().unwrap();
|
|
||||||
let textures = self.textures.read().unwrap();
|
|
||||||
let source = buffers.get(&source_buffer).unwrap();
|
|
||||||
let destination = textures.get(&destination_texture).unwrap();
|
|
||||||
encoder.copy_buffer_to_texture(
|
|
||||||
wgpu::BufferCopyView {
|
|
||||||
buffer: source,
|
|
||||||
offset: source_offset,
|
|
||||||
bytes_per_row: source_bytes_per_row,
|
|
||||||
rows_per_image: 0, // NOTE: Example sets this to 0, but should it be height?
|
|
||||||
},
|
|
||||||
wgpu::TextureCopyView {
|
|
||||||
texture: destination,
|
|
||||||
mip_level: destination_mip_level,
|
|
||||||
array_layer: destination_array_layer,
|
|
||||||
origin: wgpu::Origin3d {
|
|
||||||
x: destination_origin[0],
|
|
||||||
y: destination_origin[1],
|
|
||||||
z: destination_origin[2],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
size.wgpu_into(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_shader_module(
|
|
||||||
&self,
|
|
||||||
device: &wgpu::Device,
|
|
||||||
shader_handle: Handle<Shader>,
|
|
||||||
shader: &Shader,
|
|
||||||
) {
|
|
||||||
let shader_module = device.create_shader_module(&shader.get_spirv(None));
|
|
||||||
self.shader_modules
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.insert(shader_handle, shader_module);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_sampler(
|
|
||||||
&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.write().unwrap().insert(resource, sampler);
|
|
||||||
self.add_resource_info(resource, ResourceInfo::Sampler);
|
|
||||||
resource
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_texture(
|
|
||||||
&self,
|
|
||||||
device: &wgpu::Device,
|
|
||||||
texture_descriptor: &TextureDescriptor,
|
|
||||||
) -> RenderResource {
|
|
||||||
let descriptor: wgpu::TextureDescriptor = (*texture_descriptor).wgpu_into();
|
|
||||||
let texture = device.create_texture(&descriptor);
|
|
||||||
let texture_view = texture.create_default_view();
|
|
||||||
let resource = RenderResource::new();
|
|
||||||
self.add_resource_info(resource, ResourceInfo::Texture);
|
|
||||||
self.texture_views
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.insert(resource, texture_view);
|
|
||||||
self.textures.write().unwrap().insert(resource, texture);
|
|
||||||
resource
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_texture_with_data(
|
|
||||||
&self,
|
|
||||||
device: &wgpu::Device,
|
|
||||||
encoder: &mut wgpu::CommandEncoder,
|
|
||||||
texture_descriptor: &TextureDescriptor,
|
|
||||||
bytes: &[u8],
|
|
||||||
) -> RenderResource {
|
|
||||||
let descriptor: wgpu::TextureDescriptor = (*texture_descriptor).wgpu_into();
|
|
||||||
let texture = device.create_texture(&descriptor);
|
|
||||||
let texture_view = texture.create_default_view();
|
|
||||||
let temp_buf = device.create_buffer_with_data(bytes, wgpu::BufferUsage::COPY_SRC);
|
|
||||||
encoder.copy_buffer_to_texture(
|
|
||||||
wgpu::BufferCopyView {
|
|
||||||
buffer: &temp_buf,
|
|
||||||
offset: 0,
|
|
||||||
bytes_per_row: 4 * descriptor.size.width,
|
|
||||||
rows_per_image: 0, // NOTE: Example sets this to 0, but should it be height?
|
|
||||||
},
|
|
||||||
wgpu::TextureCopyView {
|
|
||||||
texture: &texture,
|
|
||||||
mip_level: 0,
|
|
||||||
array_layer: 0,
|
|
||||||
origin: wgpu::Origin3d { x: 0, y: 0, z: 0 },
|
|
||||||
},
|
|
||||||
descriptor.size,
|
|
||||||
);
|
|
||||||
|
|
||||||
let resource = RenderResource::new();
|
|
||||||
self.add_resource_info(resource, ResourceInfo::Texture);
|
|
||||||
self.texture_views
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.insert(resource, texture_view);
|
|
||||||
resource
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove_texture(&self, resource: RenderResource) {
|
|
||||||
self.texture_views.write().unwrap().remove(&resource);
|
|
||||||
self.textures.write().unwrap().remove(&resource);
|
|
||||||
self.resource_info.write().unwrap().remove(&resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove_sampler(&self, resource: RenderResource) {
|
|
||||||
self.samplers.write().unwrap().remove(&resource);
|
|
||||||
self.resource_info.write().unwrap().remove(&resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_asset_resource<T>(
|
|
||||||
&mut self,
|
|
||||||
handle: Handle<T>,
|
|
||||||
render_resource: RenderResource,
|
|
||||||
index: usize,
|
|
||||||
) where
|
|
||||||
T: 'static,
|
|
||||||
{
|
|
||||||
self.asset_resources
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.insert((handle.into(), index), render_resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_asset_resource<T>(
|
|
||||||
&mut self,
|
|
||||||
handle: Handle<T>,
|
|
||||||
index: usize,
|
|
||||||
) -> Option<RenderResource>
|
|
||||||
where
|
|
||||||
T: 'static,
|
|
||||||
{
|
|
||||||
self.asset_resources
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.get(&(handle.into(), index))
|
|
||||||
.cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_asset_resource_untyped(
|
|
||||||
&self,
|
|
||||||
handle: HandleUntyped,
|
|
||||||
render_resource: RenderResource,
|
|
||||||
index: usize,
|
|
||||||
) {
|
|
||||||
self.asset_resources
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.insert((handle, index), render_resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_asset_resource_untyped(
|
|
||||||
&self,
|
|
||||||
handle: HandleUntyped,
|
|
||||||
index: usize,
|
|
||||||
) -> Option<RenderResource> {
|
|
||||||
self.asset_resources
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.get(&(handle, index))
|
|
||||||
.cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_bind_group_layout(
|
|
||||||
&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);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_render_pipeline(
|
|
||||||
&self,
|
|
||||||
device: &wgpu::Device,
|
|
||||||
descriptor: &wgpu::RenderPipelineDescriptor,
|
|
||||||
) -> wgpu::RenderPipeline {
|
|
||||||
device.create_render_pipeline(&descriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_render_pipeline(
|
|
||||||
&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