Skip to content

Commit

Permalink
webgl2_renderer
Browse files Browse the repository at this point in the history
  • Loading branch information
mrk-its committed Oct 11, 2020
1 parent 0408ed6 commit 7e4f88b
Show file tree
Hide file tree
Showing 35 changed files with 1,988 additions and 149 deletions.
16 changes: 15 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ default = [
"mp3",
"x11",
]

web = [
"bevy_webgl2",
"bevy_winit",
"render",
"bevy_sprite",
"png",
"bevy_text",
"bevy_ui",
]

profiler = ["bevy_ecs/profiler", "bevy_diagnostic/profiler"]
wgpu_trace = ["bevy_wgpu/trace"]

Expand Down Expand Up @@ -80,18 +91,21 @@ bevy_sprite = { path = "crates/bevy_sprite", optional = true, version = "0.2.1"
bevy_text = { path = "crates/bevy_text", optional = true, version = "0.2.1" }
bevy_ui = { path = "crates/bevy_ui", optional = true, version = "0.2.1" }
bevy_wgpu = { path = "crates/bevy_wgpu", optional = true, version = "0.2.1" }
bevy_webgl2 = { path = "crates/bevy_webgl2", optional = true, version = "0.2.1" }
bevy_winit = { path = "crates/bevy_winit", optional = true, version = "0.2.1" }
bevy_gilrs = { path = "crates/bevy_gilrs", optional = true, version = "0.2.1" }
log = { version = "0.4", features = ["release_max_level_info"] }

[dev-dependencies]
rand = "0.7.3"
serde = { version = "1", features = ["derive"] }
log = "0.4"
ron = "0.6"
anyhow = "1.0"
env_logger = "0.7"
console_error_panic_hook = "0.1.6"

[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
console_error_panic_hook = "0.1.6"
console_log = { version = "0.2", features = ["color"] }

[[example]]
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion crates/bevy_asset/src/asset_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ impl AssetServer {

#[cfg(target_arch = "wasm32")]
fn get_root_path(&self) -> Result<PathBuf, AssetServerError> {
Ok(PathBuf::from("/"))
Ok(PathBuf::from("."))
}

// TODO: add type checking here. people shouldn't be able to request a Handle<Texture> for a Mesh asset
Expand Down
6 changes: 4 additions & 2 deletions crates/bevy_render/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ bevy_window = { path = "../bevy_window", version = "0.2.1" }
bevy_utils = { path = "../bevy_utils", version = "0.2.1" }

# rendering
spirv-reflect = "0.2.3"
image = { version = "0.23", default-features = false }

# misc
Expand All @@ -45,7 +44,10 @@ hex = "0.4.2"
hexasphere = "1.0.0"
parking_lot = "0.11.0"

[target.'cfg(not(target_os = "ios"))'.dependencies]
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
spirv-reflect = "0.2.3"

[target.'cfg(all(not(target_os = "ios"), not(target_arch = "wasm32")))'.dependencies]
bevy-glsl-to-spirv = "0.1.7"

[target.'cfg(target_os = "ios")'.dependencies]
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_render/src/pipeline/pipeline_compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ impl PipelineCompiler {

let specialized_pipeline_handle = pipelines.add(specialized_descriptor);
render_resource_context.create_render_pipeline(
source_pipeline,
specialized_pipeline_handle,
pipelines.get(&specialized_pipeline_handle).unwrap(),
&shaders,
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_render/src/pipeline/render_pipelines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ pub fn draw_render_pipelines_system(
.set_bind_groups_from_bindings(
&mut draw,
&mut [
&mut render_pipelines.bindings,
&mut render_pipelines.bindings, // memory leak!
&mut render_resource_bindings,
],
)
Expand Down
66 changes: 35 additions & 31 deletions crates/bevy_render/src/pipeline/vertex_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,40 +35,44 @@ pub enum VertexFormat {
}

impl VertexFormat {
pub fn get_size(&self) -> u64 {
pub fn get_sizes(&self) -> (i32, i32) {
match *self {
VertexFormat::Uchar2 => 2,
VertexFormat::Uchar4 => 4,
VertexFormat::Char2 => 2,
VertexFormat::Char4 => 4,
VertexFormat::Uchar2Norm => 2,
VertexFormat::Uchar4Norm => 4,
VertexFormat::Char2Norm => 2,
VertexFormat::Char4Norm => 4,
VertexFormat::Ushort2 => 2 * 2,
VertexFormat::Ushort4 => 2 * 4,
VertexFormat::Short2 => 2 * 2,
VertexFormat::Short4 => 2 * 4,
VertexFormat::Ushort2Norm => 2 * 2,
VertexFormat::Ushort4Norm => 2 * 4,
VertexFormat::Short2Norm => 2 * 2,
VertexFormat::Short4Norm => 2 * 4,
VertexFormat::Half2 => 2 * 2,
VertexFormat::Half4 => 2 * 4,
VertexFormat::Float => 4,
VertexFormat::Float2 => 4 * 2,
VertexFormat::Float3 => 4 * 3,
VertexFormat::Float4 => 4 * 4,
VertexFormat::Uint => 4,
VertexFormat::Uint2 => 4 * 2,
VertexFormat::Uint3 => 4 * 3,
VertexFormat::Uint4 => 4 * 4,
VertexFormat::Int => 4,
VertexFormat::Int2 => 4 * 2,
VertexFormat::Int3 => 4 * 3,
VertexFormat::Int4 => 4 * 4,
VertexFormat::Uchar2 => (1, 2),
VertexFormat::Uchar4 => (1, 4),
VertexFormat::Char2 => (1, 2),
VertexFormat::Char4 => (1, 4),
VertexFormat::Uchar2Norm => (1, 2),
VertexFormat::Uchar4Norm => (1, 4),
VertexFormat::Char2Norm => (1, 2),
VertexFormat::Char4Norm => (1, 4),
VertexFormat::Ushort2 => (2, 2),
VertexFormat::Ushort4 => (2, 4),
VertexFormat::Short2 => (2, 2),
VertexFormat::Short4 => (2, 4),
VertexFormat::Ushort2Norm => (2, 2),
VertexFormat::Ushort4Norm => (2, 4),
VertexFormat::Short2Norm => (2, 2),
VertexFormat::Short4Norm => (2, 4),
VertexFormat::Half2 => (2, 2),
VertexFormat::Half4 => (2, 4),
VertexFormat::Float => (4, 1),
VertexFormat::Float2 => (4, 2),
VertexFormat::Float3 => (4, 3),
VertexFormat::Float4 => (4, 4),
VertexFormat::Uint => (4, 1),
VertexFormat::Uint2 => (4, 2),
VertexFormat::Uint3 => (4, 3),
VertexFormat::Uint4 => (4, 4),
VertexFormat::Int => (4, 1),
VertexFormat::Int2 => (4, 2),
VertexFormat::Int3 => (4, 3),
VertexFormat::Int4 => (4, 4),
}
}
pub fn get_size(&self) -> u64 {
let (component_size, components) = self.get_sizes();
return (component_size * components) as u64;
}
}

pub trait AsVertexFormats {
Expand Down
115 changes: 56 additions & 59 deletions crates/bevy_render/src/render_graph/nodes/render_resources_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@ use bevy_utils::HashMap;
use renderer::{AssetRenderResourceBindings, BufferId, RenderResourceType, RenderResources};
use std::{hash::Hash, marker::PhantomData, ops::DerefMut};

pub const BIND_BUFFER_ALIGNMENT: usize = 256;

fn get_aligned_dynamic_uniform_size(data_size: usize) -> usize {
BIND_BUFFER_ALIGNMENT * ((data_size as f32 / BIND_BUFFER_ALIGNMENT as f32).ceil() as usize)
}

#[derive(Debug)]
struct QueuedBufferWrite {
buffer: BufferId,
Expand All @@ -44,13 +38,9 @@ struct BufferArray<I> {
}

impl<I: Hash + Eq> BufferArray<I> {
pub fn new(item_size: usize, min_capacity: usize, align: bool) -> Self {
pub fn new(item_size: usize, min_capacity: usize) -> Self {
BufferArray {
item_size: if align {
get_aligned_dynamic_uniform_size(item_size)
} else {
item_size
},
item_size,
len: 0,
buffer_capacity: 0,
min_capacity,
Expand Down Expand Up @@ -160,13 +150,19 @@ where
T: renderer::RenderResources,
{
/// Initialize this UniformBufferArrays using information from a RenderResources value.
fn initialize(&mut self, render_resources: &T) {
fn initialize(
&mut self,
render_resources: &T,
render_resource_context: &dyn RenderResourceContext,
) {
if self.buffer_arrays.len() != render_resources.render_resources_len() {
let mut buffer_arrays = Vec::with_capacity(render_resources.render_resources_len());
for render_resource in render_resources.iter() {
if let Some(RenderResourceType::Buffer) = render_resource.resource_type() {
let size = render_resource.buffer_byte_len().unwrap();
buffer_arrays.push(Some(BufferArray::new(size, 10, true)));
let aligned_size =
render_resource_context.get_aligned_dynamic_uniform_size(size);
buffer_arrays.push(Some(BufferArray::new(aligned_size, 10)));
} else {
buffer_arrays.push(None);
}
Expand All @@ -183,13 +179,21 @@ where
}

/// Find a spot for the given RenderResources in each uniform's BufferArray and prepare space in the staging buffer
fn prepare_uniform_buffers(&mut self, id: I, render_resources: &T) {
fn prepare_uniform_buffers(
&mut self,
id: I,
render_resources: &T,
render_resource_context: &dyn RenderResourceContext,
) {
for (i, render_resource) in render_resources.iter().enumerate() {
let render_resource_name = render_resources.get_render_resource_name(i).unwrap();
if let Some(RenderResourceType::Buffer) = render_resource.resource_type() {
let size = render_resource.buffer_byte_len().unwrap();
let aligned_size = render_resource_context
.get_aligned_uniform_size(size, Some(render_resource_name));
if let Some(buffer_array) = &mut self.buffer_arrays[i] {
buffer_array.get_or_assign_index(id);
self.required_staging_buffer_size += size;
self.required_staging_buffer_size += aligned_size;
}
}
}
Expand Down Expand Up @@ -249,8 +253,10 @@ where
Some(RenderResourceType::Buffer) => {
let size = render_resource.buffer_byte_len().unwrap();
let render_resource_name = uniforms.get_render_resource_name(i).unwrap();
let aligned_size = render_resource_context
.get_aligned_uniform_size(size, Some(render_resource_name));
let buffer_array = self.buffer_arrays[i].as_mut().unwrap();
let range = 0..size as u64;
let range = 0..aligned_size as u64;
let (target_buffer, target_offset) = if dynamic_uniforms {
let binding = buffer_array.get_binding(id).unwrap();
let dynamic_index = if let RenderResourceBinding::Buffer {
Expand All @@ -272,7 +278,7 @@ where
size: current_size, ..
}) = render_resource_context.get_buffer_info(buffer_id)
{
if size == current_size {
if aligned_size == current_size {
matching_buffer = Some(buffer_id);
} else {
render_resource_context.remove_buffer(buffer_id);
Expand All @@ -293,7 +299,7 @@ where
}

let buffer = render_resource_context.create_buffer(BufferInfo {
size,
size: aligned_size,
buffer_usage: BufferUsage::COPY_DST | usage,
..Default::default()
});
Expand Down Expand Up @@ -323,7 +329,7 @@ where
source_offset: self.current_staging_buffer_offset,
size,
});
self.current_staging_buffer_offset += size;
self.current_staging_buffer_offset += aligned_size;
}
Some(RenderResourceType::Texture) => { /* ignore textures */ }
Some(RenderResourceType::Sampler) => { /* ignore samplers */ }
Expand Down Expand Up @@ -433,8 +439,14 @@ fn render_resources_node_system<T: RenderResources>(
let render_resource_context = &**render_resource_context;
uniform_buffer_arrays.begin_update();
// initialize uniform buffer arrays using the first RenderResources
if let Some((_, first, _, _)) = query.iter().iter().next() {
uniform_buffer_arrays.initialize(first);
match query.iter().iter().next() {
Some((_, first, _, render_pipelines)) => {
if !render_pipelines_exist(render_resource_context, &*render_pipelines) {
return;
}
uniform_buffer_arrays.initialize(first, render_resource_context);
}
None => return,
}

for entity in query.removed::<T>() {
Expand All @@ -446,7 +458,7 @@ fn render_resources_node_system<T: RenderResources>(
continue;
}

uniform_buffer_arrays.prepare_uniform_buffers(entity, uniforms);
uniform_buffer_arrays.prepare_uniform_buffers(entity, uniforms, render_resource_context);
setup_uniform_texture_resources::<T>(
&uniforms,
render_resource_context,
Expand Down Expand Up @@ -484,23 +496,6 @@ fn render_resources_node_system<T: RenderResources>(
state
.uniform_buffer_arrays
.copy_staging_buffer_to_final_buffers(&mut state.command_queue, staging_buffer);
} else {
// TODO: can we just remove this?
let mut staging_buffer: [u8; 0] = [];
for (entity, uniforms, draw, mut render_pipelines) in &mut query.iter() {
if !draw.is_visible {
continue;
}

state.uniform_buffer_arrays.write_uniform_buffers(
entity,
&uniforms,
state.dynamic_uniforms,
render_resource_context,
&mut render_pipelines.bindings,
&mut staging_buffer,
);
}
}
}

Expand Down Expand Up @@ -574,7 +569,14 @@ fn asset_render_resources_node_system<T: RenderResources>(
let state = state.deref_mut();
let uniform_buffer_arrays = &mut state.uniform_buffer_arrays;
let render_resource_context = &**render_resource_context;

match query.iter().iter().next() {
Some((_, _, render_pipelines)) => {
if !render_pipelines_exist(render_resource_context, &*render_pipelines) {
return;
}
}
None => return,
}
let modified_assets = assets
.iter()
.map(|(handle, _)| handle)
Expand All @@ -584,12 +586,12 @@ fn asset_render_resources_node_system<T: RenderResources>(
// initialize uniform buffer arrays using the first RenderResources
if let Some(first_handle) = modified_assets.get(0) {
let asset = assets.get(first_handle).expect(EXPECT_ASSET_MESSAGE);
uniform_buffer_arrays.initialize(asset);
uniform_buffer_arrays.initialize(asset, render_resource_context);
}

for asset_handle in modified_assets.iter() {
let asset = assets.get(&asset_handle).expect(EXPECT_ASSET_MESSAGE);
uniform_buffer_arrays.prepare_uniform_buffers(*asset_handle, asset);
uniform_buffer_arrays.prepare_uniform_buffers(*asset_handle, asset, render_resource_context);
let mut bindings = asset_render_resource_bindings.get_or_insert_mut(*asset_handle);
setup_uniform_texture_resources::<T>(&asset, render_resource_context, &mut bindings);
}
Expand Down Expand Up @@ -624,22 +626,6 @@ fn asset_render_resources_node_system<T: RenderResources>(
state
.uniform_buffer_arrays
.copy_staging_buffer_to_final_buffers(&mut state.command_queue, staging_buffer);
} else {
let mut staging_buffer: [u8; 0] = [];
for asset_handle in modified_assets.iter() {
let asset = assets.get(&asset_handle).expect(EXPECT_ASSET_MESSAGE);
let mut render_resource_bindings =
asset_render_resource_bindings.get_or_insert_mut(*asset_handle);
// TODO: only setup buffer if we haven't seen this handle before
state.uniform_buffer_arrays.write_uniform_buffers(
*asset_handle,
&asset,
state.dynamic_uniforms,
render_resource_context,
&mut render_resource_bindings,
&mut staging_buffer,
);
}
}

for (asset_handle, draw, mut render_pipelines) in &mut query.iter() {
Expand Down Expand Up @@ -685,3 +671,14 @@ fn setup_uniform_texture_resources<T>(
}
}
}

fn render_pipelines_exist(
render_resource_context: &dyn RenderResourceContext,
render_pipelines: &RenderPipelines,
) -> bool {
return !render_pipelines.pipelines.is_empty()
&& render_pipelines
.pipelines
.iter()
.all(|f| render_resource_context.render_pipeline_exists(f.pipeline));
}
Loading

0 comments on commit 7e4f88b

Please sign in to comment.