private void RT_UpdateVisualRange(ReplayRenderer r) { if (!m_Visualise || CurrentTexture == null) return; ResourceFormat fmt = CurrentTexture.format; bool success = true; uint[] histogram; success = r.GetHistogram(m_TexDisplay.texid, m_TexDisplay.sliceFace, m_TexDisplay.mip, m_TexDisplay.sampleIdx, m_TexDisplay.typeHint, rangeHistogram.RangeMin, rangeHistogram.RangeMax, m_TexDisplay.Red, m_TexDisplay.Green && fmt.compCount > 1, m_TexDisplay.Blue && fmt.compCount > 2, m_TexDisplay.Alpha && fmt.compCount > 3, out histogram); if (success) { this.BeginInvoke(new Action(() => { rangeHistogram.SetHistogramRange(rangeHistogram.RangeMin, rangeHistogram.RangeMax); rangeHistogram.HistogramData = histogram; })); } }
//////////////////////////////////////////// // Internals private void CreateReplayRenderer(ref ReplayRenderer renderer, ref RemoteRenderer remote) { if (m_ProxyRenderer < 0) { renderer = StaticExports.CreateReplayRenderer(m_Logfile, ref LoadProgress); return; } remote = StaticExports.CreateRemoteReplayConnection(m_ReplayHost, 0); if(remote == null) { var e = new System.ApplicationException("Failed to connect to remote replay host"); e.Data.Add("status", ReplayCreateStatus.UnknownError); throw e; } renderer = remote.CreateProxyRenderer(m_ProxyRenderer, m_Logfile, ref LoadProgress); if(renderer == null) { remote.Shutdown(); var e = new System.ApplicationException("Failed to connect to remote replay host"); e.Data.Add("status", ReplayCreateStatus.UnknownError); throw e; } }
private void DestroyReplayRenderer(ReplayRenderer renderer) { if (m_Remote != null) m_Remote.CloseCapture(renderer); else renderer.Shutdown(); }
private void RT_UpdateAndDisplay(ReplayRenderer r) { if (m_Output == null) return; m_Output.SetTextureDisplay(m_TexDisplay); render.Invalidate(); }
private Dataset RT_FetchBufferContents(MeshDataStage type, ReplayRenderer r, Input input, uint byteoffs) { Dataset ret = new Dataset(); ret.IndexCount = 0; if (input == null) return ret; if (!MeshView) { if (input != null && (input.Buffers[0] != ResourceId.Null || input.Buffers[1] != ResourceId.Null)) { ret.Buffers = new byte[1][]; if(input.Buffers[0] != ResourceId.Null) ret.Buffers[0] = r.GetBufferData(input.Buffers[0], byteoffs, 0); else if (input.Buffers[1] != ResourceId.Null) ret.Buffers[0] = r.GetTextureData(input.Buffers[1], byteoffs, 0); ret.Indices = null; ret.DataIndices = null; ret.IndexCount = (uint)ret.Buffers[0].Length / input.Strides[0]; } return ret; } if (input.Drawcall == null) return ret; ret.IndexCount = input.Drawcall.numIndices; ret.Topology = input.Topology; ret.PostVS.stride = 0; if (type != MeshDataStage.VSIn) { ret.PostVS = r.GetPostVSData(Math.Min(m_MeshDisplay.curInstance, Math.Max(1U, input.Drawcall.numInstances)), type); ret.Buffers = new byte[1][]; if (ret.PostVS.buf == ResourceId.Null) { ret.IndexCount = 0; ret.Topology = PrimitiveTopology.Unknown; } else { ret.Topology = ret.PostVS.topo; ret.IndexCount = ret.PostVS.numVerts; } ret.Indices = null; ret.DataIndices = null; uint maxIndex = Math.Max(ret.IndexCount, 1) - 1; if (ret.PostVS.buf != ResourceId.Null && type == MeshDataStage.VSOut && (input.Drawcall.flags & DrawcallFlags.UseIBuffer) > 0 && input.IndexBuffer != ResourceId.Null) { ret.IndexCount = input.Drawcall.numIndices; byte[] rawidxs = r.GetBufferData(input.IndexBuffer, input.IndexOffset + input.Drawcall.indexOffset * input.Drawcall.indexByteWidth, ret.IndexCount * input.Drawcall.indexByteWidth); if (input.Drawcall.indexByteWidth == 0 || rawidxs == null || rawidxs.Length == 0) { ret.Indices = new uint[0] { }; } else { ret.Indices = new uint[rawidxs.Length / input.Drawcall.indexByteWidth]; if (input.Drawcall.indexByteWidth == 1) { for (int i = 0; i < rawidxs.Length; i++) ret.Indices[i] = rawidxs[i]; } else if (input.Drawcall.indexByteWidth == 2) { ushort[] tmp = new ushort[rawidxs.Length / 2]; Buffer.BlockCopy(rawidxs, 0, tmp, 0, tmp.Length * sizeof(ushort)); for (int i = 0; i < tmp.Length; i++) { ret.Indices[i] = tmp[i]; } } else if (input.Drawcall.indexByteWidth == 4) { Buffer.BlockCopy(rawidxs, 0, ret.Indices, 0, ret.Indices.Length * sizeof(uint)); } } rawidxs = r.GetBufferData(ret.PostVS.idxbuf, 0, 0); if (input.Drawcall.indexByteWidth == 0 || rawidxs == null || rawidxs.Length == 0) { ret.DataIndices = new uint[0] { }; } else { ret.DataIndices = new uint[rawidxs.Length / input.Drawcall.indexByteWidth]; if (input.Drawcall.indexByteWidth == 1) { for (int i = 0; i < rawidxs.Length; i++) ret.DataIndices[i] = rawidxs[i]; } else if (input.Drawcall.indexByteWidth == 2) { ushort[] tmp = new ushort[rawidxs.Length / 2]; Buffer.BlockCopy(rawidxs, 0, tmp, 0, tmp.Length * sizeof(ushort)); for (int i = 0; i < tmp.Length; i++) { ret.DataIndices[i] = tmp[i]; } } else if (input.Drawcall.indexByteWidth == 4) { Buffer.BlockCopy(rawidxs, 0, ret.DataIndices, 0, ret.DataIndices.Length * sizeof(uint)); } } maxIndex = 0; foreach (var i in ret.DataIndices) { if (i == input.IndexRestartValue && input.IndexRestart) continue; maxIndex = Math.Max(maxIndex, i); } } if (ret.PostVS.buf != ResourceId.Null) { ret.Buffers[0] = r.GetBufferData(ret.PostVS.buf, ret.PostVS.offset, (maxIndex + 1) * ret.PostVS.stride); uint stride = ret.PostVS.stride; if (stride != 0 && (input.Drawcall.flags & DrawcallFlags.UseIBuffer) == 0) ret.IndexCount = Math.Min(ret.IndexCount, (uint)ret.Buffers[0].Length / stride); } return ret; } else if (input.Buffers != null && m_Output != null) { uint maxIndex = Math.Max(ret.IndexCount, 1) - 1; uint maxInstIndex = Math.Max(input.Drawcall.numInstances, 1) - 1; if ((input.Drawcall.flags & DrawcallFlags.UseIBuffer) != 0 && input.IndexBuffer != ResourceId.Null) { byte[] rawidxs = r.GetBufferData(input.IndexBuffer, input.IndexOffset + input.Drawcall.indexOffset * input.Drawcall.indexByteWidth, ret.IndexCount * input.Drawcall.indexByteWidth); if (input.Drawcall.indexByteWidth == 0 || rawidxs == null || rawidxs.Length == 0) { ret.Indices = new uint[0]; } else { ret.Indices = new uint[rawidxs.Length / input.Drawcall.indexByteWidth]; if (input.Drawcall.indexByteWidth == 1) { for (int i = 0; i < rawidxs.Length; i++) ret.Indices[i] = rawidxs[i]; } else if (input.Drawcall.indexByteWidth == 2) { ushort[] tmp = new ushort[rawidxs.Length / 2]; Buffer.BlockCopy(rawidxs, 0, tmp, 0, tmp.Length * sizeof(ushort)); for (int i = 0; i < tmp.Length; i++) { ret.Indices[i] = tmp[i]; } } else if (input.Drawcall.indexByteWidth == 4) { Buffer.BlockCopy(rawidxs, 0, ret.Indices, 0, ret.Indices.Length * sizeof(uint)); } } maxIndex = 0; foreach (var i in ret.Indices) { if (i == input.IndexRestartValue && input.IndexRestart) continue; maxIndex = Math.Max(maxIndex, i); } } ret.DataIndices = ret.Indices; ret.Buffers = new byte[input.Buffers.Length][]; for (int i = 0; i < input.Buffers.Length; i++) { bool used = false; bool pi = false; bool pv = false; foreach (var f in input.BufferFormats) { if (f.buffer == i) { if (f.perinstance) pi = true; else pv = true; used = true; } } uint maxIdx = 0; uint offset = 0; if(used) { if (pi) { maxIdx = maxInstIndex; offset = input.Drawcall.instanceOffset; } if (pv) { maxIdx = Math.Max(maxIndex, maxIdx); offset = input.Drawcall.vertexOffset; } System.Diagnostics.Debug.Assert(pi != pv || (pi == false && pv == false)); } if (!used || input.Buffers[i] == ResourceId.Null) { ret.Buffers[i] = null; } else { ret.Buffers[i] = r.GetBufferData(input.Buffers[i], input.Offsets[i] + offset * input.Strides[i], (maxIdx + 1) * input.Strides[i]); if (ret.Buffers[i].Length < (maxIdx + 1) * input.Strides[i]) { // clamped } } } return ret; } return ret; }
private void RT_UpdateRenderOutput(ReplayRenderer r) { if (m_Output == null) return; m_MeshDisplay.cam = m_CurrentCamera.Camera.Real; m_Output.SetMeshDisplay(m_MeshDisplay); }
private void RT_UpdateRenderOutput(ReplayRenderer r) { if (m_Output == null) return; m_MeshDisplay.arcballCamera = m_Camera.IsArcball; m_MeshDisplay.cameraPos = new FloatVector(m_Camera.PositionParam); m_MeshDisplay.cameraRot = new FloatVector(m_Camera.RotationParam); m_Output.SetMeshDisplay(m_MeshDisplay); }
private Dataset RT_FetchBufferContents(MeshDataStage type, ReplayRenderer r, Input input) { Dataset ret = new Dataset(); ret.IndexCount = 0; if (input == null) return ret; if (!MeshView) { if (input != null && input.Buffers[0] != ResourceId.Null) { ret.Buffers = new byte[1][]; ret.Buffers[0] = r.GetBufferData(input.Buffers[0], 0, 0); ret.Indices = null; ret.IndexCount = (uint)ret.Buffers[0].Length / input.Strides[0]; } return ret; } if (input.Drawcall == null) return ret; ret.IndexCount = input.Drawcall.numIndices; ret.Topology = input.Topology; if (type != MeshDataStage.VSIn) { var postvs = r.GetPostVSData(type); ret.Buffers = new byte[1][]; if (postvs == null) { ret.IndexCount = 0; ret.Topology = PrimitiveTopology.Unknown; } else { ret.Buffers[0] = postvs.buf; ret.Topology = postvs.topo; ret.IndexCount = postvs.numVerts; uint stride = 0; foreach (var f in input.BufferFormats) stride += f.ByteSize; if (stride != 0) ret.IndexCount = Math.Min(ret.IndexCount, (uint)ret.Buffers[0].Length / stride); } ret.Indices = null; return ret; } else if (input.Buffers != null && m_Output != null) { uint maxIndex = Math.Max(ret.IndexCount, 1) - 1; uint maxInstIndex = Math.Max(input.Drawcall.numInstances, 1) - 1; if ((input.Drawcall.flags & DrawcallFlags.UseIBuffer) != 0 && input.IndexBuffer != ResourceId.Null) { byte[] rawidxs = r.GetBufferData(input.IndexBuffer, input.IndexOffset + input.Drawcall.indexOffset * input.IndexFormat.format.compByteWidth, ret.IndexCount * input.IndexFormat.format.compByteWidth); ret.Indices = new uint[rawidxs.Length / input.IndexFormat.format.compByteWidth]; if (input.IndexFormat.format.compByteWidth == 2) { ushort[] tmp = new ushort[rawidxs.Length / 2]; Buffer.BlockCopy(rawidxs, 0, tmp, 0, rawidxs.Length); for (int i = 0; i < tmp.Length; i++) { ret.Indices[i] = tmp[i]; } } else if (input.IndexFormat.format.compByteWidth == 4) { Buffer.BlockCopy(rawidxs, 0, ret.Indices, 0, rawidxs.Length); } maxIndex = 0; foreach (var i in ret.Indices) { if(input.IndexFormat.format.compByteWidth == 2 && i == UInt16.MaxValue) continue; if (input.IndexFormat.format.compByteWidth == 4 && i == UInt32.MaxValue) continue; maxIndex = Math.Max(maxIndex, i); } } ret.Buffers = new byte[input.Buffers.Length][]; for (int i = 0; i < input.Buffers.Length; i++) { bool used = false; bool pi = false; bool pv = false; foreach (var f in input.BufferFormats) { if (f.buffer == i) { if (f.perinstance) pi = true; else pv = true; used = true; } } uint maxIdx = 0; uint offset = 0; if(used) { if (pi) { maxIdx = maxInstIndex; offset = input.Drawcall.instanceOffset; } if (pv) { maxIdx = Math.Max(maxIndex, maxIdx); offset = input.Drawcall.vertexOffset; } System.Diagnostics.Debug.Assert(pi != pv || (pi == false && pv == false)); } if (!used || input.Buffers[i] == ResourceId.Null) { ret.Buffers[i] = null; } else { ret.Buffers[i] = r.GetBufferData(input.Buffers[i], input.Offsets[i] + offset * input.Strides[i], (maxIdx + 1) * input.Strides[i]); if (ret.Buffers[i].Length < (maxIdx + 1) * input.Strides[i]) { // clamped } } } return ret; } return ret; }
public void TimeDrawcalls(ReplayRenderer r) { if (m_TimedDrawcalls) return; m_TimedDrawcalls = true; for (int i = 0; i < m_FrameInfo.Length; i++) m_DrawCalls[i] = FakeProfileMarkers(i, r.GetDrawcalls((UInt32)i, true)); }
private void RT_UpdateVisualRange(ReplayRenderer r) { if (!m_Visualise || CurrentTexture == null || m_Output == null) return; ResourceFormat fmt = CurrentTexture.format; if (m_TexDisplay.CustomShader != ResourceId.Null) fmt.compCount = 4; bool success = true; uint[] histogram; success = m_Output.GetHistogram(rangeHistogram.RangeMin, rangeHistogram.RangeMax, m_TexDisplay.Red, m_TexDisplay.Green && fmt.compCount > 1, m_TexDisplay.Blue && fmt.compCount > 2, m_TexDisplay.Alpha && fmt.compCount > 3, out histogram); if (success) { this.BeginInvoke(new Action(() => { rangeHistogram.SetHistogramRange(rangeHistogram.RangeMin, rangeHistogram.RangeMax); rangeHistogram.HistogramData = histogram; })); } }
public void CloseCapture(ReplayRenderer renderer) { RemoteServer_CloseCapture(m_Real, renderer.Real); }