2023-06-13 06:49:47 +00:00
|
|
|
use crate::{
|
|
|
|
line_gizmo_vertex_buffer_layouts, DrawLineGizmo, GizmoConfig, LineGizmo,
|
|
|
|
LineGizmoUniformBindgroupLayout, SetLineGizmoBindGroup, LINE_SHADER_HANDLE,
|
|
|
|
};
|
|
|
|
use bevy_app::{App, Plugin};
|
2023-03-20 20:57:54 +00:00
|
|
|
use bevy_asset::Handle;
|
2023-06-13 06:49:47 +00:00
|
|
|
use bevy_core_pipeline::core_3d::Transparent3d;
|
|
|
|
|
2023-03-20 20:57:54 +00:00
|
|
|
use bevy_ecs::{
|
2023-06-13 06:49:47 +00:00
|
|
|
prelude::Entity,
|
|
|
|
schedule::IntoSystemConfigs,
|
2023-03-20 20:57:54 +00:00
|
|
|
system::{Query, Res, ResMut, Resource},
|
|
|
|
world::{FromWorld, World},
|
|
|
|
};
|
improve shader import model (#5703)
# Objective
operate on naga IR directly to improve handling of shader modules.
- give codespan reporting into imported modules
- allow glsl to be used from wgsl and vice-versa
the ultimate objective is to make it possible to
- provide user hooks for core shader functions (to modify light
behaviour within the standard pbr pipeline, for example)
- make automatic binding slot allocation possible
but ... since this is already big, adds some value and (i think) is at
feature parity with the existing code, i wanted to push this now.
## Solution
i made a crate called naga_oil (https://github.com/robtfm/naga_oil -
unpublished for now, could be part of bevy) which manages modules by
- building each module independantly to naga IR
- creating "header" files for each supported language, which are used to
build dependent modules/shaders
- make final shaders by combining the shader IR with the IR for imported
modules
then integrated this into bevy, replacing some of the existing shader
processing stuff. also reworked examples to reflect this.
## Migration Guide
shaders that don't use `#import` directives should work without changes.
the most notable user-facing difference is that imported
functions/variables/etc need to be qualified at point of use, and
there's no "leakage" of visible stuff into your shader scope from the
imports of your imports, so if you used things imported by your imports,
you now need to import them directly and qualify them.
the current strategy of including/'spreading' `mesh_vertex_output`
directly into a struct doesn't work any more, so these need to be
modified as per the examples (e.g. color_material.wgsl, or many others).
mesh data is assumed to be in bindgroup 2 by default, if mesh data is
bound into bindgroup 1 instead then the shader def `MESH_BINDGROUP_1`
needs to be added to the pipeline shader_defs.
2023-06-27 00:29:22 +00:00
|
|
|
use bevy_pbr::{MeshPipeline, MeshPipelineKey, SetMeshViewBindGroup};
|
2023-03-20 20:57:54 +00:00
|
|
|
use bevy_render::{
|
Reorder render sets, refactor bevy_sprite to take advantage (#9236)
This is a continuation of this PR: #8062
# Objective
- Reorder render schedule sets to allow data preparation when phase item
order is known to support improved batching
- Part of the batching/instancing etc plan from here:
https://github.com/bevyengine/bevy/issues/89#issuecomment-1379249074
- The original idea came from @inodentry and proved to be a good one.
Thanks!
- Refactor `bevy_sprite` and `bevy_ui` to take advantage of the new
ordering
## Solution
- Move `Prepare` and `PrepareFlush` after `PhaseSortFlush`
- Add a `PrepareAssets` set that runs in parallel with other systems and
sets in the render schedule.
- Put prepare_assets systems in the `PrepareAssets` set
- If explicit dependencies are needed on Mesh or Material RenderAssets
then depend on the appropriate system.
- Add `ManageViews` and `ManageViewsFlush` sets between
`ExtractCommands` and Queue
- Move `queue_mesh*_bind_group` to the Prepare stage
- Rename them to `prepare_`
- Put systems that prepare resources (buffers, textures, etc.) into a
`PrepareResources` set inside `Prepare`
- Put the `prepare_..._bind_group` systems into a `PrepareBindGroup` set
after `PrepareResources`
- Move `prepare_lights` to the `ManageViews` set
- `prepare_lights` creates views and this must happen before `Queue`
- This system needs refactoring to stop handling all responsibilities
- Gather lights, sort, and create shadow map views. Store sorted light
entities in a resource
- Remove `BatchedPhaseItem`
- Replace `batch_range` with `batch_size` representing how many items to
skip after rendering the item or to skip the item entirely if
`batch_size` is 0.
- `queue_sprites` has been split into `queue_sprites` for queueing phase
items and `prepare_sprites` for batching after the `PhaseSort`
- `PhaseItem`s are still inserted in `queue_sprites`
- After sorting adjacent compatible sprite phase items are accumulated
into `SpriteBatch` components on the first entity of each batch,
containing a range of vertex indices. The associated `PhaseItem`'s
`batch_size` is updated appropriately.
- `SpriteBatch` items are then drawn skipping over the other items in
the batch based on the value in `batch_size`
- A very similar refactor was performed on `bevy_ui`
---
## Changelog
Changed:
- Reordered and reworked render app schedule sets. The main change is
that data is extracted, queued, sorted, and then prepared when the order
of data is known.
- Refactor `bevy_sprite` and `bevy_ui` to take advantage of the
reordering.
## Migration Guide
- Assets such as materials and meshes should now be created in
`PrepareAssets` e.g. `prepare_assets<Mesh>`
- Queueing entities to `RenderPhase`s continues to be done in `Queue`
e.g. `queue_sprites`
- Preparing resources (textures, buffers, etc.) should now be done in
`PrepareResources`, e.g. `prepare_prepass_textures`,
`prepare_mesh_uniforms`
- Prepare bind groups should now be done in `PrepareBindGroups` e.g.
`prepare_mesh_bind_group`
- Any batching or instancing can now be done in `Prepare` where the
order of the phase items is known e.g. `prepare_sprites`
## Next Steps
- Introduce some generic mechanism to ensure items that can be batched
are grouped in the phase item order, currently you could easily have
`[sprite at z 0, mesh at z 0, sprite at z 0]` preventing batching.
- Investigate improved orderings for building the MeshUniform buffer
- Implementing batching across the rest of bevy
---------
Co-authored-by: Robert Swain <robert.swain@gmail.com>
Co-authored-by: robtfm <50659922+robtfm@users.noreply.github.com>
2023-08-27 14:33:49 +00:00
|
|
|
render_asset::{prepare_assets, RenderAssets},
|
2023-06-13 06:49:47 +00:00
|
|
|
render_phase::{AddRenderCommand, DrawFunctions, RenderPhase, SetItemPipeline},
|
2023-03-20 20:57:54 +00:00
|
|
|
render_resource::*,
|
|
|
|
texture::BevyDefault,
|
2023-06-29 00:56:31 +00:00
|
|
|
view::{ExtractedView, Msaa, RenderLayers, ViewTarget},
|
2023-06-13 06:49:47 +00:00
|
|
|
Render, RenderApp, RenderSet,
|
2023-03-20 20:57:54 +00:00
|
|
|
};
|
|
|
|
|
2023-06-13 06:49:47 +00:00
|
|
|
pub struct LineGizmo3dPlugin;
|
|
|
|
impl Plugin for LineGizmo3dPlugin {
|
|
|
|
fn build(&self, app: &mut App) {
|
2023-08-25 12:34:24 +00:00
|
|
|
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
|
|
|
return;
|
|
|
|
};
|
2023-03-20 20:57:54 +00:00
|
|
|
|
2023-06-13 06:49:47 +00:00
|
|
|
render_app
|
|
|
|
.add_render_command::<Transparent3d, DrawLineGizmo3d>()
|
|
|
|
.init_resource::<SpecializedRenderPipelines<LineGizmoPipeline>>()
|
Reorder render sets, refactor bevy_sprite to take advantage (#9236)
This is a continuation of this PR: #8062
# Objective
- Reorder render schedule sets to allow data preparation when phase item
order is known to support improved batching
- Part of the batching/instancing etc plan from here:
https://github.com/bevyengine/bevy/issues/89#issuecomment-1379249074
- The original idea came from @inodentry and proved to be a good one.
Thanks!
- Refactor `bevy_sprite` and `bevy_ui` to take advantage of the new
ordering
## Solution
- Move `Prepare` and `PrepareFlush` after `PhaseSortFlush`
- Add a `PrepareAssets` set that runs in parallel with other systems and
sets in the render schedule.
- Put prepare_assets systems in the `PrepareAssets` set
- If explicit dependencies are needed on Mesh or Material RenderAssets
then depend on the appropriate system.
- Add `ManageViews` and `ManageViewsFlush` sets between
`ExtractCommands` and Queue
- Move `queue_mesh*_bind_group` to the Prepare stage
- Rename them to `prepare_`
- Put systems that prepare resources (buffers, textures, etc.) into a
`PrepareResources` set inside `Prepare`
- Put the `prepare_..._bind_group` systems into a `PrepareBindGroup` set
after `PrepareResources`
- Move `prepare_lights` to the `ManageViews` set
- `prepare_lights` creates views and this must happen before `Queue`
- This system needs refactoring to stop handling all responsibilities
- Gather lights, sort, and create shadow map views. Store sorted light
entities in a resource
- Remove `BatchedPhaseItem`
- Replace `batch_range` with `batch_size` representing how many items to
skip after rendering the item or to skip the item entirely if
`batch_size` is 0.
- `queue_sprites` has been split into `queue_sprites` for queueing phase
items and `prepare_sprites` for batching after the `PhaseSort`
- `PhaseItem`s are still inserted in `queue_sprites`
- After sorting adjacent compatible sprite phase items are accumulated
into `SpriteBatch` components on the first entity of each batch,
containing a range of vertex indices. The associated `PhaseItem`'s
`batch_size` is updated appropriately.
- `SpriteBatch` items are then drawn skipping over the other items in
the batch based on the value in `batch_size`
- A very similar refactor was performed on `bevy_ui`
---
## Changelog
Changed:
- Reordered and reworked render app schedule sets. The main change is
that data is extracted, queued, sorted, and then prepared when the order
of data is known.
- Refactor `bevy_sprite` and `bevy_ui` to take advantage of the
reordering.
## Migration Guide
- Assets such as materials and meshes should now be created in
`PrepareAssets` e.g. `prepare_assets<Mesh>`
- Queueing entities to `RenderPhase`s continues to be done in `Queue`
e.g. `queue_sprites`
- Preparing resources (textures, buffers, etc.) should now be done in
`PrepareResources`, e.g. `prepare_prepass_textures`,
`prepare_mesh_uniforms`
- Prepare bind groups should now be done in `PrepareBindGroups` e.g.
`prepare_mesh_bind_group`
- Any batching or instancing can now be done in `Prepare` where the
order of the phase items is known e.g. `prepare_sprites`
## Next Steps
- Introduce some generic mechanism to ensure items that can be batched
are grouped in the phase item order, currently you could easily have
`[sprite at z 0, mesh at z 0, sprite at z 0]` preventing batching.
- Investigate improved orderings for building the MeshUniform buffer
- Implementing batching across the rest of bevy
---------
Co-authored-by: Robert Swain <robert.swain@gmail.com>
Co-authored-by: robtfm <50659922+robtfm@users.noreply.github.com>
2023-08-27 14:33:49 +00:00
|
|
|
.add_systems(
|
|
|
|
Render,
|
|
|
|
queue_line_gizmos_3d
|
|
|
|
.in_set(RenderSet::Queue)
|
|
|
|
.after(prepare_assets::<LineGizmo>),
|
|
|
|
);
|
2023-06-13 06:49:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn finish(&self, app: &mut App) {
|
2023-08-25 12:34:24 +00:00
|
|
|
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
|
|
|
return;
|
|
|
|
};
|
2023-06-13 06:49:47 +00:00
|
|
|
|
|
|
|
render_app.init_resource::<LineGizmoPipeline>();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Resource)]
|
|
|
|
struct LineGizmoPipeline {
|
2023-03-20 20:57:54 +00:00
|
|
|
mesh_pipeline: MeshPipeline,
|
2023-06-13 06:49:47 +00:00
|
|
|
uniform_layout: BindGroupLayout,
|
2023-03-20 20:57:54 +00:00
|
|
|
}
|
|
|
|
|
2023-06-13 06:49:47 +00:00
|
|
|
impl FromWorld for LineGizmoPipeline {
|
2023-03-20 20:57:54 +00:00
|
|
|
fn from_world(render_world: &mut World) -> Self {
|
2023-06-13 06:49:47 +00:00
|
|
|
LineGizmoPipeline {
|
2023-03-20 20:57:54 +00:00
|
|
|
mesh_pipeline: render_world.resource::<MeshPipeline>().clone(),
|
2023-06-13 06:49:47 +00:00
|
|
|
uniform_layout: render_world
|
|
|
|
.resource::<LineGizmoUniformBindgroupLayout>()
|
|
|
|
.layout
|
|
|
|
.clone(),
|
2023-03-20 20:57:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-13 06:49:47 +00:00
|
|
|
#[derive(PartialEq, Eq, Hash, Clone)]
|
|
|
|
struct LineGizmoPipelineKey {
|
|
|
|
mesh_key: MeshPipelineKey,
|
|
|
|
strip: bool,
|
|
|
|
perspective: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SpecializedRenderPipeline for LineGizmoPipeline {
|
|
|
|
type Key = LineGizmoPipelineKey;
|
|
|
|
|
|
|
|
fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
|
|
|
|
let mut shader_defs = vec![
|
|
|
|
#[cfg(feature = "webgl")]
|
|
|
|
"SIXTEEN_BYTE_ALIGNMENT".into(),
|
|
|
|
];
|
2023-03-20 20:57:54 +00:00
|
|
|
|
2023-06-13 06:49:47 +00:00
|
|
|
if key.perspective {
|
|
|
|
shader_defs.push("PERSPECTIVE".into());
|
|
|
|
}
|
2023-03-20 20:57:54 +00:00
|
|
|
|
2023-06-13 06:49:47 +00:00
|
|
|
let format = if key.mesh_key.contains(MeshPipelineKey::HDR) {
|
2023-03-20 20:57:54 +00:00
|
|
|
ViewTarget::TEXTURE_FORMAT_HDR
|
|
|
|
} else {
|
|
|
|
TextureFormat::bevy_default()
|
|
|
|
};
|
|
|
|
|
2023-06-13 06:49:47 +00:00
|
|
|
let view_layout = if key.mesh_key.msaa_samples() == 1 {
|
|
|
|
self.mesh_pipeline.view_layout.clone()
|
|
|
|
} else {
|
|
|
|
self.mesh_pipeline.view_layout_multisampled.clone()
|
|
|
|
};
|
|
|
|
|
|
|
|
let layout = vec![view_layout, self.uniform_layout.clone()];
|
|
|
|
|
|
|
|
RenderPipelineDescriptor {
|
2023-03-20 20:57:54 +00:00
|
|
|
vertex: VertexState {
|
2023-06-13 06:49:47 +00:00
|
|
|
shader: LINE_SHADER_HANDLE.typed(),
|
2023-03-20 20:57:54 +00:00
|
|
|
entry_point: "vertex".into(),
|
|
|
|
shader_defs: shader_defs.clone(),
|
2023-06-13 06:49:47 +00:00
|
|
|
buffers: line_gizmo_vertex_buffer_layouts(key.strip),
|
2023-03-20 20:57:54 +00:00
|
|
|
},
|
|
|
|
fragment: Some(FragmentState {
|
2023-06-13 06:49:47 +00:00
|
|
|
shader: LINE_SHADER_HANDLE.typed(),
|
2023-03-20 20:57:54 +00:00
|
|
|
shader_defs,
|
|
|
|
entry_point: "fragment".into(),
|
|
|
|
targets: vec![Some(ColorTargetState {
|
|
|
|
format,
|
2023-06-13 06:49:47 +00:00
|
|
|
blend: Some(BlendState::ALPHA_BLENDING),
|
2023-03-20 20:57:54 +00:00
|
|
|
write_mask: ColorWrites::ALL,
|
|
|
|
})],
|
|
|
|
}),
|
2023-06-13 06:49:47 +00:00
|
|
|
layout,
|
|
|
|
primitive: PrimitiveState::default(),
|
2023-03-20 20:57:54 +00:00
|
|
|
depth_stencil: Some(DepthStencilState {
|
|
|
|
format: TextureFormat::Depth32Float,
|
|
|
|
depth_write_enabled: true,
|
|
|
|
depth_compare: CompareFunction::Greater,
|
2023-06-13 06:49:47 +00:00
|
|
|
stencil: StencilState::default(),
|
|
|
|
bias: DepthBiasState::default(),
|
2023-03-20 20:57:54 +00:00
|
|
|
}),
|
|
|
|
multisample: MultisampleState {
|
2023-06-13 06:49:47 +00:00
|
|
|
count: key.mesh_key.msaa_samples(),
|
2023-03-20 20:57:54 +00:00
|
|
|
mask: !0,
|
|
|
|
alpha_to_coverage_enabled: false,
|
|
|
|
},
|
2023-06-13 06:49:47 +00:00
|
|
|
label: Some("LineGizmo Pipeline".into()),
|
2023-03-20 20:57:54 +00:00
|
|
|
push_constant_ranges: vec![],
|
2023-06-13 06:49:47 +00:00
|
|
|
}
|
2023-03-20 20:57:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-13 06:49:47 +00:00
|
|
|
type DrawLineGizmo3d = (
|
2023-03-20 20:57:54 +00:00
|
|
|
SetItemPipeline,
|
|
|
|
SetMeshViewBindGroup<0>,
|
2023-06-13 06:49:47 +00:00
|
|
|
SetLineGizmoBindGroup<1>,
|
|
|
|
DrawLineGizmo,
|
2023-03-20 20:57:54 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
#[allow(clippy::too_many_arguments)]
|
2023-06-13 06:49:47 +00:00
|
|
|
fn queue_line_gizmos_3d(
|
|
|
|
draw_functions: Res<DrawFunctions<Transparent3d>>,
|
|
|
|
pipeline: Res<LineGizmoPipeline>,
|
|
|
|
mut pipelines: ResMut<SpecializedRenderPipelines<LineGizmoPipeline>>,
|
2023-03-20 20:57:54 +00:00
|
|
|
pipeline_cache: Res<PipelineCache>,
|
|
|
|
msaa: Res<Msaa>,
|
|
|
|
config: Res<GizmoConfig>,
|
2023-06-13 06:49:47 +00:00
|
|
|
line_gizmos: Query<(Entity, &Handle<LineGizmo>)>,
|
|
|
|
line_gizmo_assets: Res<RenderAssets<LineGizmo>>,
|
2023-06-29 00:56:31 +00:00
|
|
|
mut views: Query<(
|
|
|
|
&ExtractedView,
|
|
|
|
&mut RenderPhase<Transparent3d>,
|
|
|
|
Option<&RenderLayers>,
|
|
|
|
)>,
|
2023-03-20 20:57:54 +00:00
|
|
|
) {
|
2023-06-13 06:49:47 +00:00
|
|
|
let draw_function = draw_functions.read().get_id::<DrawLineGizmo3d>().unwrap();
|
|
|
|
|
2023-06-29 00:56:31 +00:00
|
|
|
for (view, mut transparent_phase, render_layers) in &mut views {
|
|
|
|
let render_layers = render_layers.copied().unwrap_or_default();
|
|
|
|
if !config.render_layers.intersects(&render_layers) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2023-06-13 06:49:47 +00:00
|
|
|
let mesh_key = MeshPipelineKey::from_msaa_samples(msaa.samples())
|
|
|
|
| MeshPipelineKey::from_hdr(view.hdr);
|
|
|
|
|
|
|
|
for (entity, handle) in &line_gizmos {
|
2023-08-25 12:34:24 +00:00
|
|
|
let Some(line_gizmo) = line_gizmo_assets.get(handle) else {
|
|
|
|
continue;
|
|
|
|
};
|
2023-06-13 06:49:47 +00:00
|
|
|
|
|
|
|
let pipeline = pipelines.specialize(
|
|
|
|
&pipeline_cache,
|
|
|
|
&pipeline,
|
|
|
|
LineGizmoPipelineKey {
|
|
|
|
mesh_key,
|
|
|
|
strip: line_gizmo.strip,
|
|
|
|
perspective: config.line_perspective,
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
|
|
|
transparent_phase.add(Transparent3d {
|
|
|
|
entity,
|
|
|
|
draw_function,
|
|
|
|
pipeline,
|
|
|
|
distance: 0.,
|
Reorder render sets, refactor bevy_sprite to take advantage (#9236)
This is a continuation of this PR: #8062
# Objective
- Reorder render schedule sets to allow data preparation when phase item
order is known to support improved batching
- Part of the batching/instancing etc plan from here:
https://github.com/bevyengine/bevy/issues/89#issuecomment-1379249074
- The original idea came from @inodentry and proved to be a good one.
Thanks!
- Refactor `bevy_sprite` and `bevy_ui` to take advantage of the new
ordering
## Solution
- Move `Prepare` and `PrepareFlush` after `PhaseSortFlush`
- Add a `PrepareAssets` set that runs in parallel with other systems and
sets in the render schedule.
- Put prepare_assets systems in the `PrepareAssets` set
- If explicit dependencies are needed on Mesh or Material RenderAssets
then depend on the appropriate system.
- Add `ManageViews` and `ManageViewsFlush` sets between
`ExtractCommands` and Queue
- Move `queue_mesh*_bind_group` to the Prepare stage
- Rename them to `prepare_`
- Put systems that prepare resources (buffers, textures, etc.) into a
`PrepareResources` set inside `Prepare`
- Put the `prepare_..._bind_group` systems into a `PrepareBindGroup` set
after `PrepareResources`
- Move `prepare_lights` to the `ManageViews` set
- `prepare_lights` creates views and this must happen before `Queue`
- This system needs refactoring to stop handling all responsibilities
- Gather lights, sort, and create shadow map views. Store sorted light
entities in a resource
- Remove `BatchedPhaseItem`
- Replace `batch_range` with `batch_size` representing how many items to
skip after rendering the item or to skip the item entirely if
`batch_size` is 0.
- `queue_sprites` has been split into `queue_sprites` for queueing phase
items and `prepare_sprites` for batching after the `PhaseSort`
- `PhaseItem`s are still inserted in `queue_sprites`
- After sorting adjacent compatible sprite phase items are accumulated
into `SpriteBatch` components on the first entity of each batch,
containing a range of vertex indices. The associated `PhaseItem`'s
`batch_size` is updated appropriately.
- `SpriteBatch` items are then drawn skipping over the other items in
the batch based on the value in `batch_size`
- A very similar refactor was performed on `bevy_ui`
---
## Changelog
Changed:
- Reordered and reworked render app schedule sets. The main change is
that data is extracted, queued, sorted, and then prepared when the order
of data is known.
- Refactor `bevy_sprite` and `bevy_ui` to take advantage of the
reordering.
## Migration Guide
- Assets such as materials and meshes should now be created in
`PrepareAssets` e.g. `prepare_assets<Mesh>`
- Queueing entities to `RenderPhase`s continues to be done in `Queue`
e.g. `queue_sprites`
- Preparing resources (textures, buffers, etc.) should now be done in
`PrepareResources`, e.g. `prepare_prepass_textures`,
`prepare_mesh_uniforms`
- Prepare bind groups should now be done in `PrepareBindGroups` e.g.
`prepare_mesh_bind_group`
- Any batching or instancing can now be done in `Prepare` where the
order of the phase items is known e.g. `prepare_sprites`
## Next Steps
- Introduce some generic mechanism to ensure items that can be batched
are grouped in the phase item order, currently you could easily have
`[sprite at z 0, mesh at z 0, sprite at z 0]` preventing batching.
- Investigate improved orderings for building the MeshUniform buffer
- Implementing batching across the rest of bevy
---------
Co-authored-by: Robert Swain <robert.swain@gmail.com>
Co-authored-by: robtfm <50659922+robtfm@users.noreply.github.com>
2023-08-27 14:33:49 +00:00
|
|
|
batch_size: 1,
|
2023-06-13 06:49:47 +00:00
|
|
|
});
|
2023-03-20 20:57:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|