private void GenerateLabelLayout(Profiler.ProfilerData data) { const string labelFormat = "<b><color=#{0:X2}{1:X2}{2:X2}FF>{3}</color></b>\n"; StringBuilder builder = new StringBuilder(labelFormat.Length * data.recorderData.Count); builder.AppendLine("\n"); // To make it match with column headers of the data if (labelIndents != null) { for (int i = 0; i < data.recorderData.Count; i++) { if (data.recorderData[i].layout.visible) { Color32 col = data.recorderData[i].layout.color; builder.AppendFormat(labelFormat, col.r, col.g, col.b, '·' + new String(' ', labelIndents[i] * 3) + data.recorderData[i].label); } } } else { for (int i = 0; i < data.recorderData.Count; i++) { if (data.recorderData[i].layout.visible) { Color32 col = data.recorderData[i].layout.color; builder.AppendFormat(labelFormat, col.r, col.g, col.b, data.recorderData[i].label); } } } labelLayout.text = builder.ToString(); }
void CreateBuffers(Profiler.ProfilerData data) { previousPosition = new float[data.samplingSize]; samplingSize = data.samplingSize; colors = new Color[data.recorderData.Count + 1]; colors[data.recorderData.Count] = Color.red; //Last color is used for the frametime lines shouldRender = new bool[data.recorderData.Count + 1]; shouldRender[data.recorderData.Count] = true; //Always render the runtime labels vertices = new Vector3[2 * data.samplingSize + 2 * data.samplingSize * data.recorderData.Count + 2 * 3]; mesh = new Mesh(); mesh.MarkDynamic(); mesh.subMeshCount = data.recorderData.Count + 1; //+1 for runtime labels mesh.vertices = vertices; int[] indices = new int[6 * data.samplingSize]; for (int i = 1; i <= data.recorderData.Count; i++) { for (int j = 0; j < data.samplingSize; j++) { indices[0 + j * 6] = 0 + (i - 1) * (2 * data.samplingSize) + j * 2; //bottom left indices[1 + j * 6] = 0 + i * (2 * data.samplingSize) + j * 2; //top left indices[2 + j * 6] = 1 + i * (2 * data.samplingSize) + j * 2; //top right indices[3 + j * 6] = 0 + (i - 1) * (2 * data.samplingSize) + j * 2; //bottom left indices[4 + j * 6] = 1 + i * (2 * data.samplingSize) + j * 2; //top right indices[5 + j * 6] = 1 + (i - 1) * (2 * data.samplingSize) + j * 2; //bottom right } mesh.SetIndices(indices, MeshTopology.Triangles, i - 1); } int offset; int cacheSize = data.samplingSize; for (int j = 0; j < cacheSize; j++) { offset = j * 2; //bottom left vertices[0 + offset].x = cacheSize - j - 1; vertices[0 + offset].y = 0; //bottom right vertices[1 + offset].x = cacheSize - j; vertices[1 + offset].y = 0; } }
void ProfilerVisualizer.OnUpdate(Profiler.ProfilerData data) { if (isDirty) { GenerateLabelLayout(data); isDirty = false; } if ((passedTime + updateInterval < Time.realtimeSinceStartup)) { //Reset the builder, but keep the header format string dataBuilder.Length = header.Length; int lastFrameRendered = labelsRendered; labelsRendered = 0; const string dataFormat = "{0,6:F2}\t{1,4:F2}\t{2,6:F2}\n"; for (int i = 0; i < data.recorderData.Count; i++) { if (data.recorderData[i].layout.visible) { Profiler.RecorderData sample = data.recorderData[i]; dataBuilder.AppendFormat(dataFormat, sample.avgTime, sample.avgCount, sample.time); ++labelsRendered; } } if (labelsRendered != lastFrameRendered) //We must redraw the "static" labels if one of them has been hidden since last frame { isDirty = true; } dataLayout.text = dataBuilder.ToString(); fpsLayout.text = String.Format("<b>{0:F2} FPS ({1:F2}ms)</b>", 1.0f / data.m_AvgDeltaTime, data.m_AvgDeltaTime * 1000.0f); passedTime = Time.realtimeSinceStartup; long monoTotal = UnityEngine.Profiling.Profiler.GetMonoHeapSizeLong(); long monoUsed = UnityEngine.Profiling.Profiler.GetMonoUsedSizeLong(); long nativeTotal = UnityEngine.Profiling.Profiler.GetTotalReservedMemoryLong(); long nativeUsed = UnityEngine.Profiling.Profiler.GetTotalAllocatedMemoryLong(); const float toMB = 1f / 1000000f; memoryLabel.text = "Memory(Mono): " + Math.Round(monoUsed * toMB) + "MB / " + Math.Round(monoTotal * toMB) + "MB\nMemory(Native): " + Math.Round(nativeUsed * toMB) + "MB / " + Math.Round(nativeTotal * toMB) + "MB"; } }
void ProfilerVisualizer.OnRecorderChanged(Profiler.ProfilerData data) { GenerateLabelLayout(data); }
void ProfilerVisualizer.OnRecorderChanged(Profiler.ProfilerData data) { // We dont care about this event.. }
void ProfilerVisualizer.OnUpdate(Profiler.ProfilerData data) { if (isDirty) { CreateBuffers(data); isDirty = false; } if (maxFrameTime > 1000) { maxFrameTime = 1000; } Array.Clear(previousPosition, 0, previousPosition.Length); //Zero out int offset; CircularBuffer buffer; int cacheSize; for (int i = 0; i < data.recorderData.Count; ++i) { colors[i] = data.recorderData[i].layout.color; buffer = data.recorderData[i].buffer; cacheSize = buffer.size; if (!data.recorderData[i].layout.visible) { shouldRender[i] = false; Array.Copy(vertices, (i - 1) * (2 * cacheSize) + 2 * cacheSize, vertices, i * (2 * cacheSize) + 2 * cacheSize, 2 * cacheSize); //We use the previous recorders height, which gives us a zero height continue; } shouldRender[i] = true; for (int j = 0; j < cacheSize; j++) { float bufferValue = previousPosition[j] + buffer.get(j); offset = i * (2 * cacheSize) + j * 2 + 2 * cacheSize; //top left vertices[0 + offset].x = cacheSize - j - 1; vertices[0 + offset].y = bufferValue; //top right vertices[1 + offset].x = cacheSize - j; vertices[1 + offset].y = bufferValue; previousPosition[j] = bufferValue; } } //Last max frame expired, recalculate it if (--maxFrameLifetime < 0) { maxFrameTime = 0.0001f; for (int i = 0; i < previousPosition.Length; i++) { if (previousPosition[i] > maxFrameTime) { maxFrameTime = previousPosition[i]; maxFrameLifetime = previousPosition.Length - i; } } GenerateGraphLegend(); } else if (previousPosition[0] > maxFrameTime) { maxFrameTime = previousPosition[0]; maxFrameLifetime = previousPosition.Length; GenerateGraphLegend(); } //Update vertices mesh.vertices = vertices; //Update mesh data mesh.UploadMeshData(false); }
void ProfilerVisualizer.OnUpdate(Profiler.ProfilerData data) { currentFPS = 1.0f / data.m_AvgDeltaTime; }
void ProfilerVisualizer.OnRecorderChanged(Profiler.ProfilerData data) { }