Browse Source

mapblock_mesh: Optimize a few things (#9713)

sfan5 4 years ago
parent
commit
73180a73da
1 changed files with 44 additions and 47 deletions
  1. 44 47
      src/client/mapblock_mesh.cpp

+ 44 - 47
src/client/mapblock_mesh.cpp

@@ -225,7 +225,7 @@ static u16 getSmoothLightCombined(const v3s16 &p,
 		return f.light_propagates;
 	};
 
-	std::array<bool, 4> obstructed = {{ 1, 1, 1, 1 }};
+	bool obstructed[4] = { true, true, true, true };
 	add_node(0);
 	bool opaque1 = !add_node(1);
 	bool opaque2 = !add_node(2);
@@ -372,6 +372,32 @@ void final_color_blend(video::SColor *result,
 	Mesh generation helpers
 */
 
+// This table is moved outside getNodeVertexDirs to avoid the compiler using
+// a mutex to initialize this table at runtime right in the hot path.
+// For details search the internet for "cxa_guard_acquire".
+static const v3s16 vertex_dirs_table[] = {
+	// ( 1, 0, 0)
+	v3s16( 1,-1, 1), v3s16( 1,-1,-1),
+	v3s16( 1, 1,-1), v3s16( 1, 1, 1),
+	// ( 0, 1, 0)
+	v3s16( 1, 1,-1), v3s16(-1, 1,-1),
+	v3s16(-1, 1, 1), v3s16( 1, 1, 1),
+	// ( 0, 0, 1)
+	v3s16(-1,-1, 1), v3s16( 1,-1, 1),
+	v3s16( 1, 1, 1), v3s16(-1, 1, 1),
+	// invalid
+	v3s16(), v3s16(), v3s16(), v3s16(),
+	// ( 0, 0,-1)
+	v3s16( 1,-1,-1), v3s16(-1,-1,-1),
+	v3s16(-1, 1,-1), v3s16( 1, 1,-1),
+	// ( 0,-1, 0)
+	v3s16( 1,-1, 1), v3s16(-1,-1, 1),
+	v3s16(-1,-1,-1), v3s16( 1,-1,-1),
+	// (-1, 0, 0)
+	v3s16(-1,-1,-1), v3s16(-1,-1, 1),
+	v3s16(-1, 1, 1), v3s16(-1, 1,-1)
+};
+
 /*
 	vertex_dirs: v3s16[4]
 */
@@ -384,44 +410,16 @@ static void getNodeVertexDirs(const v3s16 &dir, v3s16 *vertex_dirs)
 		2: top-left
 		3: top-right
 	*/
-	if (dir == v3s16(0, 0, 1)) {
-		// If looking towards z+, this is the face that is behind
-		// the center point, facing towards z+.
-		vertex_dirs[0] = v3s16(-1,-1, 1);
-		vertex_dirs[1] = v3s16( 1,-1, 1);
-		vertex_dirs[2] = v3s16( 1, 1, 1);
-		vertex_dirs[3] = v3s16(-1, 1, 1);
-	} else if (dir == v3s16(0, 0, -1)) {
-		// faces towards Z-
-		vertex_dirs[0] = v3s16( 1,-1,-1);
-		vertex_dirs[1] = v3s16(-1,-1,-1);
-		vertex_dirs[2] = v3s16(-1, 1,-1);
-		vertex_dirs[3] = v3s16( 1, 1,-1);
-	} else if (dir == v3s16(1, 0, 0)) {
-		// faces towards X+
-		vertex_dirs[0] = v3s16( 1,-1, 1);
-		vertex_dirs[1] = v3s16( 1,-1,-1);
-		vertex_dirs[2] = v3s16( 1, 1,-1);
-		vertex_dirs[3] = v3s16( 1, 1, 1);
-	} else if (dir == v3s16(-1, 0, 0)) {
-		// faces towards X-
-		vertex_dirs[0] = v3s16(-1,-1,-1);
-		vertex_dirs[1] = v3s16(-1,-1, 1);
-		vertex_dirs[2] = v3s16(-1, 1, 1);
-		vertex_dirs[3] = v3s16(-1, 1,-1);
-	} else if (dir == v3s16(0, 1, 0)) {
-		// faces towards Y+ (assume Z- as "down" in texture)
-		vertex_dirs[0] = v3s16( 1, 1,-1);
-		vertex_dirs[1] = v3s16(-1, 1,-1);
-		vertex_dirs[2] = v3s16(-1, 1, 1);
-		vertex_dirs[3] = v3s16( 1, 1, 1);
-	} else if (dir == v3s16(0, -1, 0)) {
-		// faces towards Y- (assume Z+ as "down" in texture)
-		vertex_dirs[0] = v3s16( 1,-1, 1);
-		vertex_dirs[1] = v3s16(-1,-1, 1);
-		vertex_dirs[2] = v3s16(-1,-1,-1);
-		vertex_dirs[3] = v3s16( 1,-1,-1);
-	}
+
+	// Direction must be (1,0,0), (-1,0,0), (0,1,0), (0,-1,0),
+	// (0,0,1), (0,0,-1)
+	assert(dir.X * dir.X + dir.Y * dir.Y + dir.Z * dir.Z == 1);
+
+	// Convert direction to single integer for table lookup
+	u8 idx = (dir.X + 2 * dir.Y + 3 * dir.Z) & 7;
+	idx = (idx - 1) * 4;
+
+	memcpy(vertex_dirs, &vertex_dirs_table[idx], 4 * sizeof(v3s16));
 }
 
 static void getNodeTextureCoords(v3f base, const v3f &scale, const v3s16 &dir, float *u, float *v)
@@ -892,6 +890,8 @@ static void updateFastFaceRow(
 	u16 lights[4] = {0, 0, 0, 0};
 	u8 waving;
 	TileSpec tile;
+
+	// Get info of first tile
 	getTileInfo(data, p, face_dir,
 			makes_face, p_corrected, face_dir_corrected,
 			lights, waving, tile);
@@ -902,8 +902,6 @@ static void updateFastFaceRow(
 		// If tiling can be done, this is set to false in the next step
 		bool next_is_different = true;
 
-		v3s16 p_next;
-
 		bool next_makes_face = false;
 		v3s16 next_p_corrected;
 		v3s16 next_face_dir_corrected;
@@ -912,9 +910,9 @@ static void updateFastFaceRow(
 		// If at last position, there is nothing to compare to and
 		// the face must be drawn anyway
 		if (j != MAP_BLOCKSIZE - 1) {
-			p_next = p + translate_dir;
+			p += translate_dir;
 
-			getTileInfo(data, p_next, face_dir,
+			getTileInfo(data, p, face_dir,
 					next_makes_face, next_p_corrected,
 					next_face_dir_corrected, next_lights,
 					waving,
@@ -923,7 +921,7 @@ static void updateFastFaceRow(
 			if (next_makes_face == makes_face
 					&& next_p_corrected == p_corrected + translate_dir
 					&& next_face_dir_corrected == face_dir_corrected
-					&& memcmp(next_lights, lights, ARRLEN(lights) * sizeof(u16)) == 0
+					&& memcmp(next_lights, lights, sizeof(lights)) == 0
 					// Don't apply fast faces to waving water.
 					&& (waving != 3 || !waving_liquids)
 					&& next_tile.isTileable(tile)) {
@@ -961,10 +959,9 @@ static void updateFastFaceRow(
 		makes_face = next_makes_face;
 		p_corrected = next_p_corrected;
 		face_dir_corrected = next_face_dir_corrected;
-		std::memcpy(lights, next_lights, ARRLEN(lights) * sizeof(u16));
+		memcpy(lights, next_lights, sizeof(lights));
 		if (next_is_different)
-			tile = next_tile;
-		p = p_next;
+			tile = std::move(next_tile); // faster than copy
 	}
 }