UI batching Fix (#9610)

# Objective

Reimplement #8793 on top of the recent rendering changes.

## Solution

The batch creation logic is quite convoluted, but I tested it on enough
examples to convince myself that it works.

The initial value of `batch_image_handle` is changed from
`HandleId::Id(Uuid::nil(), u64::MAX)` to `DEFAULT_IMAGE_HANDLE.id()`,
which allowed me to make the if-block simpler I think.

The default image from `DEFAULT_IMAGE_HANDLE` is always inserted into
`UiImageBindGroups` even if it's not used. I tried to add a check so
that it would be only inserted when there is only one batch using the
default image but this crashed.

---

## Changelog
`prepare_uinodes`
* Changed the initial value of `batch_image_handle` to
`DEFAULT_IMAGE_HANDLE.id()`.
* The default image is added to the UI image bind groups before
assembling the batches.
* A new `UiBatch` isn't created when the next `ExtractedUiNode`s image
is set to `DEFAULT_IMAGE_HANDLE` (unless it is the first item in the UI
phase items list).
This commit is contained in:
ickshonpe 2023-11-03 01:14:43 +00:00 committed by GitHub
parent 5cc3352f5b
commit d70b4a3170
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -732,6 +732,7 @@ pub fn queue_uinodes(
transparent_phase
.items
.reserve(extracted_uinodes.uinodes.len());
for (entity, extracted_uinode) in extracted_uinodes.uinodes.iter() {
transparent_phase.add(TransparentUi {
draw_function,
@ -781,11 +782,6 @@ pub fn prepare_uinodes(
};
}
#[inline]
fn is_textured(image: AssetId<Image>) -> bool {
image != AssetId::default()
}
if let Some(view_binding) = view_uniforms.uniforms.binding() {
let mut batches: Vec<(Entity, UiBatch)> = Vec::with_capacity(*previous_len);
@ -798,7 +794,6 @@ pub fn prepare_uinodes(
// Vertex buffer index
let mut index = 0;
for mut ui_phase in &mut phases {
let mut batch_item_index = 0;
let mut batch_image_handle = AssetId::invalid();
@ -806,11 +801,14 @@ pub fn prepare_uinodes(
for item_index in 0..ui_phase.items.len() {
let item = &mut ui_phase.items[item_index];
if let Some(extracted_uinode) = extracted_uinodes.uinodes.get(&item.entity) {
let mut existing_batch = batches
.last_mut()
.filter(|_| batch_image_handle == extracted_uinode.image);
let mut existing_batch = batches.last_mut();
if existing_batch.is_none() {
if batch_image_handle == AssetId::invalid()
|| existing_batch.is_none()
|| (batch_image_handle != AssetId::default()
&& extracted_uinode.image != AssetId::default()
&& batch_image_handle != extracted_uinode.image)
{
if let Some(gpu_image) = gpu_images.get(extracted_uinode.image) {
batch_item_index = item_index;
batch_image_handle = extracted_uinode.image;
@ -840,9 +838,32 @@ pub fn prepare_uinodes(
} else {
continue;
}
} else if batch_image_handle == AssetId::default()
&& extracted_uinode.image != AssetId::default()
{
if let Some(gpu_image) = gpu_images.get(extracted_uinode.image) {
batch_image_handle = extracted_uinode.image;
existing_batch.as_mut().unwrap().1.image = extracted_uinode.image;
image_bind_groups
.values
.entry(batch_image_handle)
.or_insert_with(|| {
render_device.create_bind_group(
"ui_material_bind_group",
&ui_pipeline.image_layout,
&BindGroupEntries::sequential((
&gpu_image.texture_view,
&gpu_image.sampler,
)),
)
});
} else {
continue;
}
}
let mode = if is_textured(extracted_uinode.image) {
let mode = if extracted_uinode.image != AssetId::default() {
TEXTURED_QUAD
} else {
UNTEXTURED_QUAD