Skip to content

Commit

Permalink
Fix oit webgl (#15728)
Browse files Browse the repository at this point in the history
The previous fixes were breaking pretty much everything on main due to
naga-oil complaining about the OIT shader not being loaded, since
apparently webgl is a default feature. This fix is a bit messier, but
properly warns the user and is probably what we should have gone for in
the first place.
  • Loading branch information
tychedelia authored Oct 8, 2024
1 parent 320d53c commit b48f9e2
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 38 deletions.
3 changes: 0 additions & 3 deletions crates/bevy_core_pipeline/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ use crate::{
use bevy_app::{App, Plugin};
use bevy_asset::load_internal_asset;
use bevy_render::prelude::Shader;
#[cfg(not(feature = "webgl"))]
use oit::OrderIndependentTransparencyPlugin;

#[derive(Default)]
Expand Down Expand Up @@ -110,8 +109,6 @@ impl Plugin for CorePipelinePlugin {
DepthOfFieldPlugin,
SmaaPlugin,
PostProcessingPlugin,
// DownlevelFlags::FRAGMENT_WRITABLE_STORAGE is required for OIT
#[cfg(not(feature = "webgl"))]
OrderIndependentTransparencyPlugin,
));
}
Expand Down
51 changes: 29 additions & 22 deletions crates/bevy_core_pipeline/src/oit/resolve/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
use crate::{
fullscreen_vertex_shader::fullscreen_shader_vertex_state,
oit::OrderIndependentTransparencySettings,
};
use bevy_app::Plugin;
use bevy_asset::{load_internal_asset, Handle};
use bevy_derive::Deref;
Expand All @@ -9,20 +13,16 @@ use bevy_render::{
render_resource::{
binding_types::{storage_buffer_sized, texture_depth_2d, uniform_buffer},
BindGroup, BindGroupEntries, BindGroupLayout, BindGroupLayoutEntries, BlendComponent,
BlendState, CachedRenderPipelineId, ColorTargetState, ColorWrites, FragmentState,
MultisampleState, PipelineCache, PrimitiveState, RenderPipelineDescriptor, Shader,
ShaderStages, TextureFormat,
BlendState, CachedRenderPipelineId, ColorTargetState, ColorWrites, DownlevelFlags,
FragmentState, MultisampleState, PipelineCache, PrimitiveState, RenderPipelineDescriptor,
Shader, ShaderStages, TextureFormat,
},
renderer::RenderDevice,
renderer::{RenderAdapter, RenderDevice},
texture::BevyDefault,
view::{ExtractedView, ViewTarget, ViewUniform, ViewUniforms},
Render, RenderApp, RenderSet,
};

use crate::{
fullscreen_vertex_shader::fullscreen_shader_vertex_state,
oit::OrderIndependentTransparencySettings,
};
use bevy_utils::tracing::warn;

use super::OitBuffers;

Expand All @@ -42,26 +42,33 @@ impl Plugin for OitResolvePlugin {
"oit_resolve.wgsl",
Shader::from_wgsl
);

let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
return;
};

render_app.add_systems(
Render,
(
queue_oit_resolve_pipeline.in_set(RenderSet::Queue),
prepare_oit_resolve_bind_group.in_set(RenderSet::PrepareBindGroups),
),
);
}

fn finish(&self, app: &mut bevy_app::App) {
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
return;
};

render_app.init_resource::<OitResolvePipeline>();
if !render_app
.world()
.resource::<RenderAdapter>()
.get_downlevel_capabilities()
.flags
.contains(DownlevelFlags::FRAGMENT_WRITABLE_STORAGE)
{
warn!("OrderIndependentTransparencyPlugin not loaded. GPU lacks support: DownlevelFlags::FRAGMENT_WRITABLE_STORAGE.");
return;
}

render_app
.add_systems(
Render,
(
queue_oit_resolve_pipeline.in_set(RenderSet::Queue),
prepare_oit_resolve_bind_group.in_set(RenderSet::PrepareBindGroups),
),
)
.init_resource::<OitResolvePipeline>();
}
}

Expand Down
37 changes: 26 additions & 11 deletions crates/bevy_pbr/src/render/mesh_view_bindings.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use alloc::sync::Arc;
use core::{array, num::NonZero};

use bevy_core_pipeline::{
core_3d::ViewTransmissionTexture,
oit::{OitBuffers, OrderIndependentTransparencySettings},
Expand Down Expand Up @@ -29,9 +27,11 @@ use bevy_render::{
VISIBILITY_RANGES_STORAGE_BUFFER_COUNT,
},
};
use core::{array, num::NonZero};

#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
use bevy_render::render_resource::binding_types::texture_cube;
use bevy_render::renderer::RenderAdapter;
#[cfg(debug_assertions)]
use bevy_utils::warn_once;
use environment_map::EnvironmentMapLight;
Expand Down Expand Up @@ -194,6 +194,7 @@ fn layout_entries(
visibility_ranges_buffer_binding_type: BufferBindingType,
layout_key: MeshPipelineViewLayoutKey,
render_device: &RenderDevice,
render_adapter: &RenderAdapter,
) -> Vec<BindGroupLayoutEntry> {
let mut entries = DynamicBindGroupLayoutEntries::new_with_indices(
ShaderStages::FRAGMENT,
Expand Down Expand Up @@ -358,15 +359,25 @@ fn layout_entries(
));

// OIT
if cfg!(not(feature = "webgl")) && layout_key.contains(MeshPipelineViewLayoutKey::OIT_ENABLED) {
entries = entries.extend_with_indices((
// oit_layers
(31, storage_buffer_sized(false, None)),
// oit_layer_ids,
(32, storage_buffer_sized(false, None)),
// oit_layer_count
(33, uniform_buffer::<i32>(true)),
));
if layout_key.contains(MeshPipelineViewLayoutKey::OIT_ENABLED) {
// Check if the GPU supports writable storage buffers in the fragment shader
// If not, we can't use OIT, so we skip the OIT bindings.
// This is a hack to avoid errors on webgl -- the OIT plugin will warn the user that OIT
// is not supported on their platform, so we don't need to do it here.
if render_adapter
.get_downlevel_capabilities()
.flags
.contains(DownlevelFlags::FRAGMENT_WRITABLE_STORAGE)
{
entries = entries.extend_with_indices((
// oit_layers
(31, storage_buffer_sized(false, None)),
// oit_layer_ids,
(32, storage_buffer_sized(false, None)),
// oit_layer_count
(33, uniform_buffer::<i32>(true)),
));
}
}

entries.to_vec()
Expand All @@ -387,6 +398,7 @@ impl FromWorld for MeshPipelineViewLayouts {
// [`MeshPipelineViewLayoutKey`] flags.

let render_device = world.resource::<RenderDevice>();
let render_adapter = world.resource::<RenderAdapter>();

let clustered_forward_buffer_binding_type = render_device
.get_supported_read_only_binding_type(CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT);
Expand All @@ -400,6 +412,7 @@ impl FromWorld for MeshPipelineViewLayouts {
visibility_ranges_buffer_binding_type,
key,
render_device,
render_adapter,
);
#[cfg(debug_assertions)]
let texture_count: usize = entries
Expand Down Expand Up @@ -436,6 +449,7 @@ impl MeshPipelineViewLayouts {
/// [`MeshPipelineViewLayoutKey`] flags.
pub fn generate_view_layouts(
render_device: &RenderDevice,
render_adapter: &RenderAdapter,
clustered_forward_buffer_binding_type: BufferBindingType,
visibility_ranges_buffer_binding_type: BufferBindingType,
) -> [MeshPipelineViewLayout; MeshPipelineViewLayoutKey::COUNT] {
Expand All @@ -446,6 +460,7 @@ pub fn generate_view_layouts(
visibility_ranges_buffer_binding_type,
key,
render_device,
render_adapter,
);

#[cfg(debug_assertions)]
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_render/src/render_resource/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ pub use wgpu::{
BufferBinding, BufferBindingType, BufferDescriptor, BufferSize, BufferUsages, ColorTargetState,
ColorWrites, CommandEncoder, CommandEncoderDescriptor, CompareFunction, ComputePass,
ComputePassDescriptor, ComputePipelineDescriptor as RawComputePipelineDescriptor,
DepthBiasState, DepthStencilState, Extent3d, Face, Features as WgpuFeatures, FilterMode,
FragmentState as RawFragmentState, FrontFace, ImageCopyBuffer, ImageCopyBufferBase,
DepthBiasState, DepthStencilState, DownlevelFlags, Extent3d, Face, Features as WgpuFeatures,
FilterMode, FragmentState as RawFragmentState, FrontFace, ImageCopyBuffer, ImageCopyBufferBase,
ImageCopyTexture, ImageCopyTextureBase, ImageDataLayout, ImageSubresourceRange, IndexFormat,
Limits as WgpuLimits, LoadOp, Maintain, MapMode, MultisampleState, Operations, Origin3d,
PipelineCompilationOptions, PipelineLayout, PipelineLayoutDescriptor, PolygonMode,
Expand Down

0 comments on commit b48f9e2

Please sign in to comment.