Procházet zdrojové kódy

Fix uninitialized memory in CPUParticles2D

Calls to set_amount can increase the size of the particle array, but do not zero the memory, they only set the active flag to false. This uninitialized memory can be sent to the GPU, possibly as NaNs.
lawnjelly před 5 roky
rodič
revize
9af4c09d1b
2 změnil soubory, kde provedl 20 přidání a 16 odebrání
  1. 18 16
      scene/2d/cpu_particles_2d.cpp
  2. 2 0
      scene/2d/cpu_particles_2d.h

+ 18 - 16
scene/2d/cpu_particles_2d.cpp

@@ -53,9 +53,11 @@ void CPUParticles2D::set_amount(int p_amount) {
 	{
 		PoolVector<Particle>::Write w = particles.write();
 
-		for (int i = 0; i < p_amount; i++) {
-			w[i].active = false;
-		}
+		// each particle must be set to false
+		// zeroing the data also prevents uninitialized memory being sent to GPU
+		zeromem(static_cast<void *>(&w[0]), p_amount * sizeof(Particle));
+		// cast to prevent compiler warning .. note this relies on Particle not containing any complex types.
+		// an alternative is to use some zero method per item but the generated code will be far less efficient.
 	}
 
 	particle_data.resize((8 + 4 + 1) * p_amount);
@@ -1020,22 +1022,22 @@ void CPUParticles2D::_update_particle_data_buffer() {
 				ptr[6] = 0;
 				ptr[7] = t.elements[2][1];
 
+				Color c = r[idx].color;
+				uint8_t *data8 = (uint8_t *)&ptr[8];
+				data8[0] = CLAMP(c.r * 255.0, 0, 255);
+				data8[1] = CLAMP(c.g * 255.0, 0, 255);
+				data8[2] = CLAMP(c.b * 255.0, 0, 255);
+				data8[3] = CLAMP(c.a * 255.0, 0, 255);
+
+				ptr[9] = r[idx].custom[0];
+				ptr[10] = r[idx].custom[1];
+				ptr[11] = r[idx].custom[2];
+				ptr[12] = r[idx].custom[3];
+
 			} else {
-				zeromem(ptr, sizeof(float) * 8);
+				zeromem(ptr, sizeof(float) * 13);
 			}
 
-			Color c = r[idx].color;
-			uint8_t *data8 = (uint8_t *)&ptr[8];
-			data8[0] = CLAMP(c.r * 255.0, 0, 255);
-			data8[1] = CLAMP(c.g * 255.0, 0, 255);
-			data8[2] = CLAMP(c.b * 255.0, 0, 255);
-			data8[3] = CLAMP(c.a * 255.0, 0, 255);
-
-			ptr[9] = r[idx].custom[0];
-			ptr[10] = r[idx].custom[1];
-			ptr[11] = r[idx].custom[2];
-			ptr[12] = r[idx].custom[3];
-
 			ptr += 13;
 		}
 	}

+ 2 - 0
scene/2d/cpu_particles_2d.h

@@ -81,6 +81,8 @@ public:
 private:
 	bool emitting;
 
+	// warning - beware of adding non-trivial types
+	// to this structure as it is zeroed to initialize in set_amount()
 	struct Particle {
 		Transform2D transform;
 		Color color;