Skip to content

Conversation

@stuartcarnie
Copy link
Contributor

@stuartcarnie stuartcarnie commented Mar 24, 2025

Summary

This PR updates the 2D canvas renderer to utilise dynamic buffers for instance data, per the changes in 7861cdd.

I modified the Canvas 2D renderer to use dynamic buffers for the InstanceData (similar to what @darksylinc did for forward / mobile renderers). This change removes two copies, so the instance data is written once (on UMA devices):

  • one to upload the InstanceData to the GPU, and
  • a second to BLIT the instance data from the staging to the private GPU storage buffers.

I modified the 1x1 sprite benchmark in @Calinou's comment, to draw 20,000 textured rectangles, which still batches, but reduces the CPU bottleneck of rendering 20,000 individual canvas items, to demonstrate the advantages of this PR. TileMaps is an example that will benefit from these changes.

Modified code
extends Node2D

const ITERATIONS = 20_000

@onready var spr: Sprite2D = $Sprite2D as Sprite2D

var draw_instances := false

func _ready() -> void:
	# Use fixed seed for reproducibility.
	seed(0x60d07)

	if draw_instances:
		for i in ITERATIONS:
			var sprite: Sprite2D
			sprite = spr.duplicate() as Sprite2D
			sprite.position.x = randf_range(0, 1152)
			sprite.position.y = randf_range(0, 648)
			add_child(sprite)

func _draw() -> void:
	if !draw_instances:
		var tex: Texture2D = spr.texture
		var pos: Vector2 = Vector2.ZERO
		for i in ITERATIONS:
			pos.x = randf_range(0, 1152)
			pos.y = randf_range(0, 648)
			draw_texture(tex, pos)

About a 10% improvement. The average FPS went from 3161 FPS to 3487 FPS

darksylinc and others added 3 commits March 18, 2025 06:57
This work is a heavily refactored and rewritten from TheForge's initial
code.

TheForge's original code had too many race conditions and was
fundamentally flawed as it was too easy to incur into those data races
by accident.

However they identified the proper places that needed changes, and the
idea was sound. I used their work as a blueprint to design this work.

This PR implements:

 - A refactor of some shaders to avoid using multiple sets.
 - A push constant emulator.
- Introduction of UMA buffers used by push constants and a few buffers
(most notably the ones filled by _fill_instance_data).
@stuartcarnie
Copy link
Contributor Author

Merged into #111183

@stuartcarnie stuartcarnie deleted the 2d-uma branch October 19, 2025 00:36
@AThousandShips AThousandShips removed this from the 4.x milestone Oct 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants