Open 4d49 opened 1 year ago
I'm unsure of the reasonability of doing this scale of changes, this is 32768 nodes, being manipulated in a significant way, and unsure of how reasonable it is to expect it to not cause performance issues, some investigation is required
freeze for 8-9 times
What does this mean?
I'm unsure of the reasonability of doing this scale of changes, this is 32768 nodes, being manipulated in a significant way, and unsure of how reasonable it is to expect it to not cause performance issues, some investigation is required
I understand this and in my project I use a custom class that calls RenderingServer and PhysicsServer directly. I don't use nodes for this, but I ran into a similar issue. Polygon2D is just for example.
What does this mean?
Excuse me. I meant the problem appears after 8-9 times as I call the function to change all Polygon2D. Just press "space" 10 times in the test project.
Nodes aside, you're still manipulating a lot of data in the rendering and physics server, I don't think that's expected to work unless you use instancing, not individual objects manipulated on their own, as you used that type as an example you get no instancing, each has its own set of points
freeze for a while.
Roughly how long? A minute? Ten?
Roughly how long? A minute? Ten?
msec
That's pretty expected to me at least, taking on the order of hundreds of microseconds per polygon here
That's pretty expected to me at least, taking on the order of hundreds of microseconds per polygon here
But why does the problem appear only after a certain number of iterations? Some kind of memory cleanup? And why is there no problem on OpenGl?
But why does the problem appear only after a certain number of iterations?
Unsure, could be memory related, could be some factor in your code triggering only at some points, could be that it is unreliable if the next process frame happens before or after updating the polygons
And why is there no problem on OpenGl?
Probably because either: 1) The feature is not fully supported in some way 2) The Forward+ renderer uses clustering which has some overhead to build data
Does this happen if you use other means to generate these shapes? Like MeshInstance2D
? I suspect Polygon2D
might not be as performant, also creating a polygon like this does some math behind the scenes to decompose it into triangles which might also be a performance consideration
My main question is: Is this representative of any real world usage you are doing? Or is this just a stress test? Because I have a hard time seeing this as something that affects people in normal cases
Looking at your example you should use other means to draw hexagons if they are regular like this, use something like MeshInstance2D
using the same mesh for each instance but separate materials, this is not the way to do this specific case, it takes much more memory and processing
Edit: I don't get any variation in the time, I get a steady around 900 ms each time, with at most 100 ms variation, and I'm using a debug build so likely much faster in release build
So to summarize at least my views and thoughts:
If you are wanting to do this kind of game structure, with a lot of hex tiles, then I'd recommend using either TileMap
or MeshInstance2D
, to do your drawing, I'd say that using just a square with a texture that has transparency is better here than a hex shape directly as it speeds up a lot of rendering, even if you are using just flat colors you can easily use a custom shader that takes a hex texture with white and transparent and just multiplying the color of the texture by the desired color as a shader uniform
This should even be possible to do with a MultimeshInstance2D
which would help with a lot I'd suspect, though I haven't used it much myself so not sure how to do the specifics
TileMap
is pretty much the perfect fit for this case though, it's literally what it is built for, and it supports hex tiles
If on the other hand this is just for performance testing, I'd say that this isn't unexpected, and that this massive updating of data is bound to create slowdowns
I hope this helps either way, and will keep this open for any other perspectives on if this is in fact some bug in the system, there could be a bottleneck in the rendering system making this less performant, but I suspect this isn't unexpected in general
I continued experimenting and found strange behavior. For minimal reproduction project I used below function to create hexagon polygons:
static func create_hexagon(x: int, y: int) -> PackedVector2Array:
const OUTER_RADIUS : float = 8.0
const INNER_RADIUS : float = OUTER_RADIUS * cos(deg_to_rad(30.0))
# Just 2D hexagon.
const HEXAGON : PackedVector2Array = [
Vector2(0.0, OUTER_RADIUS),
Vector2(INNER_RADIUS, OUTER_RADIUS * 0.5),
Vector2(INNER_RADIUS, OUTER_RADIUS * -.5),
Vector2(0.0, -OUTER_RADIUS),
Vector2(-INNER_RADIUS, OUTER_RADIUS * -.5),
Vector2(-INNER_RADIUS, OUTER_RADIUS * 0.5),
]
var position := Vector2(INNER_RADIUS * 2.0 * x, OUTER_RADIUS * 1.5 * y)
if y % 2: # Add offset every second row.
position.x += INNER_RADIUS
return HEXAGON * Transform2D(0.0, -position) # Apply position.
And after several iterations of changing all polygons, I get freeze:
In my project, instead of hexagons, I use the Voronoi diagram, but I ran into the same problem there too. But as soon as I added the 7th vertex to the hexagon:
const HEXAGON : PackedVector2Array = [
Vector2(0.0, OUTER_RADIUS),
Vector2(INNER_RADIUS, OUTER_RADIUS * 0.5),
Vector2(INNER_RADIUS, OUTER_RADIUS * -.5),
Vector2(0.0, -OUTER_RADIUS),
Vector2(-INNER_RADIUS, OUTER_RADIUS * -.5),
Vector2(-INNER_RADIUS, OUTER_RADIUS * 0.5),
Vector2(0.0, OUTER_RADIUS), # Seven vertex...
]
Freeze is gone: 🙈🙈🙈
Does this happen if you use other means to generate these shapes? Like
MeshInstance2D
? I suspectPolygon2D
might not be as performant, also creating a polygon like this does some math behind the scenes to decompose it into triangles which might also be a performance consideration
The problem is not with Polygon2D
. For example, here is a custom class for creating polygons. Inside a class that works with RenderingServer
directly. And there is the same problem.
class PolygonCanvas extends Object:
var _canvas : RID
var _mesh : RID
var _vertices : PackedVector2Array
var _material : Material
func _init(parent: RID) -> void:
_canvas = RenderingServer.canvas_item_create()
RenderingServer.canvas_item_set_parent(_canvas, parent)
_mesh = RenderingServer.mesh_create()
RenderingServer.canvas_item_add_mesh(_canvas, _mesh)
In a custom class to create meshes, I use this code:
func set_vertices(vertices: PackedVector2Array) -> void:
var arrays : Array = []
arrays.resize(RenderingServer.ARRAY_MAX)
arrays[RenderingServer.ARRAY_VERTEX] = vertices
arrays[RenderingServer.ARRAY_TEX_UV] = vertices
arrays[RenderingServer.ARRAY_INDEX] = Geometry2D.triangulate_polygon(vertices)
RenderingServer.mesh_clear(_mesh)
RenderingServer.mesh_add_surface_from_arrays(_mesh, RenderingServer.PRIMITIVE_TRIANGLES, arrays, [], {}, RenderingServer.ARRAY_FLAG_USE_2D_VERTICES)
I used ARRAY_INDEX
. In OpenGL it all works fine. But if change the code like this:
func set_vertices(vertices: PackedVector2Array) -> void:
var indices : PackedInt32Array = Geometry2D.triangulate_polygon(vertices)
var trinagulated := PackedVector2Array()
trinagulated.resize(indices.size())
for i in indices.size():
trinagulated[i] = vertices[indices[i]]
var arrays : Array = []
arrays.resize(RenderingServer.ARRAY_MAX)
arrays[RenderingServer.ARRAY_VERTEX] = trinagulated
arrays[RenderingServer.ARRAY_TEX_UV] = trinagulated
# Removed ARRAY_INDEX.
RenderingServer.mesh_clear(_mesh)
RenderingServer.mesh_add_surface_from_arrays(_mesh, RenderingServer.PRIMITIVE_TRIANGLES, arrays, [], {}, RenderingServer.ARRAY_FLAG_USE_2D_VERTICES)
Freeze is gone... Polygon2D
also uses triangulation for indexing. So I think this is the problem.
This is likely a duplicate of https://github.com/godotengine/godot/issues/74540, although your issue mention that you don't get performance issues when using the Compatibility rendering method (while https://github.com/godotengine/godot/issues/74540 claims that it does impact Compatibility).
This is likely a duplicate of #74540, although your issue mention that you don't get performance issues when using the Compatibility rendering method (while #74540 claims that it does impact Compatibility).
That's right, the problem is only with Vulkan and ONLY if the mesh's vertices are indexed.
The problem also applies to 3D.
Godot version
v4.1.beta3.official [ada712e06]
System information
Godot v4.1.beta3 - Windows 10.0.22621 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 2060 (NVIDIA; 31.0.15.3161) - AMD Ryzen 5 2600X Six-Core Processor (12 Threads)
Issue description
If you create many nodes (256x128) of the Polygon2D class and start changing them, then the engine will freeze for 8-9 times. It doesn't matter if you delete and re-create nodes or just change the polygon.
Steps to reproduce
Creates many nodes (256x128) of the Polygon2D class. Сreate a function that will change the "polygon" and the material of these nodes. At 8-9 times the engine will freeze for a while. I think the problem is somewhere in RenderingServer because if you enable OpenGL then the problem goes away.
Minimal reproduction project
space - update delete - rebuild
freeze-issue.zip