Skip to content

Commit b009e38

Browse files
authored
Merge pull request #4 from wotakuro/feature/syncreadback
Feature/syncreadback
2 parents f2db60e + aa54768 commit b009e38

File tree

5 files changed

+133
-24
lines changed

5 files changed

+133
-24
lines changed

Editor/ProfilerScreenShotWindow.cs

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ private struct TagInfo
2020
public int originWidth;
2121
public int originHeight;
2222
}
23-
23+
private enum OutputMode:int
24+
{
25+
Origin = 0,
26+
FitWindow = 1,
27+
}
2428

2529
[MenuItem("Tools/ProfilerScreenshot")]
2630
public static void Create()
@@ -32,10 +36,17 @@ public static void Create()
3236
private Texture originTexture;
3337

3438
private int lastPreviewFrameIdx;
35-
private bool isAutoReflesh = false;
39+
private bool isAutoReflesh = true;
3640
private bool isYFlip = false;
41+
private OutputMode outputMode;
3742

38-
private Vector2Int outputSize = new Vector2Int();
43+
private GUIContent[] outputModeSelect = new GUIContent[2]
44+
{
45+
new GUIContent("Original Size"),
46+
new GUIContent("Fit window Size"),
47+
};
48+
49+
private Vector2Int outputSize = new Vector2Int();
3950

4051
private void OnEnable()
4152
{
@@ -63,6 +74,7 @@ private void Reflesh(int frameIdx,bool force = false)
6374
}
6475
HierarchyFrameDataView hierarchyFrameDataView =
6576
ProfilerDriver.GetHierarchyFrameDataView(frameIdx, 0, HierarchyFrameDataView.ViewModes.Default, 0, false); ;
77+
if(hierarchyFrameDataView == null) { return; }
6678
NativeArray<byte> bytes =
6779
hierarchyFrameDataView.GetFrameMetaData<byte>(ScreenShotToProfiler.MetadataGuid, ScreenShotToProfiler.InfoTag);
6880
if (bytes != null && bytes.Length >= 12)
@@ -140,6 +152,10 @@ private Texture2D GenerateTagTexture(TagInfo info,int idx)
140152
{
141153
HierarchyFrameDataView hierarchyFrameDataView =
142154
ProfilerDriver.GetHierarchyFrameDataView(i, 0, HierarchyFrameDataView.ViewModes.Default, 0, false);
155+
if( hierarchyFrameDataView == null)
156+
{
157+
continue;
158+
}
143159
NativeArray<byte> bytes =
144160
hierarchyFrameDataView.GetFrameMetaData<byte>(ScreenShotToProfiler.MetadataGuid, info.id);
145161

@@ -176,9 +192,11 @@ private void OnGUI()
176192
this.Reflesh(GetProfilerActiveFrame(),true);
177193
}
178194
}
179-
EditorGUILayout.Space();
180-
195+
EditorGUILayout.BeginHorizontal();
181196
this.isYFlip = EditorGUILayout.Toggle("Flip Y", this.isYFlip);
197+
EditorGUILayout.LabelField("Size",GUILayout.Width(40));
198+
outputMode = (OutputMode)EditorGUILayout.Popup((int)outputMode, outputModeSelect);
199+
EditorGUILayout.EndHorizontal();
182200
EditorGUILayout.Space();
183201
//drawTextureInfo.SetFlip(this.isYFlip);
184202

@@ -188,6 +206,11 @@ private void OnGUI()
188206
{
189207
var rect = EditorGUILayout.GetControlRect(GUILayout.Width(outputSize.x),
190208
GUILayout.Height(outputSize.y));
209+
if (outputMode == OutputMode.FitWindow)
210+
{
211+
rect = FitWindow(rect);
212+
}
213+
191214
if (this.isYFlip)
192215
{
193216
rect.y += rect.height;
@@ -196,6 +219,27 @@ private void OnGUI()
196219
EditorGUI.DrawTextureTransparent(rect, drawTexture);
197220
}
198221
}
222+
private Rect FitWindow(Rect r)
223+
{
224+
if( r.width == 0 || r.height == 0) { return r; }
225+
var windowPos = this.position;
226+
float xparam = (position.width - r.x * 2) / r.width;
227+
float yparam = (position.height - (r.y+5) ) / r.height;
228+
229+
if( xparam > yparam)
230+
{
231+
r.width *= yparam;
232+
r.height *= yparam;
233+
}
234+
else
235+
{
236+
r.width *= xparam;
237+
r.height *= xparam;
238+
}
239+
240+
241+
return r;
242+
}
199243

200244
private int GetProfilerActiveFrame()
201245
{

README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ Embed Screenshot to Unity Profiler protocol.<br />
66

77
## requirement
88
- 2019.3 or newer.<br />
9-
- support System.supportsAsyncGPUReadback platform only<br />
10-
(Mobile vulkan or metal....)
9+
10+
## reccomend
11+
- the platforms that supports System.supportsAsyncGPUReadback (Mobile vulkan or metal....)<br />
12+
Support sync readback from 1.1.0 , however it's very slow....
1113

1214
## how to use
1315
1.calling this at Runtime. <br />
@@ -17,6 +19,10 @@ or <br />
1719
UTJ.SS2Profiler.ScreenShotToProfiler.Instance.Initialize(w,h);<br />
1820
( w,h means recording texture size).
1921

20-
2122
2.call "Tools -> ProfilerScreenshot" from Menu. <br />
2223
And then window will be displayed.
24+
25+
26+
## change
27+
<pre>
28+
version 1.1.0 -> add sync readback option for gles.

Runtime/ScreenShotLogic.cs

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ private struct RequestInfo
3131
private byte[] tagInfo;
3232
private CommandBuffer commandBuffer;
3333

34+
private Texture2D syncTexCache;
35+
private CustomSampler syncUpdateSampler;
36+
3437
public ScreenShotLogic(int width , int height)
3538
{
3639
frames = new DataInfo[FRAME_NUM];
@@ -69,7 +72,7 @@ public void Dispose()
6972
frames = null;
7073
}
7174

72-
public void Update()
75+
public void UpdateAsyncRequest()
7376
{
7477
for( int i = 0; i < FRAME_NUM; ++i)
7578
{
@@ -106,7 +109,46 @@ public void Update()
106109
break;
107110
}
108111
}
112+
}
113+
114+
public void ReadBackSyncAtIdx(int idx)
115+
{
116+
if (idx < 0 || idx >= FRAME_NUM)
117+
{
118+
return;
119+
}
120+
var rt = frames[idx].renderTexture;
121+
if( rt == null) { return; }
122+
if(syncUpdateSampler == null)
123+
{
124+
this.syncUpdateSampler = CustomSampler.Create("SyncUpdate");
125+
}
126+
127+
syncUpdateSampler.Begin();
128+
if (syncTexCache != null &&
129+
(syncTexCache.width != rt.width || syncTexCache.height != rt.height) )
130+
{
131+
Object.Destroy(syncTexCache);
132+
syncTexCache = null;
133+
}
109134

135+
Texture2D tex2d = syncTexCache;
136+
if (tex2d == null)
137+
{
138+
tex2d = new Texture2D(rt.width, rt.height, TextureFormat.RGBA32, false);
139+
}
140+
RenderTexture.active = rt;
141+
tex2d.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
142+
tex2d.Apply();
143+
var bytes = tex2d.GetRawTextureData<byte>();
144+
Profiler.EmitFrameMetaData(ScreenShotToProfiler.MetadataGuid,
145+
frames[idx].id, bytes);
146+
147+
syncTexCache = tex2d;
148+
149+
frames[idx].isRequest = false;
150+
frames[idx].fromEnd = 0;
151+
syncUpdateSampler.End();
110152
}
111153

112154
public void AsyncReadbackRequestAtIdx(int idx)
@@ -116,7 +158,6 @@ public void AsyncReadbackRequestAtIdx(int idx)
116158
return;
117159
}
118160
if (!IsAvailable(idx) ) { return; }
119-
120161
// var request = AsyncGPUReadback.RequestIntoNativeArray(ref frames[idx].data, frames[idx].renderTexture, 0);
121162
var request = AsyncGPUReadback.Request(frames[idx].renderTexture);
122163
requests.Enqueue( new RequestInfo { request = request, idx = idx });
@@ -145,10 +186,8 @@ public int CaptureScreen(int id)
145186
continue;
146187
}
147188
frames[i].id = id;
148-
this.WriteToTagInfo(id, 0);
149-
this.WriteToTagInfoShort(Screen.width, 8);
150-
this.WriteToTagInfoShort(Screen.height, 10);
151-
Profiler.EmitFrameMetaData(ScreenShotToProfiler.MetadataGuid, ScreenShotToProfiler.InfoTag, tagInfo);
189+
WriteTagMetaData(id);
190+
152191
var rt = RenderTexture.GetTemporary(Screen.width, Screen.height, 0, RenderTextureFormat.ARGB32);
153192
ScreenCapture.CaptureScreenshotIntoRenderTexture(rt);
154193
commandBuffer.BeginSample(CAPTURE_CMD_SAMPLE);
@@ -161,11 +200,18 @@ public int CaptureScreen(int id)
161200
}
162201
return -1;
163202
}
203+
private void WriteTagMetaData(int id)
204+
{
205+
this.WriteToTagInfo(id, 0);
206+
this.WriteToTagInfoShort(Screen.width, 8);
207+
this.WriteToTagInfoShort(Screen.height, 10);
208+
Profiler.EmitFrameMetaData(ScreenShotToProfiler.MetadataGuid, ScreenShotToProfiler.InfoTag, tagInfo);
164209

165-
210+
}
166211
}
167212

168213

214+
169215
}
170216

171217
#endif

Runtime/ScreenShotToProfiler.cs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,28 @@ public bool Initialize()
3131
{
3232
if (Screen.width > Screen.height)
3333
{
34-
return Initialize(192,128);
34+
return Initialize(192,128,true);
3535
}
3636
else
3737
{
38-
return Initialize(128, 192);
38+
return Initialize(128, 192,true);
3939
}
4040
}
4141

42-
public bool Initialize(int width , int height)
42+
public bool Initialize(int width , int height,bool allowSync = false)
4343
{
44+
#if DEBUG
4445
if (!SystemInfo.supportsAsyncGPUReadback)
4546
{
46-
return false;
47+
if (!allowSync)
48+
{
49+
return false;
50+
}
51+
else
52+
{
53+
UnityEngine.Debug.LogWarning("SystemInfo.supportsAsyncGPUReadback is false! Profiler Screenshot is very slow...");
54+
}
4755
}
48-
#if DEBUG
4956
if (renderTextureBuffer != null) { return false; }
5057
InitializeLogic(width,height);
5158
#endif
@@ -83,8 +90,14 @@ public void Destroy()
8390
private void Update()
8491
{
8592
this.updateSampler.Begin();
86-
renderTextureBuffer.AsyncReadbackRequestAtIdx(lastRequestIdx);
87-
renderTextureBuffer.Update();
93+
if ( SystemInfo.supportsAsyncGPUReadback) {
94+
renderTextureBuffer.AsyncReadbackRequestAtIdx(lastRequestIdx);
95+
renderTextureBuffer.UpdateAsyncRequest();
96+
}
97+
else
98+
{
99+
renderTextureBuffer.ReadBackSyncAtIdx(lastRequestIdx);
100+
}
88101

89102
this.updateSampler.End();
90103
}
@@ -93,7 +106,7 @@ private void Capture()
93106
{
94107
captureSampler.Begin();
95108
lastRequestIdx = renderTextureBuffer.CaptureScreen(frameIdx);
96-
renderTextureBuffer.Update();
109+
renderTextureBuffer.UpdateAsyncRequest();
97110
++frameIdx;
98111
captureSampler.End();
99112
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "com.utj.screenshot2profiler",
33
"displayName": "Screenshot to Profiler",
4-
"version": "1.0.1",
4+
"version": "1.1.0",
55
"unity": "2019.3",
66
"description": "Embedded screenshot to profiler data",
77
"keywords": [

0 commit comments

Comments
 (0)