Fix oit webgl (#15728)

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.
This commit is contained in:
charlotte 2024-10-08 07:50:35 -07:00 committed by GitHub
parent 320d53c1d2
commit b48f9e2a4b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 57 additions and 38 deletions

View file

@ -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)]
@ -110,8 +109,6 @@ impl Plugin for CorePipelinePlugin {
DepthOfFieldPlugin,
SmaaPlugin,
PostProcessingPlugin,
// DownlevelFlags::FRAGMENT_WRITABLE_STORAGE is required for OIT
#[cfg(not(feature = "webgl"))]
OrderIndependentTransparencyPlugin,
));
}

View file

@ -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;
@ -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;
@ -42,18 +42,6 @@ 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) {
@ -61,7 +49,26 @@ impl Plugin for OitResolvePlugin {
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>();
}
}

View file

@ -1,6 +1,4 @@
use alloc::sync::Arc;
use core::{array, num::NonZero};
use bevy_core_pipeline::{
core_3d::ViewTransmissionTexture,
oit::{OitBuffers, OrderIndependentTransparencySettings},
@ -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;
@ -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,
@ -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()
@ -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);
@ -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
@ -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] {
@ -446,6 +460,7 @@ pub fn generate_view_layouts(
visibility_ranges_buffer_binding_type,
key,
render_device,
render_adapter,
);
#[cfg(debug_assertions)]

View file

@ -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,