mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Consolidate Render(Ui)Materials(2d) into RenderAssets (#12827)
# Objective - Replace `RenderMaterials` / `RenderMaterials2d` / `RenderUiMaterials` with `RenderAssets` to enable implementing changes to one thing, `RenderAssets`, that applies to all use cases rather than duplicating changes everywhere for multiple things that should be one thing. - Adopts #8149 ## Solution - Make RenderAsset generic over the destination type rather than the source type as in #8149 - Use `RenderAssets<PreparedMaterial<M>>` etc for render materials --- ## Changelog - Changed: - The `RenderAsset` trait is now implemented on the destination type. Its `SourceAsset` associated type refers to the type of the source asset. - `RenderMaterials`, `RenderMaterials2d`, and `RenderUiMaterials` have been replaced by `RenderAssets<PreparedMaterial<M>>` and similar. ## Migration Guide - `RenderAsset` is now implemented for the destination type rather that the source asset type. The source asset type is now the `RenderAsset` trait's `SourceAsset` associated type.
This commit is contained in:
parent
10af274d4e
commit
ab7cbfa8fc
40 changed files with 354 additions and 715 deletions
|
@ -18,7 +18,7 @@ use bevy_render::{
|
|||
*,
|
||||
},
|
||||
renderer::RenderDevice,
|
||||
texture::{BevyDefault, Image},
|
||||
texture::{BevyDefault, GpuImage, Image},
|
||||
view::{ExtractedView, Msaa, ViewTarget, ViewUniform, ViewUniforms},
|
||||
Render, RenderApp, RenderSet,
|
||||
};
|
||||
|
@ -236,7 +236,7 @@ fn prepare_skybox_bind_groups(
|
|||
pipeline: Res<SkyboxPipeline>,
|
||||
view_uniforms: Res<ViewUniforms>,
|
||||
skybox_uniforms: Res<ComponentUniforms<SkyboxUniforms>>,
|
||||
images: Res<RenderAssets<Image>>,
|
||||
images: Res<RenderAssets<GpuImage>>,
|
||||
render_device: Res<RenderDevice>,
|
||||
views: Query<(Entity, &Skybox, &DynamicUniformIndex<SkyboxUniforms>)>,
|
||||
) {
|
||||
|
|
|
@ -10,7 +10,7 @@ use bevy_render::render_resource::binding_types::{
|
|||
sampler, texture_2d, texture_3d, uniform_buffer,
|
||||
};
|
||||
use bevy_render::renderer::RenderDevice;
|
||||
use bevy_render::texture::{CompressedImageFormats, Image, ImageSampler, ImageType};
|
||||
use bevy_render::texture::{CompressedImageFormats, GpuImage, Image, ImageSampler, ImageType};
|
||||
use bevy_render::view::{ViewTarget, ViewUniform};
|
||||
use bevy_render::{camera::Camera, texture::FallbackImage};
|
||||
use bevy_render::{render_resource::*, Render, RenderApp, RenderSet};
|
||||
|
@ -319,7 +319,7 @@ pub enum DebandDither {
|
|||
}
|
||||
|
||||
pub fn get_lut_bindings<'a>(
|
||||
images: &'a RenderAssets<Image>,
|
||||
images: &'a RenderAssets<GpuImage>,
|
||||
tonemapping_luts: &'a TonemappingLuts,
|
||||
tonemapping: &Tonemapping,
|
||||
fallback_image: &'a FallbackImage,
|
||||
|
|
|
@ -11,7 +11,7 @@ use bevy_render::{
|
|||
RenderPassColorAttachment, RenderPassDescriptor, StoreOp, TextureViewId,
|
||||
},
|
||||
renderer::RenderContext,
|
||||
texture::{FallbackImage, Image},
|
||||
texture::{FallbackImage, GpuImage},
|
||||
view::{ViewTarget, ViewUniformOffset, ViewUniforms},
|
||||
};
|
||||
|
||||
|
@ -42,7 +42,7 @@ impl ViewNode for TonemappingNode {
|
|||
) -> Result<(), NodeRunError> {
|
||||
let pipeline_cache = world.resource::<PipelineCache>();
|
||||
let tonemapping_pipeline = world.resource::<TonemappingPipeline>();
|
||||
let gpu_images = world.get_resource::<RenderAssets<Image>>().unwrap();
|
||||
let gpu_images = world.get_resource::<RenderAssets<GpuImage>>().unwrap();
|
||||
let fallback_image = world.resource::<FallbackImage>();
|
||||
let view_uniforms_resource = world.resource::<ViewUniforms>();
|
||||
let view_uniforms = &view_uniforms_resource.uniforms;
|
||||
|
|
|
@ -79,9 +79,7 @@ use bevy_math::Vec3;
|
|||
use bevy_reflect::TypePath;
|
||||
use bevy_render::{
|
||||
extract_component::{ComponentUniforms, DynamicUniformIndex, UniformComponentPlugin},
|
||||
render_asset::{
|
||||
PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssetUsages, RenderAssets,
|
||||
},
|
||||
render_asset::{PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssets},
|
||||
render_phase::{PhaseItem, RenderCommand, RenderCommandResult, TrackedRenderPass},
|
||||
render_resource::{
|
||||
binding_types::uniform_buffer, BindGroup, BindGroupEntries, BindGroupLayout,
|
||||
|
@ -129,7 +127,7 @@ impl Plugin for GizmoPlugin {
|
|||
.register_type::<GizmoConfigStore>()
|
||||
.add_plugins(UniformComponentPlugin::<LineGizmoUniform>::default())
|
||||
.init_asset::<LineGizmo>()
|
||||
.add_plugins(RenderAssetPlugin::<LineGizmo>::default())
|
||||
.add_plugins(RenderAssetPlugin::<GpuLineGizmo>::default())
|
||||
.init_resource::<LineGizmoHandles>()
|
||||
// We insert the Resource GizmoConfigStore into the world implicitly here if it does not exist.
|
||||
.init_gizmo_group::<DefaultGizmoConfigGroup>()
|
||||
|
@ -377,26 +375,22 @@ struct GpuLineGizmo {
|
|||
joints: GizmoLineJoint,
|
||||
}
|
||||
|
||||
impl RenderAsset for LineGizmo {
|
||||
type PreparedAsset = GpuLineGizmo;
|
||||
impl RenderAsset for GpuLineGizmo {
|
||||
type SourceAsset = LineGizmo;
|
||||
type Param = SRes<RenderDevice>;
|
||||
|
||||
fn asset_usage(&self) -> RenderAssetUsages {
|
||||
RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD
|
||||
}
|
||||
|
||||
fn prepare_asset(
|
||||
self,
|
||||
gizmo: Self::SourceAsset,
|
||||
render_device: &mut SystemParamItem<Self::Param>,
|
||||
) -> Result<Self::PreparedAsset, PrepareAssetError<Self>> {
|
||||
let position_buffer_data = cast_slice(&self.positions);
|
||||
) -> Result<Self, PrepareAssetError<Self::SourceAsset>> {
|
||||
let position_buffer_data = cast_slice(&gizmo.positions);
|
||||
let position_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor {
|
||||
usage: BufferUsages::VERTEX,
|
||||
label: Some("LineGizmo Position Buffer"),
|
||||
contents: position_buffer_data,
|
||||
});
|
||||
|
||||
let color_buffer_data = cast_slice(&self.colors);
|
||||
let color_buffer_data = cast_slice(&gizmo.colors);
|
||||
let color_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor {
|
||||
usage: BufferUsages::VERTEX,
|
||||
label: Some("LineGizmo Color Buffer"),
|
||||
|
@ -406,9 +400,9 @@ impl RenderAsset for LineGizmo {
|
|||
Ok(GpuLineGizmo {
|
||||
position_buffer,
|
||||
color_buffer,
|
||||
vertex_count: self.positions.len() as u32,
|
||||
strip: self.strip,
|
||||
joints: self.joints,
|
||||
vertex_count: gizmo.positions.len() as u32,
|
||||
strip: gizmo.strip,
|
||||
joints: gizmo.joints,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -468,7 +462,7 @@ impl<const I: usize, P: PhaseItem> RenderCommand<P> for SetLineGizmoBindGroup<I>
|
|||
|
||||
struct DrawLineGizmo;
|
||||
impl<P: PhaseItem> RenderCommand<P> for DrawLineGizmo {
|
||||
type Param = SRes<RenderAssets<LineGizmo>>;
|
||||
type Param = SRes<RenderAssets<GpuLineGizmo>>;
|
||||
type ViewQuery = ();
|
||||
type ItemQuery = Read<Handle<LineGizmo>>;
|
||||
|
||||
|
@ -514,7 +508,7 @@ impl<P: PhaseItem> RenderCommand<P> for DrawLineGizmo {
|
|||
|
||||
struct DrawLineJointGizmo;
|
||||
impl<P: PhaseItem> RenderCommand<P> for DrawLineJointGizmo {
|
||||
type Param = SRes<RenderAssets<LineGizmo>>;
|
||||
type Param = SRes<RenderAssets<GpuLineGizmo>>;
|
||||
type ViewQuery = ();
|
||||
type ItemQuery = Read<Handle<LineGizmo>>;
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use crate::{
|
||||
config::{GizmoLineJoint, GizmoLineStyle, GizmoMeshConfig},
|
||||
line_gizmo_vertex_buffer_layouts, line_joint_gizmo_vertex_buffer_layouts, DrawLineGizmo,
|
||||
DrawLineJointGizmo, GizmoRenderSystem, LineGizmo, LineGizmoUniformBindgroupLayout,
|
||||
SetLineGizmoBindGroup, LINE_JOINT_SHADER_HANDLE, LINE_SHADER_HANDLE,
|
||||
DrawLineJointGizmo, GizmoRenderSystem, GpuLineGizmo, LineGizmo,
|
||||
LineGizmoUniformBindgroupLayout, SetLineGizmoBindGroup, LINE_JOINT_SHADER_HANDLE,
|
||||
LINE_SHADER_HANDLE,
|
||||
};
|
||||
use bevy_app::{App, Plugin};
|
||||
use bevy_asset::Handle;
|
||||
|
@ -52,7 +53,7 @@ impl Plugin for LineGizmo2dPlugin {
|
|||
Render,
|
||||
(queue_line_gizmos_2d, queue_line_joint_gizmos_2d)
|
||||
.in_set(GizmoRenderSystem::QueueLineGizmos2d)
|
||||
.after(prepare_assets::<LineGizmo>),
|
||||
.after(prepare_assets::<GpuLineGizmo>),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -253,7 +254,7 @@ fn queue_line_gizmos_2d(
|
|||
pipeline_cache: Res<PipelineCache>,
|
||||
msaa: Res<Msaa>,
|
||||
line_gizmos: Query<(Entity, &Handle<LineGizmo>, &GizmoMeshConfig)>,
|
||||
line_gizmo_assets: Res<RenderAssets<LineGizmo>>,
|
||||
line_gizmo_assets: Res<RenderAssets<GpuLineGizmo>>,
|
||||
mut views: Query<(
|
||||
&ExtractedView,
|
||||
&mut SortedRenderPhase<Transparent2d>,
|
||||
|
@ -306,7 +307,7 @@ fn queue_line_joint_gizmos_2d(
|
|||
pipeline_cache: Res<PipelineCache>,
|
||||
msaa: Res<Msaa>,
|
||||
line_gizmos: Query<(Entity, &Handle<LineGizmo>, &GizmoMeshConfig)>,
|
||||
line_gizmo_assets: Res<RenderAssets<LineGizmo>>,
|
||||
line_gizmo_assets: Res<RenderAssets<GpuLineGizmo>>,
|
||||
mut views: Query<(
|
||||
&ExtractedView,
|
||||
&mut SortedRenderPhase<Transparent2d>,
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use crate::{
|
||||
config::{GizmoLineJoint, GizmoLineStyle, GizmoMeshConfig},
|
||||
line_gizmo_vertex_buffer_layouts, line_joint_gizmo_vertex_buffer_layouts, DrawLineGizmo,
|
||||
DrawLineJointGizmo, GizmoRenderSystem, LineGizmo, LineGizmoUniformBindgroupLayout,
|
||||
SetLineGizmoBindGroup, LINE_JOINT_SHADER_HANDLE, LINE_SHADER_HANDLE,
|
||||
DrawLineJointGizmo, GizmoRenderSystem, GpuLineGizmo, LineGizmo,
|
||||
LineGizmoUniformBindgroupLayout, SetLineGizmoBindGroup, LINE_JOINT_SHADER_HANDLE,
|
||||
LINE_SHADER_HANDLE,
|
||||
};
|
||||
use bevy_app::{App, Plugin};
|
||||
use bevy_asset::Handle;
|
||||
|
@ -51,7 +52,7 @@ impl Plugin for LineGizmo3dPlugin {
|
|||
Render,
|
||||
(queue_line_gizmos_3d, queue_line_joint_gizmos_3d)
|
||||
.in_set(GizmoRenderSystem::QueueLineGizmos3d)
|
||||
.after(prepare_assets::<LineGizmo>),
|
||||
.after(prepare_assets::<GpuLineGizmo>),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -278,7 +279,7 @@ fn queue_line_gizmos_3d(
|
|||
pipeline_cache: Res<PipelineCache>,
|
||||
msaa: Res<Msaa>,
|
||||
line_gizmos: Query<(Entity, &Handle<LineGizmo>, &GizmoMeshConfig)>,
|
||||
line_gizmo_assets: Res<RenderAssets<LineGizmo>>,
|
||||
line_gizmo_assets: Res<RenderAssets<GpuLineGizmo>>,
|
||||
mut views: Query<(
|
||||
&ExtractedView,
|
||||
&mut SortedRenderPhase<Transparent3d>,
|
||||
|
@ -361,7 +362,7 @@ fn queue_line_joint_gizmos_3d(
|
|||
pipeline_cache: Res<PipelineCache>,
|
||||
msaa: Res<Msaa>,
|
||||
line_gizmos: Query<(Entity, &Handle<LineGizmo>, &GizmoMeshConfig)>,
|
||||
line_gizmo_assets: Res<RenderAssets<LineGizmo>>,
|
||||
line_gizmo_assets: Res<RenderAssets<GpuLineGizmo>>,
|
||||
mut views: Query<(
|
||||
&ExtractedView,
|
||||
&mut SortedRenderPhase<Transparent3d>,
|
||||
|
|
|
@ -8,7 +8,7 @@ use bevy_render::{
|
|||
ShaderRef, SpecializedMeshPipelineError, UnpreparedBindGroup,
|
||||
},
|
||||
renderer::RenderDevice,
|
||||
texture::{FallbackImage, Image},
|
||||
texture::{FallbackImage, GpuImage},
|
||||
};
|
||||
|
||||
use crate::{Material, MaterialPipeline, MaterialPipelineKey, MeshPipeline, MeshPipelineKey};
|
||||
|
@ -139,7 +139,7 @@ impl<B: Material, E: MaterialExtension> AsBindGroup for ExtendedMaterial<B, E> {
|
|||
&self,
|
||||
layout: &BindGroupLayout,
|
||||
render_device: &RenderDevice,
|
||||
images: &RenderAssets<Image>,
|
||||
images: &RenderAssets<GpuImage>,
|
||||
fallback_image: &FallbackImage,
|
||||
) -> Result<UnpreparedBindGroup<Self::Data>, AsBindGroupError> {
|
||||
// add together the bindings of the base material and the user material
|
||||
|
|
|
@ -95,7 +95,7 @@ use bevy_render::{
|
|||
render_asset::prepare_assets,
|
||||
render_graph::RenderGraph,
|
||||
render_resource::Shader,
|
||||
texture::Image,
|
||||
texture::{GpuImage, Image},
|
||||
view::VisibilitySystems,
|
||||
ExtractSchedule, Render, RenderApp, RenderSet,
|
||||
};
|
||||
|
@ -375,7 +375,7 @@ impl Plugin for PbrPlugin {
|
|||
(
|
||||
prepare_lights
|
||||
.in_set(RenderSet::ManageViews)
|
||||
.after(prepare_assets::<Image>),
|
||||
.after(prepare_assets::<GpuImage>),
|
||||
prepare_clusters.in_set(RenderSet::PrepareResources),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -60,7 +60,7 @@ use bevy_render::{
|
|||
TextureSampleType, TextureView,
|
||||
},
|
||||
renderer::RenderDevice,
|
||||
texture::{FallbackImage, Image},
|
||||
texture::{FallbackImage, GpuImage, Image},
|
||||
};
|
||||
|
||||
use std::num::NonZeroU32;
|
||||
|
@ -213,7 +213,7 @@ impl<'a> RenderViewEnvironmentMapBindGroupEntries<'a> {
|
|||
/// specular binding arrays respectively, as well as the sampler.
|
||||
pub(crate) fn get(
|
||||
render_view_environment_maps: Option<&RenderViewLightProbes<EnvironmentMapLight>>,
|
||||
images: &'a RenderAssets<Image>,
|
||||
images: &'a RenderAssets<GpuImage>,
|
||||
fallback_image: &'a FallbackImage,
|
||||
render_device: &RenderDevice,
|
||||
) -> RenderViewEnvironmentMapBindGroupEntries<'a> {
|
||||
|
@ -283,7 +283,7 @@ impl LightProbeComponent for EnvironmentMapLight {
|
|||
// view.
|
||||
type ViewLightProbeInfo = EnvironmentMapViewLightProbeInfo;
|
||||
|
||||
fn id(&self, image_assets: &RenderAssets<Image>) -> Option<Self::AssetId> {
|
||||
fn id(&self, image_assets: &RenderAssets<GpuImage>) -> Option<Self::AssetId> {
|
||||
if image_assets.get(&self.diffuse_map).is_none()
|
||||
|| image_assets.get(&self.specular_map).is_none()
|
||||
{
|
||||
|
@ -302,7 +302,7 @@ impl LightProbeComponent for EnvironmentMapLight {
|
|||
|
||||
fn create_render_view_light_probes(
|
||||
view_component: Option<&EnvironmentMapLight>,
|
||||
image_assets: &RenderAssets<Image>,
|
||||
image_assets: &RenderAssets<GpuImage>,
|
||||
) -> RenderViewLightProbes<Self> {
|
||||
let mut render_view_light_probes = RenderViewLightProbes::new();
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ use bevy_render::{
|
|||
TextureSampleType, TextureView,
|
||||
},
|
||||
renderer::RenderDevice,
|
||||
texture::{FallbackImage, Image},
|
||||
texture::{FallbackImage, GpuImage, Image},
|
||||
};
|
||||
use std::{num::NonZeroU32, ops::Deref};
|
||||
|
||||
|
@ -212,7 +212,7 @@ impl<'a> RenderViewIrradianceVolumeBindGroupEntries<'a> {
|
|||
/// the view, as well as the sampler.
|
||||
pub(crate) fn get(
|
||||
render_view_irradiance_volumes: Option<&RenderViewLightProbes<IrradianceVolume>>,
|
||||
images: &'a RenderAssets<Image>,
|
||||
images: &'a RenderAssets<GpuImage>,
|
||||
fallback_image: &'a FallbackImage,
|
||||
render_device: &RenderDevice,
|
||||
) -> RenderViewIrradianceVolumeBindGroupEntries<'a> {
|
||||
|
@ -236,7 +236,7 @@ impl<'a> RenderViewIrradianceVolumeBindGroupEntries<'a> {
|
|||
/// arrays are available on the current platform.
|
||||
fn get_multiple(
|
||||
render_view_irradiance_volumes: Option<&RenderViewLightProbes<IrradianceVolume>>,
|
||||
images: &'a RenderAssets<Image>,
|
||||
images: &'a RenderAssets<GpuImage>,
|
||||
fallback_image: &'a FallbackImage,
|
||||
) -> RenderViewIrradianceVolumeBindGroupEntries<'a> {
|
||||
let mut texture_views = vec![];
|
||||
|
@ -269,7 +269,7 @@ impl<'a> RenderViewIrradianceVolumeBindGroupEntries<'a> {
|
|||
/// arrays aren't available on the current platform.
|
||||
fn get_single(
|
||||
render_view_irradiance_volumes: Option<&RenderViewLightProbes<IrradianceVolume>>,
|
||||
images: &'a RenderAssets<Image>,
|
||||
images: &'a RenderAssets<GpuImage>,
|
||||
fallback_image: &'a FallbackImage,
|
||||
) -> RenderViewIrradianceVolumeBindGroupEntries<'a> {
|
||||
if let Some(irradiance_volumes) = render_view_irradiance_volumes {
|
||||
|
@ -322,7 +322,7 @@ impl LightProbeComponent for IrradianceVolume {
|
|||
// here.
|
||||
type ViewLightProbeInfo = ();
|
||||
|
||||
fn id(&self, image_assets: &RenderAssets<Image>) -> Option<Self::AssetId> {
|
||||
fn id(&self, image_assets: &RenderAssets<GpuImage>) -> Option<Self::AssetId> {
|
||||
if image_assets.get(&self.voxels).is_none() {
|
||||
None
|
||||
} else {
|
||||
|
@ -336,7 +336,7 @@ impl LightProbeComponent for IrradianceVolume {
|
|||
|
||||
fn create_render_view_light_probes(
|
||||
_: Option<&Self>,
|
||||
_: &RenderAssets<Image>,
|
||||
_: &RenderAssets<GpuImage>,
|
||||
) -> RenderViewLightProbes<Self> {
|
||||
RenderViewLightProbes::new()
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ use bevy_render::{
|
|||
render_resource::{DynamicUniformBuffer, Sampler, Shader, ShaderType, TextureView},
|
||||
renderer::{RenderDevice, RenderQueue},
|
||||
settings::WgpuFeatures,
|
||||
texture::{FallbackImage, Image},
|
||||
texture::{FallbackImage, GpuImage, Image},
|
||||
view::ExtractedView,
|
||||
Extract, ExtractSchedule, Render, RenderApp, RenderSet,
|
||||
};
|
||||
|
@ -270,7 +270,7 @@ pub trait LightProbeComponent: Send + Sync + Component + Sized {
|
|||
|
||||
/// Returns the asset ID or asset IDs of the texture or textures referenced
|
||||
/// by this light probe.
|
||||
fn id(&self, image_assets: &RenderAssets<Image>) -> Option<Self::AssetId>;
|
||||
fn id(&self, image_assets: &RenderAssets<GpuImage>) -> Option<Self::AssetId>;
|
||||
|
||||
/// Returns the intensity of this light probe.
|
||||
///
|
||||
|
@ -284,7 +284,7 @@ pub trait LightProbeComponent: Send + Sync + Component + Sized {
|
|||
/// This is called for every light probe in view every frame.
|
||||
fn create_render_view_light_probes(
|
||||
view_component: Option<&Self>,
|
||||
image_assets: &RenderAssets<Image>,
|
||||
image_assets: &RenderAssets<GpuImage>,
|
||||
) -> RenderViewLightProbes<Self>;
|
||||
}
|
||||
|
||||
|
@ -342,7 +342,7 @@ impl Plugin for LightProbePlugin {
|
|||
/// Gathers up all light probes of a single type in the scene and assigns them
|
||||
/// to views, performing frustum culling and distance sorting in the process.
|
||||
fn gather_light_probes<C>(
|
||||
image_assets: Res<RenderAssets<Image>>,
|
||||
image_assets: Res<RenderAssets<GpuImage>>,
|
||||
light_probe_query: Extract<Query<(&GlobalTransform, &C), With<LightProbe>>>,
|
||||
view_query: Extract<Query<(Entity, &GlobalTransform, &Frustum, Option<&C>), With<Camera3d>>>,
|
||||
mut reflection_probes: Local<Vec<LightProbeInfo<C>>>,
|
||||
|
@ -505,7 +505,7 @@ where
|
|||
/// every frame.
|
||||
fn new(
|
||||
(light_probe_transform, environment_map): (&GlobalTransform, &C),
|
||||
image_assets: &RenderAssets<Image>,
|
||||
image_assets: &RenderAssets<GpuImage>,
|
||||
) -> Option<LightProbeInfo<C>> {
|
||||
environment_map.id(image_assets).map(|id| LightProbeInfo {
|
||||
affine_transform: light_probe_transform.affine(),
|
||||
|
@ -634,7 +634,7 @@ pub(crate) fn add_cubemap_texture_view<'a>(
|
|||
texture_views: &mut Vec<&'a <TextureView as Deref>::Target>,
|
||||
sampler: &mut Option<&'a Sampler>,
|
||||
image_id: AssetId<Image>,
|
||||
images: &'a RenderAssets<Image>,
|
||||
images: &'a RenderAssets<GpuImage>,
|
||||
fallback_image: &'a FallbackImage,
|
||||
) {
|
||||
match images.get(image_id) {
|
||||
|
|
|
@ -40,6 +40,8 @@ use bevy_ecs::{
|
|||
};
|
||||
use bevy_math::{uvec2, vec4, Rect, UVec2};
|
||||
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||
use bevy_render::mesh::GpuMesh;
|
||||
use bevy_render::texture::GpuImage;
|
||||
use bevy_render::{
|
||||
mesh::Mesh, render_asset::RenderAssets, render_resource::Shader, texture::Image,
|
||||
view::ViewVisibility, Extract, ExtractSchedule, RenderApp,
|
||||
|
@ -143,8 +145,8 @@ fn extract_lightmaps(
|
|||
mut render_lightmaps: ResMut<RenderLightmaps>,
|
||||
lightmaps: Extract<Query<(Entity, &ViewVisibility, &Lightmap)>>,
|
||||
render_mesh_instances: Res<RenderMeshInstances>,
|
||||
images: Res<RenderAssets<Image>>,
|
||||
meshes: Res<RenderAssets<Mesh>>,
|
||||
images: Res<RenderAssets<GpuImage>>,
|
||||
meshes: Res<RenderAssets<GpuMesh>>,
|
||||
) {
|
||||
// Clear out the old frame's data.
|
||||
render_lightmaps.render_lightmaps.clear();
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::meshlet::{
|
|||
MeshletGpuScene,
|
||||
};
|
||||
use crate::*;
|
||||
use bevy_asset::{Asset, AssetEvent, AssetId, AssetServer};
|
||||
use bevy_asset::{Asset, AssetId, AssetServer};
|
||||
use bevy_core_pipeline::{
|
||||
core_3d::{
|
||||
AlphaMask3d, Camera3d, Opaque3d, Opaque3dBinKey, ScreenSpaceTransmissionQuality,
|
||||
|
@ -25,16 +25,15 @@ use bevy_render::{
|
|||
camera::TemporalJitter,
|
||||
extract_instances::{ExtractInstancesPlugin, ExtractedInstances},
|
||||
extract_resource::ExtractResource,
|
||||
mesh::{Mesh, MeshVertexBufferLayoutRef},
|
||||
render_asset::RenderAssets,
|
||||
mesh::{GpuMesh, MeshVertexBufferLayoutRef},
|
||||
render_asset::{PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssets},
|
||||
render_phase::*,
|
||||
render_resource::*,
|
||||
renderer::RenderDevice,
|
||||
texture::FallbackImage,
|
||||
view::{ExtractedView, Msaa, VisibleEntities},
|
||||
Extract,
|
||||
};
|
||||
use bevy_utils::{tracing::error, HashMap, HashSet};
|
||||
use bevy_utils::tracing::error;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
use std::{hash::Hash, num::NonZeroU32};
|
||||
|
@ -43,7 +42,7 @@ use self::{irradiance_volume::IrradianceVolume, prelude::EnvironmentMapLight};
|
|||
|
||||
/// Materials are used alongside [`MaterialPlugin`] and [`MaterialMeshBundle`]
|
||||
/// to spawn entities that are rendered with a specific [`Material`] type. They serve as an easy to use high level
|
||||
/// way to render [`Mesh`] entities with custom shader logic.
|
||||
/// way to render [`Mesh`](bevy_render::mesh::Mesh) entities with custom shader logic.
|
||||
///
|
||||
/// Materials must implement [`AsBindGroup`] to define how data will be transferred to the GPU and bound in shaders.
|
||||
/// [`AsBindGroup`] can be derived, which makes generating bindings straightforward. See the [`AsBindGroup`] docs for details.
|
||||
|
@ -250,8 +249,10 @@ where
|
|||
M::Data: PartialEq + Eq + Hash + Clone,
|
||||
{
|
||||
fn build(&self, app: &mut App) {
|
||||
app.init_asset::<M>()
|
||||
.add_plugins(ExtractInstancesPlugin::<AssetId<M>>::extract_visible());
|
||||
app.init_asset::<M>().add_plugins((
|
||||
ExtractInstancesPlugin::<AssetId<M>>::extract_visible(),
|
||||
RenderAssetPlugin::<PreparedMaterial<M>>::default(),
|
||||
));
|
||||
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app
|
||||
|
@ -261,28 +262,20 @@ where
|
|||
.add_render_command::<Transparent3d, DrawMaterial<M>>()
|
||||
.add_render_command::<Opaque3d, DrawMaterial<M>>()
|
||||
.add_render_command::<AlphaMask3d, DrawMaterial<M>>()
|
||||
.init_resource::<ExtractedMaterials<M>>()
|
||||
.init_resource::<RenderMaterials<M>>()
|
||||
.init_resource::<SpecializedMeshPipelines<MaterialPipeline<M>>>()
|
||||
.add_systems(ExtractSchedule, extract_materials::<M>)
|
||||
.add_systems(
|
||||
Render,
|
||||
(
|
||||
prepare_materials::<M>
|
||||
.in_set(RenderSet::PrepareAssets)
|
||||
.after(prepare_assets::<Image>),
|
||||
queue_material_meshes::<M>
|
||||
.in_set(RenderSet::QueueMeshes)
|
||||
.after(prepare_materials::<M>),
|
||||
),
|
||||
queue_material_meshes::<M>
|
||||
.in_set(RenderSet::QueueMeshes)
|
||||
.after(prepare_assets::<PreparedMaterial<M>>),
|
||||
);
|
||||
|
||||
if self.shadows_enabled {
|
||||
render_app.add_systems(
|
||||
Render,
|
||||
(queue_shadows::<M>
|
||||
queue_shadows::<M>
|
||||
.in_set(RenderSet::QueueMeshes)
|
||||
.after(prepare_materials::<M>),),
|
||||
.after(prepare_assets::<PreparedMaterial<M>>),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -438,7 +431,10 @@ type DrawMaterial<M> = (
|
|||
/// Sets the bind group for a given [`Material`] at the configured `I` index.
|
||||
pub struct SetMaterialBindGroup<M: Material, const I: usize>(PhantomData<M>);
|
||||
impl<P: PhaseItem, M: Material, const I: usize> RenderCommand<P> for SetMaterialBindGroup<M, I> {
|
||||
type Param = (SRes<RenderMaterials<M>>, SRes<RenderMaterialInstances<M>>);
|
||||
type Param = (
|
||||
SRes<RenderAssets<PreparedMaterial<M>>>,
|
||||
SRes<RenderMaterialInstances<M>>,
|
||||
);
|
||||
type ViewQuery = ();
|
||||
type ItemQuery = ();
|
||||
|
||||
|
@ -456,7 +452,7 @@ impl<P: PhaseItem, M: Material, const I: usize> RenderCommand<P> for SetMaterial
|
|||
let Some(material_asset_id) = material_instances.get(&item.entity()) else {
|
||||
return RenderCommandResult::Failure;
|
||||
};
|
||||
let Some(material) = materials.get(material_asset_id) else {
|
||||
let Some(material) = materials.get(*material_asset_id) else {
|
||||
return RenderCommandResult::Failure;
|
||||
};
|
||||
pass.set_bind_group(I, &material.bind_group, &[]);
|
||||
|
@ -522,8 +518,8 @@ pub fn queue_material_meshes<M: Material>(
|
|||
mut pipelines: ResMut<SpecializedMeshPipelines<MaterialPipeline<M>>>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
msaa: Res<Msaa>,
|
||||
render_meshes: Res<RenderAssets<Mesh>>,
|
||||
render_materials: Res<RenderMaterials<M>>,
|
||||
render_meshes: Res<RenderAssets<GpuMesh>>,
|
||||
render_materials: Res<RenderAssets<PreparedMaterial<M>>>,
|
||||
render_mesh_instances: Res<RenderMeshInstances>,
|
||||
render_material_instances: Res<RenderMaterialInstances<M>>,
|
||||
render_lightmaps: Res<RenderLightmaps>,
|
||||
|
@ -657,7 +653,7 @@ pub fn queue_material_meshes<M: Material>(
|
|||
let Some(mesh) = render_meshes.get(mesh_instance.mesh_asset_id) else {
|
||||
continue;
|
||||
};
|
||||
let Some(material) = render_materials.get(material_asset_id) else {
|
||||
let Some(material) = render_materials.get(*material_asset_id) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
@ -846,6 +842,61 @@ pub struct PreparedMaterial<T: Material> {
|
|||
pub properties: MaterialProperties,
|
||||
}
|
||||
|
||||
impl<M: Material> RenderAsset for PreparedMaterial<M> {
|
||||
type SourceAsset = M;
|
||||
|
||||
type Param = (
|
||||
SRes<RenderDevice>,
|
||||
SRes<RenderAssets<GpuImage>>,
|
||||
SRes<FallbackImage>,
|
||||
SRes<MaterialPipeline<M>>,
|
||||
SRes<DefaultOpaqueRendererMethod>,
|
||||
);
|
||||
|
||||
fn prepare_asset(
|
||||
material: Self::SourceAsset,
|
||||
(render_device, images, fallback_image, pipeline, default_opaque_render_method): &mut SystemParamItem<Self::Param>,
|
||||
) -> Result<Self, PrepareAssetError<Self::SourceAsset>> {
|
||||
match material.as_bind_group(
|
||||
&pipeline.material_layout,
|
||||
render_device,
|
||||
images,
|
||||
fallback_image,
|
||||
) {
|
||||
Ok(prepared) => {
|
||||
let method = match material.opaque_render_method() {
|
||||
OpaqueRendererMethod::Forward => OpaqueRendererMethod::Forward,
|
||||
OpaqueRendererMethod::Deferred => OpaqueRendererMethod::Deferred,
|
||||
OpaqueRendererMethod::Auto => default_opaque_render_method.0,
|
||||
};
|
||||
let mut mesh_pipeline_key_bits = MeshPipelineKey::empty();
|
||||
mesh_pipeline_key_bits.set(
|
||||
MeshPipelineKey::READS_VIEW_TRANSMISSION_TEXTURE,
|
||||
material.reads_view_transmission_texture(),
|
||||
);
|
||||
mesh_pipeline_key_bits.insert(alpha_mode_pipeline_key(material.alpha_mode()));
|
||||
|
||||
Ok(PreparedMaterial {
|
||||
bindings: prepared.bindings,
|
||||
bind_group: prepared.bind_group,
|
||||
key: prepared.data,
|
||||
properties: MaterialProperties {
|
||||
alpha_mode: material.alpha_mode(),
|
||||
depth_bias: material.depth_bias(),
|
||||
reads_view_transmission_texture: mesh_pipeline_key_bits
|
||||
.contains(MeshPipelineKey::READS_VIEW_TRANSMISSION_TEXTURE),
|
||||
render_method: method,
|
||||
mesh_pipeline_key_bits,
|
||||
},
|
||||
})
|
||||
}
|
||||
Err(AsBindGroupError::RetryNextUpdate) => {
|
||||
Err(PrepareAssetError::RetryNextUpdate(material))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component, Clone, Copy, Default, PartialEq, Eq, Deref, DerefMut)]
|
||||
pub struct MaterialBindGroupId(pub Option<BindGroupId>);
|
||||
|
||||
|
@ -894,181 +945,3 @@ impl<T: Material> PreparedMaterial<T> {
|
|||
MaterialBindGroupId(Some(self.bind_group.id()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Resource)]
|
||||
pub struct ExtractedMaterials<M: Material> {
|
||||
extracted: Vec<(AssetId<M>, M)>,
|
||||
removed: Vec<AssetId<M>>,
|
||||
}
|
||||
|
||||
impl<M: Material> Default for ExtractedMaterials<M> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
extracted: Default::default(),
|
||||
removed: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores all prepared representations of [`Material`] assets for as long as they exist.
|
||||
#[derive(Resource, Deref, DerefMut)]
|
||||
pub struct RenderMaterials<T: Material>(pub HashMap<AssetId<T>, PreparedMaterial<T>>);
|
||||
|
||||
impl<T: Material> Default for RenderMaterials<T> {
|
||||
fn default() -> Self {
|
||||
Self(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
/// This system extracts all created or modified assets of the corresponding [`Material`] type
|
||||
/// into the "render world".
|
||||
pub fn extract_materials<M: Material>(
|
||||
mut commands: Commands,
|
||||
mut events: Extract<EventReader<AssetEvent<M>>>,
|
||||
assets: Extract<Res<Assets<M>>>,
|
||||
) {
|
||||
let mut changed_assets = HashSet::default();
|
||||
let mut removed = Vec::new();
|
||||
for event in events.read() {
|
||||
#[allow(clippy::match_same_arms)]
|
||||
match event {
|
||||
AssetEvent::Added { id } | AssetEvent::Modified { id } => {
|
||||
changed_assets.insert(*id);
|
||||
}
|
||||
AssetEvent::Removed { id } => {
|
||||
changed_assets.remove(id);
|
||||
removed.push(*id);
|
||||
}
|
||||
AssetEvent::Unused { .. } => {}
|
||||
AssetEvent::LoadedWithDependencies { .. } => {
|
||||
// TODO: handle this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut extracted_assets = Vec::new();
|
||||
for id in changed_assets.drain() {
|
||||
if let Some(asset) = assets.get(id) {
|
||||
extracted_assets.push((id, asset.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
commands.insert_resource(ExtractedMaterials {
|
||||
extracted: extracted_assets,
|
||||
removed,
|
||||
});
|
||||
}
|
||||
|
||||
/// All [`Material`] values of a given type that should be prepared next frame.
|
||||
pub struct PrepareNextFrameMaterials<M: Material> {
|
||||
assets: Vec<(AssetId<M>, M)>,
|
||||
}
|
||||
|
||||
impl<M: Material> Default for PrepareNextFrameMaterials<M> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
assets: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This system prepares all assets of the corresponding [`Material`] type
|
||||
/// which where extracted this frame for the GPU.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn prepare_materials<M: Material>(
|
||||
mut prepare_next_frame: Local<PrepareNextFrameMaterials<M>>,
|
||||
mut extracted_assets: ResMut<ExtractedMaterials<M>>,
|
||||
mut render_materials: ResMut<RenderMaterials<M>>,
|
||||
render_device: Res<RenderDevice>,
|
||||
images: Res<RenderAssets<Image>>,
|
||||
fallback_image: Res<FallbackImage>,
|
||||
pipeline: Res<MaterialPipeline<M>>,
|
||||
default_opaque_render_method: Res<DefaultOpaqueRendererMethod>,
|
||||
) {
|
||||
let queued_assets = std::mem::take(&mut prepare_next_frame.assets);
|
||||
for (id, material) in queued_assets.into_iter() {
|
||||
if extracted_assets.removed.contains(&id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
match prepare_material(
|
||||
&material,
|
||||
&render_device,
|
||||
&images,
|
||||
&fallback_image,
|
||||
&pipeline,
|
||||
default_opaque_render_method.0,
|
||||
) {
|
||||
Ok(prepared_asset) => {
|
||||
render_materials.insert(id, prepared_asset);
|
||||
}
|
||||
Err(AsBindGroupError::RetryNextUpdate) => {
|
||||
prepare_next_frame.assets.push((id, material));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for removed in std::mem::take(&mut extracted_assets.removed) {
|
||||
render_materials.remove(&removed);
|
||||
}
|
||||
|
||||
for (id, material) in std::mem::take(&mut extracted_assets.extracted) {
|
||||
match prepare_material(
|
||||
&material,
|
||||
&render_device,
|
||||
&images,
|
||||
&fallback_image,
|
||||
&pipeline,
|
||||
default_opaque_render_method.0,
|
||||
) {
|
||||
Ok(prepared_asset) => {
|
||||
render_materials.insert(id, prepared_asset);
|
||||
}
|
||||
Err(AsBindGroupError::RetryNextUpdate) => {
|
||||
prepare_next_frame.assets.push((id, material));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn prepare_material<M: Material>(
|
||||
material: &M,
|
||||
render_device: &RenderDevice,
|
||||
images: &RenderAssets<Image>,
|
||||
fallback_image: &FallbackImage,
|
||||
pipeline: &MaterialPipeline<M>,
|
||||
default_opaque_render_method: OpaqueRendererMethod,
|
||||
) -> Result<PreparedMaterial<M>, AsBindGroupError> {
|
||||
let prepared = material.as_bind_group(
|
||||
&pipeline.material_layout,
|
||||
render_device,
|
||||
images,
|
||||
fallback_image,
|
||||
)?;
|
||||
let method = match material.opaque_render_method() {
|
||||
OpaqueRendererMethod::Forward => OpaqueRendererMethod::Forward,
|
||||
OpaqueRendererMethod::Deferred => OpaqueRendererMethod::Deferred,
|
||||
OpaqueRendererMethod::Auto => default_opaque_render_method,
|
||||
};
|
||||
|
||||
let mut mesh_pipeline_key_bits = MeshPipelineKey::empty();
|
||||
mesh_pipeline_key_bits.set(
|
||||
MeshPipelineKey::READS_VIEW_TRANSMISSION_TEXTURE,
|
||||
material.reads_view_transmission_texture(),
|
||||
);
|
||||
mesh_pipeline_key_bits.insert(alpha_mode_pipeline_key(material.alpha_mode()));
|
||||
|
||||
Ok(PreparedMaterial {
|
||||
bindings: prepared.bindings,
|
||||
bind_group: prepared.bind_group,
|
||||
key: prepared.data,
|
||||
properties: MaterialProperties {
|
||||
alpha_mode: material.alpha_mode(),
|
||||
depth_bias: material.depth_bias(),
|
||||
reads_view_transmission_texture: mesh_pipeline_key_bits
|
||||
.contains(MeshPipelineKey::READS_VIEW_TRANSMISSION_TEXTURE),
|
||||
render_method: method,
|
||||
mesh_pipeline_key_bits,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ use bevy_derive::{Deref, DerefMut};
|
|||
use bevy_render::{
|
||||
camera::TemporalJitter,
|
||||
mesh::{Mesh, MeshVertexBufferLayout, MeshVertexBufferLayoutRef, MeshVertexBufferLayouts},
|
||||
render_asset::RenderAssets,
|
||||
render_resource::*,
|
||||
view::ExtractedView,
|
||||
};
|
||||
|
@ -29,7 +30,7 @@ pub fn prepare_material_meshlet_meshes_main_opaque_pass<M: Material>(
|
|||
pipeline_cache: Res<PipelineCache>,
|
||||
material_pipeline: Res<MaterialPipeline<M>>,
|
||||
mesh_pipeline: Res<MeshPipeline>,
|
||||
render_materials: Res<RenderMaterials<M>>,
|
||||
render_materials: Res<RenderAssets<PreparedMaterial<M>>>,
|
||||
render_material_instances: Res<RenderMaterialInstances<M>>,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut mesh_vertex_buffer_layouts: ResMut<MeshVertexBufferLayouts>,
|
||||
|
@ -139,7 +140,7 @@ pub fn prepare_material_meshlet_meshes_main_opaque_pass<M: Material>(
|
|||
view_key |= MeshPipelineKey::from_primitive_topology(PrimitiveTopology::TriangleList);
|
||||
|
||||
for material_id in render_material_instances.values() {
|
||||
let Some(material) = render_materials.get(material_id) else {
|
||||
let Some(material) = render_materials.get(*material_id) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
@ -226,7 +227,7 @@ pub fn prepare_material_meshlet_meshes_prepass<M: Material>(
|
|||
mut cache: Local<HashMap<MeshPipelineKey, CachedRenderPipelineId>>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
prepass_pipeline: Res<PrepassPipeline<M>>,
|
||||
render_materials: Res<RenderMaterials<M>>,
|
||||
render_materials: Res<RenderAssets<PreparedMaterial<M>>>,
|
||||
render_material_instances: Res<RenderMaterialInstances<M>>,
|
||||
mut mesh_vertex_buffer_layouts: ResMut<MeshVertexBufferLayouts>,
|
||||
asset_server: Res<AssetServer>,
|
||||
|
@ -264,7 +265,7 @@ pub fn prepare_material_meshlet_meshes_prepass<M: Material>(
|
|||
view_key |= MeshPipelineKey::from_primitive_topology(PrimitiveTopology::TriangleList);
|
||||
|
||||
for material_id in render_material_instances.values() {
|
||||
let Some(material) = render_materials.get(material_id) else {
|
||||
let Some(material) = render_materials.get(*material_id) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
|
|
@ -651,7 +651,10 @@ pub struct StandardMaterialUniform {
|
|||
}
|
||||
|
||||
impl AsBindGroupShaderType<StandardMaterialUniform> for StandardMaterial {
|
||||
fn as_bind_group_shader_type(&self, images: &RenderAssets<Image>) -> StandardMaterialUniform {
|
||||
fn as_bind_group_shader_type(
|
||||
&self,
|
||||
images: &RenderAssets<GpuImage>,
|
||||
) -> StandardMaterialUniform {
|
||||
let mut flags = StandardMaterialFlags::NONE;
|
||||
if self.base_color_texture.is_some() {
|
||||
flags |= StandardMaterialFlags::BASE_COLOR_TEXTURE;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
mod prepass_bindings;
|
||||
|
||||
use bevy_render::batching::{batch_and_prepare_binned_render_phase, sort_binned_render_phase};
|
||||
use bevy_render::mesh::MeshVertexBufferLayoutRef;
|
||||
use bevy_render::mesh::{GpuMesh, MeshVertexBufferLayoutRef};
|
||||
use bevy_render::render_resource::binding_types::uniform_buffer;
|
||||
pub use prepass_bindings::*;
|
||||
|
||||
|
@ -181,7 +181,7 @@ where
|
|||
Render,
|
||||
queue_prepass_material_meshes::<M>
|
||||
.in_set(RenderSet::QueueMeshes)
|
||||
.after(prepare_materials::<M>)
|
||||
.after(prepare_assets::<PreparedMaterial<M>>)
|
||||
// queue_material_meshes only writes to `material_bind_group_id`, which `queue_prepass_material_meshes` doesn't read
|
||||
.ambiguous_with(queue_material_meshes::<StandardMaterial>),
|
||||
);
|
||||
|
@ -714,9 +714,9 @@ pub fn queue_prepass_material_meshes<M: Material>(
|
|||
mut pipelines: ResMut<SpecializedMeshPipelines<PrepassPipeline<M>>>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
msaa: Res<Msaa>,
|
||||
render_meshes: Res<RenderAssets<Mesh>>,
|
||||
render_meshes: Res<RenderAssets<GpuMesh>>,
|
||||
render_mesh_instances: Res<RenderMeshInstances>,
|
||||
render_materials: Res<RenderMaterials<M>>,
|
||||
render_materials: Res<RenderAssets<PreparedMaterial<M>>>,
|
||||
render_material_instances: Res<RenderMaterialInstances<M>>,
|
||||
render_lightmaps: Res<RenderLightmaps>,
|
||||
mut views: Query<
|
||||
|
@ -789,7 +789,7 @@ pub fn queue_prepass_material_meshes<M: Material>(
|
|||
let Some(mesh_instance) = render_mesh_instances.get(visible_entity) else {
|
||||
continue;
|
||||
};
|
||||
let Some(material) = render_materials.get(material_asset_id) else {
|
||||
let Some(material) = render_materials.get(*material_asset_id) else {
|
||||
continue;
|
||||
};
|
||||
let Some(mesh) = render_meshes.get(mesh_instance.mesh_asset_id) else {
|
||||
|
|
|
@ -3,10 +3,11 @@ use bevy_core_pipeline::core_3d::{Transparent3d, CORE_3D_DEPTH_FORMAT};
|
|||
use bevy_ecs::prelude::*;
|
||||
use bevy_ecs::{entity::EntityHashMap, system::lifetimeless::Read};
|
||||
use bevy_math::{Mat4, UVec3, UVec4, Vec2, Vec3, Vec3Swizzles, Vec4, Vec4Swizzles};
|
||||
use bevy_render::mesh::Mesh;
|
||||
use bevy_render::{
|
||||
camera::Camera,
|
||||
diagnostic::RecordDiagnostics,
|
||||
mesh::Mesh,
|
||||
mesh::GpuMesh,
|
||||
primitives::{CascadesFrusta, CubemapFrusta, Frustum, HalfSpace},
|
||||
render_asset::RenderAssets,
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext},
|
||||
|
@ -1599,9 +1600,9 @@ pub fn prepare_clusters(
|
|||
pub fn queue_shadows<M: Material>(
|
||||
shadow_draw_functions: Res<DrawFunctions<Shadow>>,
|
||||
prepass_pipeline: Res<PrepassPipeline<M>>,
|
||||
render_meshes: Res<RenderAssets<Mesh>>,
|
||||
render_meshes: Res<RenderAssets<GpuMesh>>,
|
||||
render_mesh_instances: Res<RenderMeshInstances>,
|
||||
render_materials: Res<RenderMaterials<M>>,
|
||||
render_materials: Res<RenderAssets<PreparedMaterial<M>>>,
|
||||
render_material_instances: Res<RenderMaterialInstances<M>>,
|
||||
mut pipelines: ResMut<SpecializedMeshPipelines<PrepassPipeline<M>>>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
|
@ -1659,7 +1660,7 @@ pub fn queue_shadows<M: Material>(
|
|||
let Some(material_asset_id) = render_material_instances.get(&entity) else {
|
||||
continue;
|
||||
};
|
||||
let Some(material) = render_materials.get(material_asset_id) else {
|
||||
let Some(material) = render_materials.get(*material_asset_id) else {
|
||||
continue;
|
||||
};
|
||||
let Some(mesh) = render_meshes.get(mesh_instance.mesh_asset_id) else {
|
||||
|
|
|
@ -22,7 +22,7 @@ use bevy_render::{
|
|||
render_phase::{PhaseItem, RenderCommand, RenderCommandResult, TrackedRenderPass},
|
||||
render_resource::*,
|
||||
renderer::{RenderDevice, RenderQueue},
|
||||
texture::{BevyDefault, DefaultImageSampler, GpuImage, ImageSampler, TextureFormatPixelInfo},
|
||||
texture::{BevyDefault, DefaultImageSampler, ImageSampler, TextureFormatPixelInfo},
|
||||
view::{ViewTarget, ViewUniformOffset, ViewVisibility},
|
||||
Extract,
|
||||
};
|
||||
|
@ -427,7 +427,7 @@ impl FromWorld for MeshPipeline {
|
|||
impl MeshPipeline {
|
||||
pub fn get_image_texture<'a>(
|
||||
&'a self,
|
||||
gpu_images: &'a RenderAssets<Image>,
|
||||
gpu_images: &'a RenderAssets<GpuImage>,
|
||||
handle_option: &Option<Handle<Image>>,
|
||||
) -> Option<(&'a TextureView, &'a Sampler)> {
|
||||
if let Some(handle) = handle_option {
|
||||
|
@ -1026,8 +1026,8 @@ impl MeshBindGroups {
|
|||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn prepare_mesh_bind_group(
|
||||
meshes: Res<RenderAssets<Mesh>>,
|
||||
images: Res<RenderAssets<Image>>,
|
||||
meshes: Res<RenderAssets<GpuMesh>>,
|
||||
images: Res<RenderAssets<GpuImage>>,
|
||||
mut groups: ResMut<MeshBindGroups>,
|
||||
mesh_pipeline: Res<MeshPipeline>,
|
||||
render_device: Res<RenderDevice>,
|
||||
|
@ -1187,7 +1187,7 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMeshBindGroup<I> {
|
|||
|
||||
pub struct DrawMesh;
|
||||
impl<P: PhaseItem> RenderCommand<P> for DrawMesh {
|
||||
type Param = (SRes<RenderAssets<Mesh>>, SRes<RenderMeshInstances>);
|
||||
type Param = (SRes<RenderAssets<GpuMesh>>, SRes<RenderMeshInstances>);
|
||||
type ViewQuery = ();
|
||||
type ItemQuery = ();
|
||||
#[inline]
|
||||
|
|
|
@ -17,7 +17,7 @@ use bevy_render::{
|
|||
render_asset::RenderAssets,
|
||||
render_resource::{binding_types::*, *},
|
||||
renderer::RenderDevice,
|
||||
texture::{BevyDefault, FallbackImage, FallbackImageMsaa, FallbackImageZero, Image},
|
||||
texture::{BevyDefault, FallbackImage, FallbackImageMsaa, FallbackImageZero, GpuImage},
|
||||
view::{Msaa, ViewUniform, ViewUniforms},
|
||||
};
|
||||
|
||||
|
@ -370,7 +370,7 @@ pub fn prepare_mesh_view_bind_groups(
|
|||
Option<&RenderViewLightProbes<IrradianceVolume>>,
|
||||
)>,
|
||||
(images, mut fallback_images, fallback_image, fallback_image_zero): (
|
||||
Res<RenderAssets<Image>>,
|
||||
Res<RenderAssets<GpuImage>>,
|
||||
FallbackImageMsaa,
|
||||
Res<FallbackImage>,
|
||||
Res<FallbackImageZero>,
|
||||
|
|
|
@ -498,7 +498,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result<TokenStream> {
|
|||
&self,
|
||||
layout: &#render_path::render_resource::BindGroupLayout,
|
||||
render_device: &#render_path::renderer::RenderDevice,
|
||||
images: &#render_path::render_asset::RenderAssets<#render_path::texture::Image>,
|
||||
images: &#render_path::render_asset::RenderAssets<#render_path::texture::GpuImage>,
|
||||
fallback_image: &#render_path::texture::FallbackImage,
|
||||
) -> Result<#render_path::render_resource::UnpreparedBindGroup<Self::Data>, #render_path::render_resource::AsBindGroupError> {
|
||||
let bindings = vec![#(#binding_impls,)*];
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use crate::{
|
||||
camera::CameraProjection,
|
||||
camera::{ManualTextureViewHandle, ManualTextureViews},
|
||||
camera::{CameraProjection, ManualTextureViewHandle, ManualTextureViews},
|
||||
prelude::Image,
|
||||
primitives::Frustum,
|
||||
render_asset::RenderAssets,
|
||||
render_graph::{InternedRenderSubGraph, RenderSubGraph},
|
||||
render_resource::TextureView,
|
||||
texture::GpuImage,
|
||||
view::{ColorGrading, ExtractedView, ExtractedWindows, RenderLayers, VisibleEntities},
|
||||
Extract,
|
||||
};
|
||||
|
@ -581,7 +581,7 @@ impl NormalizedRenderTarget {
|
|||
pub fn get_texture_view<'a>(
|
||||
&self,
|
||||
windows: &'a ExtractedWindows,
|
||||
images: &'a RenderAssets<Image>,
|
||||
images: &'a RenderAssets<GpuImage>,
|
||||
manual_texture_views: &'a ManualTextureViews,
|
||||
) -> Option<&'a TextureView> {
|
||||
match self {
|
||||
|
@ -601,7 +601,7 @@ impl NormalizedRenderTarget {
|
|||
pub fn get_texture_format<'a>(
|
||||
&self,
|
||||
windows: &'a ExtractedWindows,
|
||||
images: &'a RenderAssets<Image>,
|
||||
images: &'a RenderAssets<GpuImage>,
|
||||
manual_texture_views: &'a ManualTextureViews,
|
||||
) -> Option<TextureFormat> {
|
||||
match self {
|
||||
|
|
|
@ -61,10 +61,11 @@ use bevy_window::{PrimaryWindow, RawHandleWrapper};
|
|||
use globals::GlobalsPlugin;
|
||||
use renderer::{RenderAdapter, RenderAdapterInfo, RenderDevice, RenderQueue};
|
||||
|
||||
use crate::mesh::GpuMesh;
|
||||
use crate::renderer::WgpuWrapper;
|
||||
use crate::{
|
||||
camera::CameraPlugin,
|
||||
mesh::{morph::MorphPlugin, Mesh, MeshPlugin},
|
||||
mesh::{morph::MorphPlugin, MeshPlugin},
|
||||
render_asset::prepare_assets,
|
||||
render_resource::{PipelineCache, Shader, ShaderLoader},
|
||||
renderer::{render_system, RenderInstance},
|
||||
|
@ -111,7 +112,7 @@ pub enum RenderSet {
|
|||
/// Queue drawable entities as phase items in render phases ready for
|
||||
/// sorting (if necessary)
|
||||
Queue,
|
||||
/// A sub-set within [`Queue`](RenderSet::Queue) where mesh entity queue systems are executed. Ensures `prepare_assets::<Mesh>` is completed.
|
||||
/// A sub-set within [`Queue`](RenderSet::Queue) where mesh entity queue systems are executed. Ensures `prepare_assets::<GpuMesh>` is completed.
|
||||
QueueMeshes,
|
||||
// TODO: This could probably be moved in favor of a system ordering
|
||||
// abstraction in `Render` or `Queue`
|
||||
|
@ -161,7 +162,7 @@ impl Render {
|
|||
);
|
||||
|
||||
schedule.configure_sets((ExtractCommands, PrepareAssets, Prepare).chain());
|
||||
schedule.configure_sets(QueueMeshes.in_set(Queue).after(prepare_assets::<Mesh>));
|
||||
schedule.configure_sets(QueueMeshes.in_set(Queue).after(prepare_assets::<GpuMesh>));
|
||||
schedule.configure_sets(
|
||||
(PrepareResources, PrepareResourcesFlush, PrepareBindGroups)
|
||||
.chain()
|
||||
|
|
|
@ -10,6 +10,7 @@ use crate::{
|
|||
render_asset::{PrepareAssetError, RenderAsset, RenderAssetUsages, RenderAssets},
|
||||
render_resource::{Buffer, TextureView, VertexBufferLayout},
|
||||
renderer::RenderDevice,
|
||||
texture::GpuImage,
|
||||
};
|
||||
use bevy_asset::{Asset, Handle};
|
||||
use bevy_derive::EnumVariantMeta;
|
||||
|
@ -1463,68 +1464,69 @@ pub enum GpuBufferInfo {
|
|||
NonIndexed,
|
||||
}
|
||||
|
||||
impl RenderAsset for Mesh {
|
||||
type PreparedAsset = GpuMesh;
|
||||
impl RenderAsset for GpuMesh {
|
||||
type SourceAsset = Mesh;
|
||||
type Param = (
|
||||
SRes<RenderDevice>,
|
||||
SRes<RenderAssets<Image>>,
|
||||
SRes<RenderAssets<GpuImage>>,
|
||||
SResMut<MeshVertexBufferLayouts>,
|
||||
);
|
||||
|
||||
fn asset_usage(&self) -> RenderAssetUsages {
|
||||
self.asset_usage
|
||||
#[inline]
|
||||
fn asset_usage(mesh: &Self::SourceAsset) -> RenderAssetUsages {
|
||||
mesh.asset_usage
|
||||
}
|
||||
|
||||
/// Converts the extracted mesh a into [`GpuMesh`].
|
||||
fn prepare_asset(
|
||||
self,
|
||||
mesh: Self::SourceAsset,
|
||||
(render_device, images, ref mut mesh_vertex_buffer_layouts): &mut SystemParamItem<
|
||||
Self::Param,
|
||||
>,
|
||||
) -> Result<Self::PreparedAsset, PrepareAssetError<Self>> {
|
||||
let morph_targets = match self.morph_targets.as_ref() {
|
||||
) -> Result<Self, PrepareAssetError<Self::SourceAsset>> {
|
||||
let morph_targets = match mesh.morph_targets.as_ref() {
|
||||
Some(mt) => {
|
||||
let Some(target_image) = images.get(mt) else {
|
||||
return Err(PrepareAssetError::RetryNextUpdate(self));
|
||||
return Err(PrepareAssetError::RetryNextUpdate(mesh));
|
||||
};
|
||||
Some(target_image.texture_view.clone())
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
let vertex_buffer_data = self.get_vertex_buffer_data();
|
||||
let vertex_buffer_data = mesh.get_vertex_buffer_data();
|
||||
let vertex_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor {
|
||||
usage: BufferUsages::VERTEX,
|
||||
label: Some("Mesh Vertex Buffer"),
|
||||
contents: &vertex_buffer_data,
|
||||
});
|
||||
|
||||
let buffer_info = if let Some(data) = self.get_index_buffer_bytes() {
|
||||
let buffer_info = if let Some(data) = mesh.get_index_buffer_bytes() {
|
||||
GpuBufferInfo::Indexed {
|
||||
buffer: render_device.create_buffer_with_data(&BufferInitDescriptor {
|
||||
usage: BufferUsages::INDEX,
|
||||
contents: data,
|
||||
label: Some("Mesh Index Buffer"),
|
||||
}),
|
||||
count: self.indices().unwrap().len() as u32,
|
||||
index_format: self.indices().unwrap().into(),
|
||||
count: mesh.indices().unwrap().len() as u32,
|
||||
index_format: mesh.indices().unwrap().into(),
|
||||
}
|
||||
} else {
|
||||
GpuBufferInfo::NonIndexed
|
||||
};
|
||||
|
||||
let mesh_vertex_buffer_layout =
|
||||
self.get_mesh_vertex_buffer_layout(mesh_vertex_buffer_layouts);
|
||||
mesh.get_mesh_vertex_buffer_layout(mesh_vertex_buffer_layouts);
|
||||
|
||||
let mut key_bits = BaseMeshPipelineKey::from_primitive_topology(self.primitive_topology());
|
||||
let mut key_bits = BaseMeshPipelineKey::from_primitive_topology(mesh.primitive_topology());
|
||||
key_bits.set(
|
||||
BaseMeshPipelineKey::MORPH_TARGETS,
|
||||
self.morph_targets.is_some(),
|
||||
mesh.morph_targets.is_some(),
|
||||
);
|
||||
|
||||
Ok(GpuMesh {
|
||||
vertex_buffer,
|
||||
vertex_count: self.count_vertices() as u32,
|
||||
vertex_count: mesh.count_vertices() as u32,
|
||||
buffer_info,
|
||||
key_bits,
|
||||
layout: mesh_vertex_buffer_layout,
|
||||
|
|
|
@ -11,7 +11,7 @@ use std::{
|
|||
sync::Arc,
|
||||
};
|
||||
|
||||
use crate::{prelude::Image, render_asset::RenderAssetPlugin, RenderApp};
|
||||
use crate::{render_asset::RenderAssetPlugin, texture::GpuImage, RenderApp};
|
||||
use bevy_app::{App, Plugin};
|
||||
use bevy_asset::AssetApp;
|
||||
use bevy_ecs::{entity::Entity, system::Resource};
|
||||
|
@ -27,7 +27,7 @@ impl Plugin for MeshPlugin {
|
|||
.register_type::<skinning::SkinnedMesh>()
|
||||
.register_type::<Vec<Entity>>()
|
||||
// 'Mesh' must be prepared after 'Image' as meshes rely on the morph target image being ready
|
||||
.add_plugins(RenderAssetPlugin::<Mesh, Image>::default());
|
||||
.add_plugins(RenderAssetPlugin::<GpuMesh, GpuImage>::default());
|
||||
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
|
|
|
@ -21,14 +21,14 @@ pub enum PrepareAssetError<E: Send + Sync + 'static> {
|
|||
|
||||
/// Describes how an asset gets extracted and prepared for rendering.
|
||||
///
|
||||
/// In the [`ExtractSchedule`] step the asset is transferred
|
||||
/// In the [`ExtractSchedule`] step the [`RenderAsset::SourceAsset`] is transferred
|
||||
/// from the "main world" into the "render world".
|
||||
///
|
||||
/// After that in the [`RenderSet::PrepareAssets`] step the extracted asset
|
||||
/// is transformed into its GPU-representation of type [`RenderAsset::PreparedAsset`].
|
||||
pub trait RenderAsset: Asset + Clone {
|
||||
/// The GPU-representation of the asset.
|
||||
type PreparedAsset: Send + Sync + 'static;
|
||||
/// is transformed into its GPU-representation of type [`RenderAsset`].
|
||||
pub trait RenderAsset: Send + Sync + 'static + Sized {
|
||||
/// The representation of the asset in the "main world".
|
||||
type SourceAsset: Asset + Clone;
|
||||
|
||||
/// Specifies all ECS data required by [`RenderAsset::prepare_asset`].
|
||||
///
|
||||
|
@ -36,15 +36,18 @@ pub trait RenderAsset: Asset + Clone {
|
|||
type Param: SystemParam;
|
||||
|
||||
/// Whether or not to unload the asset after extracting it to the render world.
|
||||
fn asset_usage(&self) -> RenderAssetUsages;
|
||||
#[inline]
|
||||
fn asset_usage(_source_asset: &Self::SourceAsset) -> RenderAssetUsages {
|
||||
RenderAssetUsages::default()
|
||||
}
|
||||
|
||||
/// Prepares the asset for the GPU by transforming it into a [`RenderAsset::PreparedAsset`].
|
||||
/// Prepares the [`RenderAsset::SourceAsset`] for the GPU by transforming it into a [`RenderAsset`].
|
||||
///
|
||||
/// ECS data may be accessed via `param`.
|
||||
fn prepare_asset(
|
||||
self,
|
||||
source_asset: Self::SourceAsset,
|
||||
param: &mut SystemParamItem<Self::Param>,
|
||||
) -> Result<Self::PreparedAsset, PrepareAssetError<Self>>;
|
||||
) -> Result<Self, PrepareAssetError<Self::SourceAsset>>;
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
|
@ -101,8 +104,8 @@ impl Default for RenderAssetUsages {
|
|||
///
|
||||
/// The `AFTER` generic parameter can be used to specify that `A::prepare_asset` should not be run until
|
||||
/// `prepare_assets::<AFTER>` has completed. This allows the `prepare_asset` function to depend on another
|
||||
/// prepared [`RenderAsset`], for example `Mesh::prepare_asset` relies on `RenderAssets::<Image>` for morph
|
||||
/// targets, so the plugin is created as `RenderAssetPlugin::<Mesh, Image>::default()`.
|
||||
/// prepared [`RenderAsset`], for example `Mesh::prepare_asset` relies on `RenderAssets::<GpuImage>` for morph
|
||||
/// targets, so the plugin is created as `RenderAssetPlugin::<GpuMesh, GpuImage>::default()`.
|
||||
pub struct RenderAssetPlugin<A: RenderAsset, AFTER: RenderAssetDependency + 'static = ()> {
|
||||
phantom: PhantomData<fn() -> (A, AFTER)>,
|
||||
}
|
||||
|
@ -156,8 +159,8 @@ impl<A: RenderAsset> RenderAssetDependency for A {
|
|||
/// Temporarily stores the extracted and removed assets of the current frame.
|
||||
#[derive(Resource)]
|
||||
pub struct ExtractedAssets<A: RenderAsset> {
|
||||
extracted: Vec<(AssetId<A>, A)>,
|
||||
removed: Vec<AssetId<A>>,
|
||||
extracted: Vec<(AssetId<A::SourceAsset>, A::SourceAsset)>,
|
||||
removed: Vec<AssetId<A::SourceAsset>>,
|
||||
}
|
||||
|
||||
impl<A: RenderAsset> Default for ExtractedAssets<A> {
|
||||
|
@ -169,10 +172,10 @@ impl<A: RenderAsset> Default for ExtractedAssets<A> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Stores all GPU representations ([`RenderAsset::PreparedAssets`](RenderAsset::PreparedAsset))
|
||||
/// of [`RenderAssets`](RenderAsset) as long as they exist.
|
||||
/// Stores all GPU representations ([`RenderAsset`])
|
||||
/// of [`RenderAsset::SourceAsset`] as long as they exist.
|
||||
#[derive(Resource)]
|
||||
pub struct RenderAssets<A: RenderAsset>(HashMap<AssetId<A>, A::PreparedAsset>);
|
||||
pub struct RenderAssets<A: RenderAsset>(HashMap<AssetId<A::SourceAsset>, A>);
|
||||
|
||||
impl<A: RenderAsset> Default for RenderAssets<A> {
|
||||
fn default() -> Self {
|
||||
|
@ -181,31 +184,27 @@ impl<A: RenderAsset> Default for RenderAssets<A> {
|
|||
}
|
||||
|
||||
impl<A: RenderAsset> RenderAssets<A> {
|
||||
pub fn get(&self, id: impl Into<AssetId<A>>) -> Option<&A::PreparedAsset> {
|
||||
pub fn get(&self, id: impl Into<AssetId<A::SourceAsset>>) -> Option<&A> {
|
||||
self.0.get(&id.into())
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, id: impl Into<AssetId<A>>) -> Option<&mut A::PreparedAsset> {
|
||||
pub fn get_mut(&mut self, id: impl Into<AssetId<A::SourceAsset>>) -> Option<&mut A> {
|
||||
self.0.get_mut(&id.into())
|
||||
}
|
||||
|
||||
pub fn insert(
|
||||
&mut self,
|
||||
id: impl Into<AssetId<A>>,
|
||||
value: A::PreparedAsset,
|
||||
) -> Option<A::PreparedAsset> {
|
||||
pub fn insert(&mut self, id: impl Into<AssetId<A::SourceAsset>>, value: A) -> Option<A> {
|
||||
self.0.insert(id.into(), value)
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, id: impl Into<AssetId<A>>) -> Option<A::PreparedAsset> {
|
||||
pub fn remove(&mut self, id: impl Into<AssetId<A::SourceAsset>>) -> Option<A> {
|
||||
self.0.remove(&id.into())
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = (AssetId<A>, &A::PreparedAsset)> {
|
||||
pub fn iter(&self) -> impl Iterator<Item = (AssetId<A::SourceAsset>, &A)> {
|
||||
self.0.iter().map(|(k, v)| (*k, v))
|
||||
}
|
||||
|
||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = (AssetId<A>, &mut A::PreparedAsset)> {
|
||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = (AssetId<A::SourceAsset>, &mut A)> {
|
||||
self.0.iter_mut().map(|(k, v)| (*k, v))
|
||||
}
|
||||
}
|
||||
|
@ -213,8 +212,8 @@ impl<A: RenderAsset> RenderAssets<A> {
|
|||
#[derive(Resource)]
|
||||
struct CachedExtractRenderAssetSystemState<A: RenderAsset> {
|
||||
state: SystemState<(
|
||||
EventReader<'static, 'static, AssetEvent<A>>,
|
||||
ResMut<'static, Assets<A>>,
|
||||
EventReader<'static, 'static, AssetEvent<A::SourceAsset>>,
|
||||
ResMut<'static, Assets<A::SourceAsset>>,
|
||||
)>,
|
||||
}
|
||||
|
||||
|
@ -226,7 +225,7 @@ impl<A: RenderAsset> FromWorld for CachedExtractRenderAssetSystemState<A> {
|
|||
}
|
||||
}
|
||||
|
||||
/// This system extracts all created or modified assets of the corresponding [`RenderAsset`] type
|
||||
/// This system extracts all created or modified assets of the corresponding [`RenderAsset::SourceAsset`] type
|
||||
/// into the "render world".
|
||||
fn extract_render_asset<A: RenderAsset>(mut commands: Commands, mut main_world: ResMut<MainWorld>) {
|
||||
main_world.resource_scope(
|
||||
|
@ -256,7 +255,7 @@ fn extract_render_asset<A: RenderAsset>(mut commands: Commands, mut main_world:
|
|||
let mut extracted_assets = Vec::new();
|
||||
for id in changed_assets.drain() {
|
||||
if let Some(asset) = assets.get(id) {
|
||||
let asset_usage = asset.asset_usage();
|
||||
let asset_usage = A::asset_usage(asset);
|
||||
if asset_usage.contains(RenderAssetUsages::RENDER_WORLD) {
|
||||
if asset_usage == RenderAssetUsages::RENDER_WORLD {
|
||||
if let Some(asset) = assets.remove(id) {
|
||||
|
@ -269,7 +268,7 @@ fn extract_render_asset<A: RenderAsset>(mut commands: Commands, mut main_world:
|
|||
}
|
||||
}
|
||||
|
||||
commands.insert_resource(ExtractedAssets {
|
||||
commands.insert_resource(ExtractedAssets::<A> {
|
||||
extracted: extracted_assets,
|
||||
removed,
|
||||
});
|
||||
|
@ -282,7 +281,7 @@ fn extract_render_asset<A: RenderAsset>(mut commands: Commands, mut main_world:
|
|||
/// All assets that should be prepared next frame.
|
||||
#[derive(Resource)]
|
||||
pub struct PrepareNextFrameAssets<A: RenderAsset> {
|
||||
assets: Vec<(AssetId<A>, A)>,
|
||||
assets: Vec<(AssetId<A::SourceAsset>, A::SourceAsset)>,
|
||||
}
|
||||
|
||||
impl<A: RenderAsset> Default for PrepareNextFrameAssets<A> {
|
||||
|
@ -293,7 +292,7 @@ impl<A: RenderAsset> Default for PrepareNextFrameAssets<A> {
|
|||
}
|
||||
}
|
||||
|
||||
/// This system prepares all assets of the corresponding [`RenderAsset`] type
|
||||
/// This system prepares all assets of the corresponding [`RenderAsset::SourceAsset`] type
|
||||
/// which where extracted this frame for the GPU.
|
||||
pub fn prepare_assets<A: RenderAsset>(
|
||||
mut extracted_assets: ResMut<ExtractedAssets<A>>,
|
||||
|
@ -308,7 +307,7 @@ pub fn prepare_assets<A: RenderAsset>(
|
|||
continue;
|
||||
}
|
||||
|
||||
match extracted_asset.prepare_asset(&mut param) {
|
||||
match A::prepare_asset(extracted_asset, &mut param) {
|
||||
Ok(prepared_asset) => {
|
||||
render_assets.insert(id, prepared_asset);
|
||||
}
|
||||
|
@ -323,7 +322,7 @@ pub fn prepare_assets<A: RenderAsset>(
|
|||
}
|
||||
|
||||
for (id, extracted_asset) in extracted_assets.extracted.drain(..) {
|
||||
match extracted_asset.prepare_asset(&mut param) {
|
||||
match A::prepare_asset(extracted_asset, &mut param) {
|
||||
Ok(prepared_asset) => {
|
||||
render_assets.insert(id, prepared_asset);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use crate::{
|
||||
define_atomic_id,
|
||||
prelude::Image,
|
||||
render_asset::RenderAssets,
|
||||
render_resource::{resource_macros::*, BindGroupLayout, Buffer, Sampler, TextureView},
|
||||
renderer::RenderDevice,
|
||||
texture::FallbackImage,
|
||||
texture::{FallbackImage, GpuImage},
|
||||
};
|
||||
pub use bevy_render_macros::AsBindGroup;
|
||||
use encase::ShaderType;
|
||||
|
@ -58,14 +57,14 @@ impl Deref for BindGroup {
|
|||
///
|
||||
/// This is an opinionated trait that is intended to make it easy to generically
|
||||
/// convert a type into a [`BindGroup`]. It provides access to specific render resources,
|
||||
/// such as [`RenderAssets<Image>`] and [`FallbackImage`]. If a type has a [`Handle<Image>`](bevy_asset::Handle),
|
||||
/// such as [`RenderAssets<GpuImage>`] and [`FallbackImage`]. If a type has a [`Handle<Image>`](bevy_asset::Handle),
|
||||
/// these can be used to retrieve the corresponding [`Texture`](crate::render_resource::Texture) resource.
|
||||
///
|
||||
/// [`AsBindGroup::as_bind_group`] is intended to be called once, then the result cached somewhere. It is generally
|
||||
/// ok to do "expensive" work here, such as creating a [`Buffer`] for a uniform.
|
||||
///
|
||||
/// If for some reason a [`BindGroup`] cannot be created yet (for example, the [`Texture`](crate::render_resource::Texture)
|
||||
/// for an [`Image`] hasn't loaded yet), just return [`AsBindGroupError::RetryNextUpdate`], which signals that the caller
|
||||
/// for an [`Image`](crate::texture::Image) hasn't loaded yet), just return [`AsBindGroupError::RetryNextUpdate`], which signals that the caller
|
||||
/// should retry again later.
|
||||
///
|
||||
/// # Deriving
|
||||
|
@ -117,7 +116,7 @@ impl Deref for BindGroup {
|
|||
/// GPU resource, which will be bound as a texture in shaders. The field will be assumed to implement [`Into<Option<Handle<Image>>>`]. In practice,
|
||||
/// most fields should be a [`Handle<Image>`](bevy_asset::Handle) or [`Option<Handle<Image>>`]. If the value of an [`Option<Handle<Image>>`] is
|
||||
/// [`None`], the [`FallbackImage`] resource will be used instead. This attribute can be used in conjunction with a `sampler` binding attribute
|
||||
/// (with a different binding index) if a binding of the sampler for the [`Image`] is also required.
|
||||
/// (with a different binding index) if a binding of the sampler for the [`Image`](crate::texture::Image) is also required.
|
||||
///
|
||||
/// | Arguments | Values | Default |
|
||||
/// |-----------------------|-------------------------------------------------------------------------|----------------------|
|
||||
|
@ -145,7 +144,7 @@ impl Deref for BindGroup {
|
|||
/// resource, which will be bound as a sampler in shaders. The field will be assumed to implement [`Into<Option<Handle<Image>>>`]. In practice,
|
||||
/// most fields should be a [`Handle<Image>`](bevy_asset::Handle) or [`Option<Handle<Image>>`]. If the value of an [`Option<Handle<Image>>`] is
|
||||
/// [`None`], the [`FallbackImage`] resource will be used instead. This attribute can be used in conjunction with a `texture` binding attribute
|
||||
/// (with a different binding index) if a binding of the texture for the [`Image`] is also required.
|
||||
/// (with a different binding index) if a binding of the texture for the [`Image`](crate::texture::Image) is also required.
|
||||
///
|
||||
/// | Arguments | Values | Default |
|
||||
/// |------------------------|-------------------------------------------------------------------------|------------------------|
|
||||
|
@ -220,7 +219,7 @@ impl Deref for BindGroup {
|
|||
/// much like the field-level `uniform` attribute. The difference is that the entire [`AsBindGroup`] value is converted to `ConvertedShaderType`,
|
||||
/// which must implement [`ShaderType`], instead of a specific field implementing [`ShaderType`]. This is useful if more complicated conversion
|
||||
/// logic is required. The conversion is done using the [`AsBindGroupShaderType<ConvertedShaderType>`] trait, which is automatically implemented
|
||||
/// if `&Self` implements [`Into<ConvertedShaderType>`]. Only use [`AsBindGroupShaderType`] if access to resources like [`RenderAssets<Image>`] is
|
||||
/// if `&Self` implements [`Into<ConvertedShaderType>`]. Only use [`AsBindGroupShaderType`] if access to resources like [`RenderAssets<GpuImage>`] is
|
||||
/// required.
|
||||
/// * `bind_group_data(DataType)`
|
||||
/// * The [`AsBindGroup`] type will be converted to some `DataType` using [`Into<DataType>`] and stored
|
||||
|
@ -295,7 +294,7 @@ pub trait AsBindGroup {
|
|||
&self,
|
||||
layout: &BindGroupLayout,
|
||||
render_device: &RenderDevice,
|
||||
images: &RenderAssets<Image>,
|
||||
images: &RenderAssets<GpuImage>,
|
||||
fallback_image: &FallbackImage,
|
||||
) -> Result<PreparedBindGroup<Self::Data>, AsBindGroupError> {
|
||||
let UnpreparedBindGroup { bindings, data } =
|
||||
|
@ -326,7 +325,7 @@ pub trait AsBindGroup {
|
|||
&self,
|
||||
layout: &BindGroupLayout,
|
||||
render_device: &RenderDevice,
|
||||
images: &RenderAssets<Image>,
|
||||
images: &RenderAssets<GpuImage>,
|
||||
fallback_image: &FallbackImage,
|
||||
) -> Result<UnpreparedBindGroup<Self::Data>, AsBindGroupError>;
|
||||
|
||||
|
@ -396,7 +395,7 @@ impl OwnedBindingResource {
|
|||
pub trait AsBindGroupShaderType<T: ShaderType> {
|
||||
/// Return the `T` [`ShaderType`] for `self`. When used in [`AsBindGroup`]
|
||||
/// derives, it is safe to assume that all images in `self` exist.
|
||||
fn as_bind_group_shader_type(&self, images: &RenderAssets<Image>) -> T;
|
||||
fn as_bind_group_shader_type(&self, images: &RenderAssets<GpuImage>) -> T;
|
||||
}
|
||||
|
||||
impl<T, U: ShaderType> AsBindGroupShaderType<U> for T
|
||||
|
@ -404,7 +403,7 @@ where
|
|||
for<'a> &'a T: Into<U>,
|
||||
{
|
||||
#[inline]
|
||||
fn as_bind_group_shader_type(&self, _images: &RenderAssets<Image>) -> U {
|
||||
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
|
@ -412,7 +411,7 @@ where
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate as bevy_render;
|
||||
use crate::{self as bevy_render, prelude::Image};
|
||||
use bevy_asset::Handle;
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -826,39 +826,41 @@ pub struct GpuImage {
|
|||
pub mip_level_count: u32,
|
||||
}
|
||||
|
||||
impl RenderAsset for Image {
|
||||
type PreparedAsset = GpuImage;
|
||||
impl RenderAsset for GpuImage {
|
||||
type SourceAsset = Image;
|
||||
type Param = (
|
||||
SRes<RenderDevice>,
|
||||
SRes<RenderQueue>,
|
||||
SRes<DefaultImageSampler>,
|
||||
);
|
||||
|
||||
fn asset_usage(&self) -> RenderAssetUsages {
|
||||
self.asset_usage
|
||||
#[inline]
|
||||
fn asset_usage(image: &Self::SourceAsset) -> RenderAssetUsages {
|
||||
image.asset_usage
|
||||
}
|
||||
|
||||
/// Converts the extracted image into a [`GpuImage`].
|
||||
fn prepare_asset(
|
||||
self,
|
||||
image: Self::SourceAsset,
|
||||
(render_device, render_queue, default_sampler): &mut SystemParamItem<Self::Param>,
|
||||
) -> Result<Self::PreparedAsset, PrepareAssetError<Self>> {
|
||||
) -> Result<Self, PrepareAssetError<Self::SourceAsset>> {
|
||||
let texture = render_device.create_texture_with_data(
|
||||
render_queue,
|
||||
&self.texture_descriptor,
|
||||
&image.texture_descriptor,
|
||||
// TODO: Is this correct? Do we need to use `MipMajor` if it's a ktx2 file?
|
||||
wgpu::util::TextureDataOrder::default(),
|
||||
&self.data,
|
||||
&image.data,
|
||||
);
|
||||
|
||||
let size = self.size();
|
||||
let size = image.size();
|
||||
let texture_view = texture.create_view(
|
||||
self.texture_view_descriptor
|
||||
image
|
||||
.texture_view_descriptor
|
||||
.or_else(|| Some(TextureViewDescriptor::default()))
|
||||
.as_ref()
|
||||
.unwrap(),
|
||||
);
|
||||
let sampler = match self.sampler {
|
||||
let sampler = match image.sampler {
|
||||
ImageSampler::Default => (***default_sampler).clone(),
|
||||
ImageSampler::Descriptor(descriptor) => {
|
||||
render_device.create_sampler(&descriptor.as_wgpu())
|
||||
|
@ -868,10 +870,10 @@ impl RenderAsset for Image {
|
|||
Ok(GpuImage {
|
||||
texture,
|
||||
texture_view,
|
||||
texture_format: self.texture_descriptor.format,
|
||||
texture_format: image.texture_descriptor.format,
|
||||
sampler,
|
||||
size,
|
||||
mip_level_count: self.texture_descriptor.mip_level_count,
|
||||
mip_level_count: image.texture_descriptor.mip_level_count,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ impl Plugin for ImagePlugin {
|
|||
app.init_asset_loader::<HdrTextureLoader>();
|
||||
}
|
||||
|
||||
app.add_plugins(RenderAssetPlugin::<Image>::default())
|
||||
app.add_plugins(RenderAssetPlugin::<GpuImage>::default())
|
||||
.register_type::<Image>()
|
||||
.init_asset::<Image>()
|
||||
.register_asset_reflect::<Image>();
|
||||
|
|
|
@ -11,13 +11,15 @@ use crate::{
|
|||
ManualTextureViews, MipBias, TemporalJitter,
|
||||
},
|
||||
extract_resource::{ExtractResource, ExtractResourcePlugin},
|
||||
prelude::{Image, Shader},
|
||||
prelude::Shader,
|
||||
primitives::Frustum,
|
||||
render_asset::RenderAssets,
|
||||
render_phase::ViewRangefinder3d,
|
||||
render_resource::{DynamicUniformBuffer, ShaderType, Texture, TextureView},
|
||||
renderer::{RenderDevice, RenderQueue},
|
||||
texture::{BevyDefault, CachedTexture, ColorAttachment, DepthAttachment, TextureCache},
|
||||
texture::{
|
||||
BevyDefault, CachedTexture, ColorAttachment, DepthAttachment, GpuImage, TextureCache,
|
||||
},
|
||||
Render, RenderApp, RenderSet,
|
||||
};
|
||||
use bevy_app::{App, Plugin};
|
||||
|
@ -62,7 +64,7 @@ impl Plugin for ViewPlugin {
|
|||
prepare_view_targets
|
||||
.in_set(RenderSet::ManageViews)
|
||||
.after(prepare_windows)
|
||||
.after(crate::render_asset::prepare_assets::<Image>)
|
||||
.after(crate::render_asset::prepare_assets::<GpuImage>)
|
||||
.ambiguous_with(crate::camera::sort_cameras), // doesn't use `sorted_camera_index_for_target`
|
||||
prepare_view_uniforms.in_set(RenderSet::PrepareResources),
|
||||
),
|
||||
|
@ -460,7 +462,7 @@ struct MainTargetTextures {
|
|||
pub fn prepare_view_targets(
|
||||
mut commands: Commands,
|
||||
windows: Res<ExtractedWindows>,
|
||||
images: Res<RenderAssets<Image>>,
|
||||
images: Res<RenderAssets<GpuImage>>,
|
||||
msaa: Res<Msaa>,
|
||||
clear_color_global: Res<ClearColor>,
|
||||
render_device: Res<RenderDevice>,
|
||||
|
|
|
@ -3,7 +3,7 @@ use bevy_asset::{Assets, Handle};
|
|||
use bevy_math::{URect, UVec2};
|
||||
use bevy_render::{
|
||||
render_asset::{RenderAsset, RenderAssetUsages},
|
||||
texture::{Image, TextureFormatPixelInfo},
|
||||
texture::{GpuImage, Image, TextureFormatPixelInfo},
|
||||
};
|
||||
use guillotiere::{size2, Allocation, AtlasAllocator};
|
||||
|
||||
|
@ -56,8 +56,7 @@ impl DynamicTextureAtlasBuilder {
|
|||
if let Some(allocation) = allocation {
|
||||
let atlas_texture = textures.get_mut(atlas_texture_handle).unwrap();
|
||||
assert!(
|
||||
atlas_texture
|
||||
.asset_usage()
|
||||
<GpuImage as RenderAsset>::asset_usage(atlas_texture)
|
||||
.contains(RenderAssetUsages::MAIN_WORLD),
|
||||
"The asset at atlas_texture_handle must have the RenderAssetUsages::MAIN_WORLD usage flag set"
|
||||
);
|
||||
|
|
|
@ -4,7 +4,11 @@ use bevy_asset::{load_internal_asset, Asset, AssetApp, Assets, Handle};
|
|||
use bevy_color::{Color, LinearRgba};
|
||||
use bevy_math::Vec4;
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_render::{render_asset::RenderAssets, render_resource::*, texture::Image};
|
||||
use bevy_render::{
|
||||
render_asset::RenderAssets,
|
||||
render_resource::*,
|
||||
texture::{GpuImage, Image},
|
||||
};
|
||||
|
||||
pub const COLOR_MATERIAL_SHADER_HANDLE: Handle<Shader> =
|
||||
Handle::weak_from_u128(3253086872234592509);
|
||||
|
@ -92,7 +96,7 @@ pub struct ColorMaterialUniform {
|
|||
}
|
||||
|
||||
impl AsBindGroupShaderType<ColorMaterialUniform> for ColorMaterial {
|
||||
fn as_bind_group_shader_type(&self, _images: &RenderAssets<Image>) -> ColorMaterialUniform {
|
||||
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> ColorMaterialUniform {
|
||||
let mut flags = ColorMaterialFlags::NONE;
|
||||
if self.texture.is_some() {
|
||||
flags |= ColorMaterialFlags::TEXTURE;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use bevy_app::{App, Plugin};
|
||||
use bevy_asset::{Asset, AssetApp, AssetEvent, AssetId, AssetServer, Assets, Handle};
|
||||
use bevy_asset::{Asset, AssetApp, AssetId, AssetServer, Handle};
|
||||
use bevy_core_pipeline::{
|
||||
core_2d::Transparent2d,
|
||||
tonemapping::{DebandDither, Tonemapping},
|
||||
|
@ -12,9 +12,10 @@ use bevy_ecs::{
|
|||
};
|
||||
use bevy_math::FloatOrd;
|
||||
use bevy_render::{
|
||||
mesh::{Mesh, MeshVertexBufferLayoutRef},
|
||||
prelude::Image,
|
||||
render_asset::{prepare_assets, RenderAssets},
|
||||
mesh::{GpuMesh, MeshVertexBufferLayoutRef},
|
||||
render_asset::{
|
||||
prepare_assets, PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssets,
|
||||
},
|
||||
render_phase::{
|
||||
AddRenderCommand, DrawFunctions, PhaseItem, RenderCommand, RenderCommandResult,
|
||||
SetItemPipeline, SortedRenderPhase, TrackedRenderPass,
|
||||
|
@ -25,13 +26,12 @@ use bevy_render::{
|
|||
SpecializedMeshPipeline, SpecializedMeshPipelineError, SpecializedMeshPipelines,
|
||||
},
|
||||
renderer::RenderDevice,
|
||||
texture::FallbackImage,
|
||||
texture::{FallbackImage, GpuImage},
|
||||
view::{ExtractedView, InheritedVisibility, Msaa, ViewVisibility, Visibility, VisibleEntities},
|
||||
Extract, ExtractSchedule, Render, RenderApp, RenderSet,
|
||||
};
|
||||
use bevy_transform::components::{GlobalTransform, Transform};
|
||||
use bevy_utils::tracing::error;
|
||||
use bevy_utils::{HashMap, HashSet};
|
||||
use std::hash::Hash;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
@ -148,29 +148,20 @@ where
|
|||
M::Data: PartialEq + Eq + Hash + Clone,
|
||||
{
|
||||
fn build(&self, app: &mut App) {
|
||||
app.init_asset::<M>();
|
||||
app.init_asset::<M>()
|
||||
.add_plugins(RenderAssetPlugin::<PreparedMaterial2d<M>>::default());
|
||||
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app
|
||||
.add_render_command::<Transparent2d, DrawMaterial2d<M>>()
|
||||
.init_resource::<ExtractedMaterials2d<M>>()
|
||||
.init_resource::<RenderMaterials2d<M>>()
|
||||
.init_resource::<RenderMaterial2dInstances<M>>()
|
||||
.init_resource::<SpecializedMeshPipelines<Material2dPipeline<M>>>()
|
||||
.add_systems(
|
||||
ExtractSchedule,
|
||||
(extract_materials_2d::<M>, extract_material_meshes_2d::<M>),
|
||||
)
|
||||
.add_systems(ExtractSchedule, extract_material_meshes_2d::<M>)
|
||||
.add_systems(
|
||||
Render,
|
||||
(
|
||||
prepare_materials_2d::<M>
|
||||
.in_set(RenderSet::PrepareAssets)
|
||||
.after(prepare_assets::<Image>),
|
||||
queue_material2d_meshes::<M>
|
||||
.in_set(RenderSet::QueueMeshes)
|
||||
.after(prepare_materials_2d::<M>),
|
||||
),
|
||||
queue_material2d_meshes::<M>
|
||||
.in_set(RenderSet::QueueMeshes)
|
||||
.after(prepare_assets::<PreparedMaterial2d<M>>),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -330,7 +321,7 @@ impl<P: PhaseItem, M: Material2d, const I: usize> RenderCommand<P>
|
|||
for SetMaterial2dBindGroup<M, I>
|
||||
{
|
||||
type Param = (
|
||||
SRes<RenderMaterials2d<M>>,
|
||||
SRes<RenderAssets<PreparedMaterial2d<M>>>,
|
||||
SRes<RenderMaterial2dInstances<M>>,
|
||||
);
|
||||
type ViewQuery = ();
|
||||
|
@ -349,7 +340,7 @@ impl<P: PhaseItem, M: Material2d, const I: usize> RenderCommand<P>
|
|||
let Some(material_instance) = material_instances.get(&item.entity()) else {
|
||||
return RenderCommandResult::Failure;
|
||||
};
|
||||
let Some(material2d) = materials.get(material_instance) else {
|
||||
let Some(material2d) = materials.get(*material_instance) else {
|
||||
return RenderCommandResult::Failure;
|
||||
};
|
||||
pass.set_bind_group(I, &material2d.bind_group, &[]);
|
||||
|
@ -379,8 +370,8 @@ pub fn queue_material2d_meshes<M: Material2d>(
|
|||
mut pipelines: ResMut<SpecializedMeshPipelines<Material2dPipeline<M>>>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
msaa: Res<Msaa>,
|
||||
render_meshes: Res<RenderAssets<Mesh>>,
|
||||
render_materials: Res<RenderMaterials2d<M>>,
|
||||
render_meshes: Res<RenderAssets<GpuMesh>>,
|
||||
render_materials: Res<RenderAssets<PreparedMaterial2d<M>>>,
|
||||
mut render_mesh_instances: ResMut<RenderMesh2dInstances>,
|
||||
render_material_instances: Res<RenderMaterial2dInstances<M>>,
|
||||
mut views: Query<(
|
||||
|
@ -419,7 +410,7 @@ pub fn queue_material2d_meshes<M: Material2d>(
|
|||
let Some(mesh_instance) = render_mesh_instances.get_mut(visible_entity) else {
|
||||
continue;
|
||||
};
|
||||
let Some(material2d) = render_materials.get(material_asset_id) else {
|
||||
let Some(material2d) = render_materials.get(*material_asset_id) else {
|
||||
continue;
|
||||
};
|
||||
let Some(mesh) = render_meshes.get(mesh_instance.mesh_asset_id) else {
|
||||
|
@ -483,157 +474,37 @@ impl<T: Material2d> PreparedMaterial2d<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Resource)]
|
||||
pub struct ExtractedMaterials2d<M: Material2d> {
|
||||
extracted: Vec<(AssetId<M>, M)>,
|
||||
removed: Vec<AssetId<M>>,
|
||||
}
|
||||
impl<M: Material2d> RenderAsset for PreparedMaterial2d<M> {
|
||||
type SourceAsset = M;
|
||||
|
||||
impl<M: Material2d> Default for ExtractedMaterials2d<M> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
extracted: Default::default(),
|
||||
removed: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
type Param = (
|
||||
SRes<RenderDevice>,
|
||||
SRes<RenderAssets<GpuImage>>,
|
||||
SRes<FallbackImage>,
|
||||
SRes<Material2dPipeline<M>>,
|
||||
);
|
||||
|
||||
/// Stores all prepared representations of [`Material2d`] assets for as long as they exist.
|
||||
#[derive(Resource, Deref, DerefMut)]
|
||||
pub struct RenderMaterials2d<T: Material2d>(HashMap<AssetId<T>, PreparedMaterial2d<T>>);
|
||||
|
||||
impl<T: Material2d> Default for RenderMaterials2d<T> {
|
||||
fn default() -> Self {
|
||||
Self(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
/// This system extracts all created or modified assets of the corresponding [`Material2d`] type
|
||||
/// into the "render world".
|
||||
pub fn extract_materials_2d<M: Material2d>(
|
||||
mut commands: Commands,
|
||||
mut events: Extract<EventReader<AssetEvent<M>>>,
|
||||
assets: Extract<Res<Assets<M>>>,
|
||||
) {
|
||||
let mut changed_assets = HashSet::default();
|
||||
let mut removed = Vec::new();
|
||||
for event in events.read() {
|
||||
#[allow(clippy::match_same_arms)]
|
||||
match event {
|
||||
AssetEvent::Added { id } | AssetEvent::Modified { id } => {
|
||||
changed_assets.insert(*id);
|
||||
}
|
||||
AssetEvent::Removed { id } => {
|
||||
changed_assets.remove(id);
|
||||
removed.push(*id);
|
||||
}
|
||||
AssetEvent::Unused { .. } => {}
|
||||
AssetEvent::LoadedWithDependencies { .. } => {
|
||||
// TODO: handle this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut extracted_assets = Vec::new();
|
||||
for id in changed_assets.drain() {
|
||||
if let Some(asset) = assets.get(id) {
|
||||
extracted_assets.push((id, asset.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
commands.insert_resource(ExtractedMaterials2d {
|
||||
extracted: extracted_assets,
|
||||
removed,
|
||||
});
|
||||
}
|
||||
|
||||
/// All [`Material2d`] values of a given type that should be prepared next frame.
|
||||
pub struct PrepareNextFrameMaterials<M: Material2d> {
|
||||
assets: Vec<(AssetId<M>, M)>,
|
||||
}
|
||||
|
||||
impl<M: Material2d> Default for PrepareNextFrameMaterials<M> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
assets: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This system prepares all assets of the corresponding [`Material2d`] type
|
||||
/// which where extracted this frame for the GPU.
|
||||
pub fn prepare_materials_2d<M: Material2d>(
|
||||
mut prepare_next_frame: Local<PrepareNextFrameMaterials<M>>,
|
||||
mut extracted_assets: ResMut<ExtractedMaterials2d<M>>,
|
||||
mut render_materials: ResMut<RenderMaterials2d<M>>,
|
||||
render_device: Res<RenderDevice>,
|
||||
images: Res<RenderAssets<Image>>,
|
||||
fallback_image: Res<FallbackImage>,
|
||||
pipeline: Res<Material2dPipeline<M>>,
|
||||
) {
|
||||
let queued_assets = std::mem::take(&mut prepare_next_frame.assets);
|
||||
for (id, material) in queued_assets {
|
||||
if extracted_assets.removed.contains(&id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
match prepare_material2d(
|
||||
&material,
|
||||
&render_device,
|
||||
&images,
|
||||
&fallback_image,
|
||||
&pipeline,
|
||||
fn prepare_asset(
|
||||
material: Self::SourceAsset,
|
||||
(render_device, images, fallback_image, pipeline): &mut SystemParamItem<Self::Param>,
|
||||
) -> Result<Self, bevy_render::render_asset::PrepareAssetError<Self::SourceAsset>> {
|
||||
match material.as_bind_group(
|
||||
&pipeline.material2d_layout,
|
||||
render_device,
|
||||
images,
|
||||
fallback_image,
|
||||
) {
|
||||
Ok(prepared_asset) => {
|
||||
render_materials.insert(id, prepared_asset);
|
||||
}
|
||||
Ok(prepared) => Ok(PreparedMaterial2d {
|
||||
bindings: prepared.bindings,
|
||||
bind_group: prepared.bind_group,
|
||||
key: prepared.data,
|
||||
depth_bias: material.depth_bias(),
|
||||
}),
|
||||
Err(AsBindGroupError::RetryNextUpdate) => {
|
||||
prepare_next_frame.assets.push((id, material));
|
||||
Err(PrepareAssetError::RetryNextUpdate(material))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for removed in std::mem::take(&mut extracted_assets.removed) {
|
||||
render_materials.remove(&removed);
|
||||
}
|
||||
|
||||
for (asset_id, material) in std::mem::take(&mut extracted_assets.extracted) {
|
||||
match prepare_material2d(
|
||||
&material,
|
||||
&render_device,
|
||||
&images,
|
||||
&fallback_image,
|
||||
&pipeline,
|
||||
) {
|
||||
Ok(prepared_asset) => {
|
||||
render_materials.insert(asset_id, prepared_asset);
|
||||
}
|
||||
Err(AsBindGroupError::RetryNextUpdate) => {
|
||||
prepare_next_frame.assets.push((asset_id, material));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn prepare_material2d<M: Material2d>(
|
||||
material: &M,
|
||||
render_device: &RenderDevice,
|
||||
images: &RenderAssets<Image>,
|
||||
fallback_image: &FallbackImage,
|
||||
pipeline: &Material2dPipeline<M>,
|
||||
) -> Result<PreparedMaterial2d<M>, AsBindGroupError> {
|
||||
let prepared = material.as_bind_group(
|
||||
&pipeline.material2d_layout,
|
||||
render_device,
|
||||
images,
|
||||
fallback_image,
|
||||
)?;
|
||||
Ok(PreparedMaterial2d {
|
||||
bindings: prepared.bindings,
|
||||
bind_group: prepared.bind_group,
|
||||
key: prepared.data,
|
||||
depth_bias: material.depth_bias(),
|
||||
})
|
||||
}
|
||||
|
||||
/// A component bundle for entities with a [`Mesh2dHandle`] and a [`Material2d`].
|
||||
|
|
|
@ -11,7 +11,7 @@ use bevy_ecs::{
|
|||
};
|
||||
use bevy_math::{Affine3, Vec4};
|
||||
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||
use bevy_render::mesh::MeshVertexBufferLayoutRef;
|
||||
use bevy_render::mesh::{GpuMesh, MeshVertexBufferLayoutRef};
|
||||
use bevy_render::{
|
||||
batching::{
|
||||
batch_and_prepare_sorted_render_phase, write_batched_instance_buffer, GetBatchData,
|
||||
|
@ -323,7 +323,7 @@ impl FromWorld for Mesh2dPipeline {
|
|||
impl Mesh2dPipeline {
|
||||
pub fn get_image_texture<'a>(
|
||||
&'a self,
|
||||
gpu_images: &'a RenderAssets<Image>,
|
||||
gpu_images: &'a RenderAssets<GpuImage>,
|
||||
handle_option: &Option<Handle<Image>>,
|
||||
) -> Option<(&'a TextureView, &'a Sampler)> {
|
||||
if let Some(handle) = handle_option {
|
||||
|
@ -666,7 +666,7 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMesh2dBindGroup<I> {
|
|||
|
||||
pub struct DrawMesh2d;
|
||||
impl<P: PhaseItem> RenderCommand<P> for DrawMesh2d {
|
||||
type Param = (SRes<RenderAssets<Mesh>>, SRes<RenderMesh2dInstances>);
|
||||
type Param = (SRes<RenderAssets<GpuMesh>>, SRes<RenderMesh2dInstances>);
|
||||
type ViewQuery = ();
|
||||
type ItemQuery = ();
|
||||
|
||||
|
|
|
@ -528,7 +528,7 @@ pub fn prepare_sprites(
|
|||
view_uniforms: Res<ViewUniforms>,
|
||||
sprite_pipeline: Res<SpritePipeline>,
|
||||
mut image_bind_groups: ResMut<ImageBindGroups>,
|
||||
gpu_images: Res<RenderAssets<Image>>,
|
||||
gpu_images: Res<RenderAssets<GpuImage>>,
|
||||
extracted_sprites: Res<ExtractedSprites>,
|
||||
mut phases: Query<&mut SortedRenderPhase<Transparent2d>>,
|
||||
events: Res<SpriteAssetEvents>,
|
||||
|
|
|
@ -7,6 +7,7 @@ use bevy_core_pipeline::core_2d::graph::{Core2d, Node2d};
|
|||
use bevy_core_pipeline::core_3d::graph::{Core3d, Node3d};
|
||||
use bevy_core_pipeline::{core_2d::Camera2d, core_3d::Camera3d};
|
||||
use bevy_hierarchy::Parent;
|
||||
use bevy_render::texture::GpuImage;
|
||||
use bevy_render::{render_phase::PhaseItem, view::ViewVisibility, ExtractSchedule, Render};
|
||||
use bevy_sprite::{SpriteAssetEvents, TextureAtlas};
|
||||
pub use pipeline::*;
|
||||
|
@ -920,7 +921,7 @@ pub fn prepare_uinodes(
|
|||
view_uniforms: Res<ViewUniforms>,
|
||||
ui_pipeline: Res<UiPipeline>,
|
||||
mut image_bind_groups: ResMut<UiImageBindGroups>,
|
||||
gpu_images: Res<RenderAssets<Image>>,
|
||||
gpu_images: Res<RenderAssets<GpuImage>>,
|
||||
mut phases: Query<&mut SortedRenderPhase<TransparentUi>>,
|
||||
events: Res<SpriteAssetEvents>,
|
||||
mut previous_len: Local<usize>,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::{hash::Hash, marker::PhantomData, ops::Range};
|
||||
|
||||
use bevy_asset::*;
|
||||
use bevy_derive::{Deref, DerefMut};
|
||||
use bevy_ecs::{
|
||||
prelude::Component,
|
||||
query::ROQueryItem,
|
||||
|
@ -13,16 +12,15 @@ use bevy_math::{FloatOrd, Mat4, Rect, Vec2, Vec4Swizzles};
|
|||
use bevy_render::{
|
||||
extract_component::ExtractComponentPlugin,
|
||||
globals::{GlobalsBuffer, GlobalsUniform},
|
||||
render_asset::RenderAssets,
|
||||
render_asset::{PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssets},
|
||||
render_phase::*,
|
||||
render_resource::{binding_types::uniform_buffer, *},
|
||||
renderer::{RenderDevice, RenderQueue},
|
||||
texture::{BevyDefault, FallbackImage, Image},
|
||||
texture::{BevyDefault, FallbackImage, GpuImage},
|
||||
view::*,
|
||||
Extract, ExtractSchedule, Render, RenderSet,
|
||||
};
|
||||
use bevy_transform::prelude::GlobalTransform;
|
||||
use bevy_utils::{HashMap, HashSet};
|
||||
use bevy_window::{PrimaryWindow, Window};
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
|
||||
|
@ -59,28 +57,24 @@ where
|
|||
"ui_material.wgsl",
|
||||
Shader::from_wgsl
|
||||
);
|
||||
app.init_asset::<M>()
|
||||
.add_plugins(ExtractComponentPlugin::<Handle<M>>::extract_visible());
|
||||
app.init_asset::<M>().add_plugins((
|
||||
ExtractComponentPlugin::<Handle<M>>::extract_visible(),
|
||||
RenderAssetPlugin::<PreparedUiMaterial<M>>::default(),
|
||||
));
|
||||
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app
|
||||
.add_render_command::<TransparentUi, DrawUiMaterial<M>>()
|
||||
.init_resource::<ExtractedUiMaterials<M>>()
|
||||
.init_resource::<ExtractedUiMaterialNodes<M>>()
|
||||
.init_resource::<RenderUiMaterials<M>>()
|
||||
.init_resource::<UiMaterialMeta<M>>()
|
||||
.init_resource::<SpecializedRenderPipelines<UiMaterialPipeline<M>>>()
|
||||
.add_systems(
|
||||
ExtractSchedule,
|
||||
(
|
||||
extract_ui_materials::<M>,
|
||||
extract_ui_material_nodes::<M>.in_set(RenderUiSystem::ExtractBackgrounds),
|
||||
),
|
||||
extract_ui_material_nodes::<M>.in_set(RenderUiSystem::ExtractBackgrounds),
|
||||
)
|
||||
.add_systems(
|
||||
Render,
|
||||
(
|
||||
prepare_ui_materials::<M>.in_set(RenderSet::PrepareAssets),
|
||||
queue_ui_material_nodes::<M>.in_set(RenderSet::Queue),
|
||||
prepare_uimaterial_nodes::<M>.in_set(RenderSet::PrepareBindGroups),
|
||||
),
|
||||
|
@ -286,7 +280,7 @@ pub struct SetUiMaterialBindGroup<M: UiMaterial, const I: usize>(PhantomData<M>)
|
|||
impl<P: PhaseItem, M: UiMaterial, const I: usize> RenderCommand<P>
|
||||
for SetUiMaterialBindGroup<M, I>
|
||||
{
|
||||
type Param = SRes<RenderUiMaterials<M>>;
|
||||
type Param = SRes<RenderAssets<PreparedUiMaterial<M>>>;
|
||||
type ViewQuery = ();
|
||||
type ItemQuery = Read<UiMaterialBatch<M>>;
|
||||
|
||||
|
@ -300,7 +294,7 @@ impl<P: PhaseItem, M: UiMaterial, const I: usize> RenderCommand<P>
|
|||
let Some(material_handle) = material_handle else {
|
||||
return RenderCommandResult::Failure;
|
||||
};
|
||||
let Some(material) = materials.into_inner().get(&material_handle.material) else {
|
||||
let Some(material) = materials.into_inner().get(material_handle.material) else {
|
||||
return RenderCommandResult::Failure;
|
||||
};
|
||||
pass.set_bind_group(I, &material.bind_group, &[]);
|
||||
|
@ -601,152 +595,37 @@ pub fn prepare_uimaterial_nodes<M: UiMaterial>(
|
|||
extracted_uinodes.uinodes.clear();
|
||||
}
|
||||
|
||||
#[derive(Resource, Deref, DerefMut)]
|
||||
pub struct RenderUiMaterials<T: UiMaterial>(HashMap<AssetId<T>, PreparedUiMaterial<T>>);
|
||||
|
||||
impl<T: UiMaterial> Default for RenderUiMaterials<T> {
|
||||
fn default() -> Self {
|
||||
Self(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PreparedUiMaterial<T: UiMaterial> {
|
||||
pub bindings: Vec<(u32, OwnedBindingResource)>,
|
||||
pub bind_group: BindGroup,
|
||||
pub key: T::Data,
|
||||
}
|
||||
|
||||
#[derive(Resource)]
|
||||
pub struct ExtractedUiMaterials<M: UiMaterial> {
|
||||
extracted: Vec<(AssetId<M>, M)>,
|
||||
removed: Vec<AssetId<M>>,
|
||||
}
|
||||
impl<M: UiMaterial> RenderAsset for PreparedUiMaterial<M> {
|
||||
type SourceAsset = M;
|
||||
|
||||
impl<M: UiMaterial> Default for ExtractedUiMaterials<M> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
extracted: Default::default(),
|
||||
removed: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
type Param = (
|
||||
SRes<RenderDevice>,
|
||||
SRes<RenderAssets<GpuImage>>,
|
||||
SRes<FallbackImage>,
|
||||
SRes<UiMaterialPipeline<M>>,
|
||||
);
|
||||
|
||||
pub fn extract_ui_materials<M: UiMaterial>(
|
||||
mut commands: Commands,
|
||||
mut events: Extract<EventReader<AssetEvent<M>>>,
|
||||
assets: Extract<Res<Assets<M>>>,
|
||||
) {
|
||||
let mut changed_assets = HashSet::default();
|
||||
let mut removed = Vec::new();
|
||||
for event in events.read() {
|
||||
#[allow(clippy::match_same_arms)]
|
||||
match event {
|
||||
AssetEvent::Added { id } | AssetEvent::Modified { id } => {
|
||||
changed_assets.insert(*id);
|
||||
}
|
||||
AssetEvent::Removed { id } => {
|
||||
changed_assets.remove(id);
|
||||
removed.push(*id);
|
||||
}
|
||||
AssetEvent::Unused { .. } => {}
|
||||
AssetEvent::LoadedWithDependencies { .. } => {
|
||||
// TODO: handle this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut extracted_assets = Vec::new();
|
||||
for id in changed_assets.drain() {
|
||||
if let Some(asset) = assets.get(id) {
|
||||
extracted_assets.push((id, asset.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
commands.insert_resource(ExtractedUiMaterials {
|
||||
extracted: extracted_assets,
|
||||
removed,
|
||||
});
|
||||
}
|
||||
|
||||
pub struct PrepareNextFrameMaterials<M: UiMaterial> {
|
||||
assets: Vec<(AssetId<M>, M)>,
|
||||
}
|
||||
|
||||
impl<M: UiMaterial> Default for PrepareNextFrameMaterials<M> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
assets: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prepare_ui_materials<M: UiMaterial>(
|
||||
mut prepare_next_frame: Local<PrepareNextFrameMaterials<M>>,
|
||||
mut extracted_assets: ResMut<ExtractedUiMaterials<M>>,
|
||||
mut render_materials: ResMut<RenderUiMaterials<M>>,
|
||||
render_device: Res<RenderDevice>,
|
||||
images: Res<RenderAssets<Image>>,
|
||||
fallback_image: Res<FallbackImage>,
|
||||
pipeline: Res<UiMaterialPipeline<M>>,
|
||||
) {
|
||||
let queued_assets = std::mem::take(&mut prepare_next_frame.assets);
|
||||
for (id, material) in queued_assets {
|
||||
if extracted_assets.removed.contains(&id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
match prepare_ui_material(
|
||||
&material,
|
||||
&render_device,
|
||||
&images,
|
||||
&fallback_image,
|
||||
&pipeline,
|
||||
) {
|
||||
Ok(prepared_asset) => {
|
||||
render_materials.insert(id, prepared_asset);
|
||||
}
|
||||
fn prepare_asset(
|
||||
material: Self::SourceAsset,
|
||||
(render_device, images, fallback_image, pipeline): &mut SystemParamItem<Self::Param>,
|
||||
) -> Result<Self, PrepareAssetError<Self::SourceAsset>> {
|
||||
match material.as_bind_group(&pipeline.ui_layout, render_device, images, fallback_image) {
|
||||
Ok(prepared) => Ok(PreparedUiMaterial {
|
||||
bindings: prepared.bindings,
|
||||
bind_group: prepared.bind_group,
|
||||
key: prepared.data,
|
||||
}),
|
||||
Err(AsBindGroupError::RetryNextUpdate) => {
|
||||
prepare_next_frame.assets.push((id, material));
|
||||
Err(PrepareAssetError::RetryNextUpdate(material))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for removed in std::mem::take(&mut extracted_assets.removed) {
|
||||
render_materials.remove(&removed);
|
||||
}
|
||||
|
||||
for (handle, material) in std::mem::take(&mut extracted_assets.extracted) {
|
||||
match prepare_ui_material(
|
||||
&material,
|
||||
&render_device,
|
||||
&images,
|
||||
&fallback_image,
|
||||
&pipeline,
|
||||
) {
|
||||
Ok(prepared_asset) => {
|
||||
render_materials.insert(handle, prepared_asset);
|
||||
}
|
||||
Err(AsBindGroupError::RetryNextUpdate) => {
|
||||
prepare_next_frame.assets.push((handle, material));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn prepare_ui_material<M: UiMaterial>(
|
||||
material: &M,
|
||||
render_device: &RenderDevice,
|
||||
images: &RenderAssets<Image>,
|
||||
fallback_image: &Res<FallbackImage>,
|
||||
pipeline: &UiMaterialPipeline<M>,
|
||||
) -> Result<PreparedUiMaterial<M>, AsBindGroupError> {
|
||||
let prepared =
|
||||
material.as_bind_group(&pipeline.ui_layout, render_device, images, fallback_image)?;
|
||||
Ok(PreparedUiMaterial {
|
||||
bindings: prepared.bindings,
|
||||
bind_group: prepared.bind_group,
|
||||
key: prepared.data,
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
|
@ -756,7 +635,7 @@ pub fn queue_ui_material_nodes<M: UiMaterial>(
|
|||
ui_material_pipeline: Res<UiMaterialPipeline<M>>,
|
||||
mut pipelines: ResMut<SpecializedRenderPipelines<UiMaterialPipeline<M>>>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
render_materials: Res<RenderUiMaterials<M>>,
|
||||
render_materials: Res<RenderAssets<PreparedUiMaterial<M>>>,
|
||||
mut views: Query<(&ExtractedView, &mut SortedRenderPhase<TransparentUi>)>,
|
||||
) where
|
||||
M::Data: PartialEq + Eq + Hash + Clone,
|
||||
|
@ -764,7 +643,7 @@ pub fn queue_ui_material_nodes<M: UiMaterial>(
|
|||
let draw_function = draw_functions.read().id::<DrawUiMaterial<M>>();
|
||||
|
||||
for (entity, extracted_uinode) in extracted_uinodes.uinodes.iter() {
|
||||
let Some(material) = render_materials.get(&extracted_uinode.material) else {
|
||||
let Some(material) = render_materials.get(extracted_uinode.material) else {
|
||||
continue;
|
||||
};
|
||||
let Ok((view, mut transparent_phase)) = views.get_mut(extracted_uinode.camera_entity)
|
||||
|
|
|
@ -11,7 +11,7 @@ use bevy::{
|
|||
math::FloatOrd,
|
||||
prelude::*,
|
||||
render::{
|
||||
mesh::{Indices, MeshVertexAttribute},
|
||||
mesh::{GpuMesh, Indices, MeshVertexAttribute},
|
||||
render_asset::{RenderAssetUsages, RenderAssets},
|
||||
render_phase::{AddRenderCommand, DrawFunctions, SetItemPipeline, SortedRenderPhase},
|
||||
render_resource::{
|
||||
|
@ -356,7 +356,7 @@ pub fn queue_colored_mesh2d(
|
|||
mut pipelines: ResMut<SpecializedRenderPipelines<ColoredMesh2dPipeline>>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
msaa: Res<Msaa>,
|
||||
render_meshes: Res<RenderAssets<Mesh>>,
|
||||
render_meshes: Res<RenderAssets<GpuMesh>>,
|
||||
render_mesh_instances: Res<RenderMesh2dInstances>,
|
||||
mut views: Query<(
|
||||
&VisibleEntities,
|
||||
|
|
|
@ -11,6 +11,7 @@ use bevy::{
|
|||
render_graph::{self, RenderGraph, RenderLabel},
|
||||
render_resource::{binding_types::texture_storage_2d, *},
|
||||
renderer::{RenderContext, RenderDevice},
|
||||
texture::GpuImage,
|
||||
Render, RenderApp, RenderSet,
|
||||
},
|
||||
};
|
||||
|
@ -129,7 +130,7 @@ struct GameOfLifeImageBindGroups([BindGroup; 2]);
|
|||
fn prepare_bind_group(
|
||||
mut commands: Commands,
|
||||
pipeline: Res<GameOfLifePipeline>,
|
||||
gpu_images: Res<RenderAssets<Image>>,
|
||||
gpu_images: Res<RenderAssets<GpuImage>>,
|
||||
game_of_life_images: Res<GameOfLifeImages>,
|
||||
render_device: Res<RenderDevice>,
|
||||
) {
|
||||
|
|
|
@ -12,7 +12,7 @@ use bevy::{
|
|||
prelude::*,
|
||||
render::{
|
||||
extract_component::{ExtractComponent, ExtractComponentPlugin},
|
||||
mesh::{GpuBufferInfo, MeshVertexBufferLayoutRef},
|
||||
mesh::{GpuBufferInfo, GpuMesh, MeshVertexBufferLayoutRef},
|
||||
render_asset::RenderAssets,
|
||||
render_phase::{
|
||||
AddRenderCommand, DrawFunctions, PhaseItem, RenderCommand, RenderCommandResult,
|
||||
|
@ -114,7 +114,7 @@ fn queue_custom(
|
|||
msaa: Res<Msaa>,
|
||||
mut pipelines: ResMut<SpecializedMeshPipelines<CustomPipeline>>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
meshes: Res<RenderAssets<Mesh>>,
|
||||
meshes: Res<RenderAssets<GpuMesh>>,
|
||||
render_mesh_instances: Res<RenderMeshInstances>,
|
||||
material_meshes: Query<Entity, With<InstanceMaterialData>>,
|
||||
mut views: Query<(&ExtractedView, &mut SortedRenderPhase<Transparent3d>)>,
|
||||
|
@ -234,7 +234,7 @@ type DrawCustom = (
|
|||
struct DrawMeshInstanced;
|
||||
|
||||
impl<P: PhaseItem> RenderCommand<P> for DrawMeshInstanced {
|
||||
type Param = (SRes<RenderAssets<Mesh>>, SRes<RenderMeshInstances>);
|
||||
type Param = (SRes<RenderAssets<GpuMesh>>, SRes<RenderMeshInstances>);
|
||||
type ViewQuery = ();
|
||||
type ItemQuery = Read<InstanceBuffer>;
|
||||
|
||||
|
|
|
@ -5,8 +5,11 @@ use bevy::{
|
|||
prelude::*,
|
||||
reflect::TypePath,
|
||||
render::{
|
||||
render_asset::RenderAssets, render_resource::*, renderer::RenderDevice,
|
||||
texture::FallbackImage, RenderApp,
|
||||
render_asset::RenderAssets,
|
||||
render_resource::*,
|
||||
renderer::RenderDevice,
|
||||
texture::{FallbackImage, GpuImage},
|
||||
RenderApp,
|
||||
},
|
||||
};
|
||||
use std::{num::NonZeroU32, process::exit};
|
||||
|
@ -92,7 +95,7 @@ impl AsBindGroup for BindlessMaterial {
|
|||
&self,
|
||||
layout: &BindGroupLayout,
|
||||
render_device: &RenderDevice,
|
||||
image_assets: &RenderAssets<Image>,
|
||||
image_assets: &RenderAssets<GpuImage>,
|
||||
fallback_image: &FallbackImage,
|
||||
) -> Result<PreparedBindGroup<Self::Data>, AsBindGroupError> {
|
||||
// retrieve the render resources from handles
|
||||
|
@ -133,7 +136,7 @@ impl AsBindGroup for BindlessMaterial {
|
|||
&self,
|
||||
_: &BindGroupLayout,
|
||||
_: &RenderDevice,
|
||||
_: &RenderAssets<Image>,
|
||||
_: &RenderAssets<GpuImage>,
|
||||
_: &FallbackImage,
|
||||
) -> Result<UnpreparedBindGroup<Self::Data>, AsBindGroupError> {
|
||||
// we implement as_bind_group directly because
|
||||
|
|
Loading…
Reference in a new issue