public PostVSMeshData GetPostVSData(MeshDataStage stage) { IntPtr mem = CustomMarshal.Alloc(typeof(PostVSMeshData)); PostVSMeshData ret = null; bool success = ReplayRenderer_GetPostVSData(m_Real, stage, mem); if (success) { ret = (PostVSMeshData)CustomMarshal.PtrToStructure(mem, typeof(PostVSMeshData), true); } CustomMarshal.Free(mem); return(ret); }
public MeshFormat GetPostVSData(UInt32 instID, MeshDataStage stage) { IntPtr mem = CustomMarshal.Alloc(typeof(MeshFormat)); MeshFormat ret = new MeshFormat(); ret.buf = ResourceId.Null; bool success = ReplayRenderer_GetPostVSData(m_Real, instID, stage, mem); if (success) { ret = (MeshFormat)CustomMarshal.PtrToStructure(mem, typeof(MeshFormat), true); } CustomMarshal.Free(mem); return(ret); }
public void OnEventSelected(UInt32 frameID, UInt32 eventID) { ClearStoredData(); var draw = m_Core.CurDrawcall; byteOffset.Enabled = false; instanceIdxToolitem.Enabled = (draw != null && draw.numInstances > 1); if (!instanceIdxToolitem.Enabled) instanceIdxToolitem.Text = "0"; if (MeshView && draw == null) { m_VSIn.AbortThread(); m_VSOut.AbortThread(); m_GSOut.AbortThread(); return; } int[] horizscroll = new int[] { m_VSIn.m_GridView.HorizontalScrollingOffset, m_VSOut.m_GridView.HorizontalScrollingOffset, m_GSOut.m_GridView.HorizontalScrollingOffset, }; int curReq = m_ReqID; uint byteoffs = ByteOffset; m_Core.Renderer.BeginInvoke((ReplayRenderer r) => { m_VSIn.AbortThread(); m_VSOut.AbortThread(); m_GSOut.AbortThread(); if (curReq != m_ReqID) return; if (MeshView) { MeshDataStage[] stages = new MeshDataStage[] { MeshDataStage.VSIn, MeshDataStage.VSOut, MeshDataStage.GSOut }; FormatElement[] prevPos = new FormatElement[3]; FormatElement[] prevSecond = new FormatElement[3]; for (int i = 0; i < 3; i++) { prevPos[i] = GetPosHighlightFormatElement(stages[i]); prevSecond[i] = GetSecondHighlightFormatElement(stages[i]); } m_VSIn.m_Input = GetCurrentMeshInput(draw, MeshDataStage.VSIn); m_VSOut.m_Input = GetCurrentMeshInput(draw, MeshDataStage.VSOut); m_GSOut.m_Input = GetCurrentMeshInput(draw, MeshDataStage.GSOut); for(int i=0; i < 3; i++) { FormatElement curPos = GetPosHighlightFormatElement(stages[i]); FormatElement curSecond = GetSecondHighlightFormatElement(stages[i]); if (prevPos[i] == null || prevPos[i] != curPos) UI_AutoFetchRenderComponents(stages[i], true); if (prevSecond[i] == null || prevSecond[i] != curSecond) UI_AutoFetchRenderComponents(stages[i], false); } } var contentsVSIn = RT_FetchBufferContents(MeshDataStage.VSIn, r, m_VSIn.m_Input, byteoffs); var contentsVSOut = RT_FetchBufferContents(MeshDataStage.VSOut, r, m_VSOut.m_Input, byteoffs); var contentsGSOut = RT_FetchBufferContents(MeshDataStage.GSOut, r, m_GSOut.m_Input, byteoffs); if (curReq != m_ReqID) return; this.BeginInvoke(new Action(() => { if (curReq != m_ReqID) return; m_VSIn.AbortThread(); m_VSOut.AbortThread(); m_GSOut.AbortThread(); if (m_VSIn.m_Input != null) UI_SetRowsData(MeshDataStage.VSIn, contentsVSIn, horizscroll[0]); if (m_VSOut.m_Input != null) UI_SetRowsData(MeshDataStage.VSOut, contentsVSOut, horizscroll[1]); if (m_GSOut.m_Input != null) UI_SetRowsData(MeshDataStage.GSOut, contentsGSOut, horizscroll[2]); if (MeshView) UI_UpdateMeshRenderComponents(); UI_SetAllColumns(); camGuess_PropChanged(); render.Invalidate(); })); }); }
private void UI_UpdateMeshColumns(MeshDataStage type, FormatElement[] el) { bool active = (type == m_MeshDisplay.type); bool input = (type == MeshDataStage.VSIn); var bufView = GetUIState(type).m_GridView; if (bufView.ColumnCount == 0) return; int colidx = 2; // skip VTX and IDX columns Color defaultCol = bufView.Columns[0].DefaultCellStyle.BackColor; for (int e = 0; e < el.Length; e++) { for (int i = 0; i < el[e].format.compCount; i++) { if (colidx >= bufView.ColumnCount) return; DataGridViewColumn col = bufView.Columns[colidx]; colidx++; if (e == m_PosElement[(int)type] && active) { if (i != 3 || !input) col.DefaultCellStyle.BackColor = Color.SkyBlue; else col.DefaultCellStyle.BackColor = Color.LightCyan; } else if (e == m_SecondElement[(int)type] && active && m_MeshDisplay.solidShadeMode == SolidShadeMode.Secondary) { if ((m_MeshDisplay.secondary.showAlpha && i == 3) || (!m_MeshDisplay.secondary.showAlpha && i != 3)) col.DefaultCellStyle.BackColor = Color.LightGreen; else col.DefaultCellStyle.BackColor = Color.FromArgb(200, 238, 200); } else col.DefaultCellStyle.BackColor = defaultCol; } } }
private void UI_SetMeshColumns(MeshDataStage type, FormatElement[] el) { var bufView = GetUIState(type).m_GridView; bufView.Columns.Clear(); DataGridViewTextBoxColumn Column = new DataGridViewTextBoxColumn(); Column.AutoSizeMode = DataGridViewAutoSizeColumnMode.None; Column.HeaderText = "VTX"; Column.ReadOnly = true; Column.Frozen = true; Column.Width = 50; Column.DividerWidth = 0; Column.SortMode = DataGridViewColumnSortMode.Programmatic; Column.DefaultCellStyle.Padding = new Padding(0, 2, 0, 2); bufView.Columns.Add(Column); Column = new DataGridViewTextBoxColumn(); Column.AutoSizeMode = DataGridViewAutoSizeColumnMode.None; Column.HeaderText = "IDX"; Column.ReadOnly = true; Column.Frozen = true; Column.Width = 50; Column.DividerWidth = 10; Column.SortMode = DataGridViewColumnSortMode.Programmatic; Column.DefaultCellStyle.Padding = new Padding(0, 2, 0, 2); bufView.Columns.Add(Column); for(int e=0; e < el.Length; e++) { for (int i = 0; i < el[e].format.compCount; i++) { DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn(); col.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; col.MinimumWidth = 50; col.HeaderText = el[e].name; col.ReadOnly = true; col.SortMode = DataGridViewColumnSortMode.Programmatic; col.DefaultCellStyle.Padding = new Padding(0, 2, 0, 2); bufView.Columns.Add(col); } if (e < el.Length-1) bufView.Columns[bufView.Columns.Count - 1].DividerWidth = 10; } UI_UpdateMeshColumns(type, el); }
private void UI_SetRowsData(MeshDataStage type, Dataset data, int horizScroll) { var state = GetUIState(type); Input input = state.m_Input; if(data.Buffers == null) return; var bufView = state.m_GridView; bufView.RowCount = 0; state.m_Data = data; { byte[][] d = data.Buffers; state.m_Stream = new Stream[d.Length]; state.m_Reader = new BinaryReader[d.Length]; state.m_MinBounds = null; state.m_MaxBounds = null; var bufferFormats = input.BufferFormats; foreach (var el in bufferFormats) { if (state.m_Stream[el.buffer] == null) { if (d[el.buffer] == null) { state.m_Stream[el.buffer] = new MemoryStream(m_Zeroes); state.m_Reader[el.buffer] = new BinaryReader(state.m_Stream[el.buffer]); } else { state.m_Stream[el.buffer] = new MemoryStream(d[el.buffer]); state.m_Reader[el.buffer] = new BinaryReader(state.m_Stream[el.buffer]); } } } state.m_RawStride = 0; foreach (var el in bufferFormats) state.m_RawStride += el.ByteSize; state.m_Rows = new object[data.IndexCount][]; if (!MeshView) { state.m_RawData = d[0]; this.BeginInvoke(new Action(() => { UI_ShowRows(state, horizScroll); })); } else { state.m_RawData = new byte[state.m_RawStride * data.IndexCount]; UI_FillRawData(state, horizScroll); } } }
private void UI_AutoFetchRenderComponents(MeshDataStage stage, bool pos) { var ui = GetUIState(stage); if (pos) { int posEl = -1; if (ui.m_Input != null && ui.m_Input.BufferFormats != null) { // prioritise system value over general "POSITION" string matching for (int i = 0; i < ui.m_Input.BufferFormats.Length; i++) { FormatElement el = ui.m_Input.BufferFormats[i]; if (el.systemValue == SystemAttribute.Position) { posEl = i; break; } } // look for an exact match for (int i = 0; posEl == -1 && i < ui.m_Input.BufferFormats.Length; i++) { FormatElement el = ui.m_Input.BufferFormats[i]; if (el.name.ToUpperInvariant() == "POSITION" || el.name.ToUpperInvariant() == "POSITION0" || el.name.ToUpperInvariant() == "POS" || el.name.ToUpperInvariant() == "POS0") { posEl = i; break; } } // try anything containing position for (int i = 0; posEl == -1 && i < ui.m_Input.BufferFormats.Length; i++) { FormatElement el = ui.m_Input.BufferFormats[i]; if (el.name.ToUpperInvariant().Contains("POSITION")) { posEl = i; break; } } // OK last resort, just look for 'pos' for (int i = 0; posEl == -1 && i < ui.m_Input.BufferFormats.Length; i++) { FormatElement el = ui.m_Input.BufferFormats[i]; if (el.name.ToUpperInvariant().Contains("POS")) { posEl = i; break; } } // if we still have absolutely nothing, just use the first available element if (posEl == -1 && ui.m_Input.BufferFormats.Length > 0) { posEl = 0; } } m_PosElement[(int)stage] = posEl; } else { int secondEl = -1; if (ui.m_Input != null && ui.m_Input.BufferFormats != null) { // prioritise TEXCOORD over general COLOR for (int i = 0; i < ui.m_Input.BufferFormats.Length; i++) { FormatElement el = ui.m_Input.BufferFormats[i]; if (el.name.ToUpperInvariant() == "TEXCOORD" || el.name.ToUpperInvariant() == "TEXCOORD0" || el.name.ToUpperInvariant() == "TEX" || el.name.ToUpperInvariant() == "TEX0" || el.name.ToUpperInvariant() == "UV" || el.name.ToUpperInvariant() == "UV0") { secondEl = i; break; } } for (int i = 0; secondEl == -1 && i < ui.m_Input.BufferFormats.Length; i++) { FormatElement el = ui.m_Input.BufferFormats[i]; if (el.name.ToUpperInvariant() == "COLOR" || el.name.ToUpperInvariant() == "COLOR0" || el.name.ToUpperInvariant() == "COL" || el.name.ToUpperInvariant() == "COL0") { secondEl = i; break; } } } m_SecondElement[(int)stage] = secondEl; } }
private void UI_SetColumns(MeshDataStage type, FormatElement[] el) { if (MeshView) UI_SetMeshColumns(type, el); else UI_SetRawColumns(el); }
private static extern bool ReplayRenderer_GetPostVSData(IntPtr real, MeshDataStage stage, IntPtr outdata);
public MeshFormat GetPostVSData(UInt32 instID, MeshDataStage stage) { IntPtr mem = CustomMarshal.Alloc(typeof(MeshFormat)); MeshFormat ret = new MeshFormat(); ret.buf = ResourceId.Null; bool success = ReplayRenderer_GetPostVSData(m_Real, instID, stage, mem); if (success) ret = (MeshFormat)CustomMarshal.PtrToStructure(mem, typeof(MeshFormat), true); CustomMarshal.Free(mem); return ret; }
// used for the mesh view, to get the format of the mesh input from whichever stage that // we're looking at private Input GetCurrentMeshInput(FetchDrawcall draw, MeshDataStage type) { if (!MeshView) return null; Input ret = new Input(); ret.Drawcall = draw; ret.Topology = draw.topology; ResourceId ibuffer = ResourceId.Null; ulong ioffset = 0; m_Core.CurPipelineState.GetIBuffer(out ibuffer, out ioffset); if (draw != null && (draw.flags & DrawcallFlags.UseIBuffer) == 0) { ibuffer = ResourceId.Null; ioffset = 0; } ret.IndexBuffer = ibuffer; ret.IndexOffset = ioffset; ret.IndexRestart = m_Core.CurPipelineState.IsStripRestartEnabled(); ret.IndexRestartValue = m_Core.CurPipelineState.GetStripRestartIndex(draw != null ? draw.indexByteWidth : 0); if (type != MeshDataStage.VSIn) { ShaderReflection details = null; if (type == MeshDataStage.VSOut) details = m_Core.CurPipelineState.GetShaderReflection(ShaderStageType.Vertex); else if (type == MeshDataStage.GSOut) { details = m_Core.CurPipelineState.GetShaderReflection(ShaderStageType.Geometry); if (details == null) details = m_Core.CurPipelineState.GetShaderReflection(ShaderStageType.Domain); } if (details == null) return null; List<FormatElement> f = new List<FormatElement>(); int posidx = -1; for (int i = 0; i < details.OutputSig.Length; i++) { var sig = details.OutputSig[i]; f.Add(new FormatElement()); f[i].buffer = 0; f[i].name = details.OutputSig[i].varName.Length > 0 ? details.OutputSig[i].varName : details.OutputSig[i].semanticIdxName; f[i].format.compByteWidth = sizeof(float); f[i].format.compCount = sig.compCount; f[i].format.compType = sig.compType; f[i].format.special = false; f[i].format.rawType = 0; f[i].perinstance = false; f[i].instancerate = 1; f[i].rowmajor = false; f[i].matrixdim = 1; f[i].systemValue = sig.systemValue; if(f[i].systemValue == SystemAttribute.Position) posidx = i; } // shift position attribute up to first, keeping order otherwise // the same if (posidx > 0) { FormatElement pos = f[posidx]; f.RemoveAt(posidx); f.Insert(0, pos); } uint offset = 0; for (int i = 0; i < details.OutputSig.Length; i++) { uint numComps = f[i].format.compCount; uint elemSize = f[i].format.compType == FormatComponentType.Double ? 8U : 4U; if (m_Core.CurPipelineState.HasAlignedPostVSData) { if (numComps == 2) offset = offset.AlignUp(2U * elemSize); else if (numComps > 2) offset = offset.AlignUp(4U * elemSize); } f[i].offset = offset; offset += numComps * elemSize; } ret.BufferFormats = f.ToArray(); ret.Strides = new uint[] { offset }; ret.Offsets = new ulong[] { 0 }; ret.Buffers = null; return ret; } BoundVBuffer[] vbs = m_Core.CurPipelineState.GetVBuffers(); ResourceId[] bs = new ResourceId[vbs.Length]; uint[] s = new uint[vbs.Length]; ulong[] o = new ulong[vbs.Length]; for (int i = 0; i < vbs.Length; i++) { bs[i] = vbs[i].Buffer; s[i] = vbs[i].ByteStride; o[i] = vbs[i].ByteOffset; } { FormatElement[] f = null; var vinputs = m_Core.CurPipelineState.GetVertexInputs(); f = new FormatElement[vinputs.Length]; ret.GenericValues = new object[vinputs.Length][]; int numinputs = vinputs.Length; int i = 0; foreach (var a in vinputs) { if (!a.Used) { numinputs--; Array.Resize(ref f, numinputs); Array.Resize(ref ret.GenericValues, numinputs); continue; } f[i] = new FormatElement(a.Name, a.VertexBuffer, a.RelativeByteOffset, a.PerInstance, a.InstanceRate, false, // row major matrix 1, // matrix dimension a.Format, false); ret.GenericValues[i] = a.GenericValue; i++; } ret.BufferFormats = f; ret.Strides = s; ret.Offsets = o; ret.Buffers = bs; } return ret; }
private FormatElement GetSecondHighlightFormatElement(MeshDataStage stage) { var ui = GetUIState(stage); int idx = m_SecondElement[(int)stage]; if (ui.m_Input == null || ui.m_Input.BufferFormats == null || idx == -1 || idx >= ui.m_Input.BufferFormats.Length) return null; return ui.m_Input.BufferFormats[idx]; }
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; }
// used for the mesh view, to get the format of the mesh input from whichever stage that // we're looking at private Input GetCurrentMeshInput(FetchDrawcall draw, MeshDataStage type) { if (!MeshView) return null; FormatElement[] f = null; Input ret = new Input(); ret.Drawcall = draw; ret.Topology = m_Core.CurPipelineState.DrawTopology; if (type != MeshDataStage.VSIn) { ShaderReflection details = null; if (type == MeshDataStage.VSOut) details = m_Core.CurPipelineState.GetShaderReflection(ShaderStageType.Vertex); else if (type == MeshDataStage.GSOut) { details = m_Core.CurPipelineState.GetShaderReflection(ShaderStageType.Geometry); if (details == null) details = m_Core.CurPipelineState.GetShaderReflection(ShaderStageType.Domain); } if (details == null) return null; f = new FormatElement[details.OutputSig.Length]; uint offset = 0; for (int i = 0; i < details.OutputSig.Length; i++) { var sig = details.OutputSig[i]; f[i] = new FormatElement(); f[i].buffer = 0; f[i].name = details.OutputSig[i].varName != "" ? details.OutputSig[i].varName : details.OutputSig[i].semanticIdxName; f[i].format.compByteWidth = sizeof(float); f[i].format.compCount = sig.compCount; f[i].format.compType = sig.compType; f[i].format.special = false; f[i].format.rawType = 0; f[i].offset = offset; f[i].perinstance = false; f[i].rowmajor = false; f[i].matrixdim = 1; offset += details.OutputSig[i].compCount * sizeof(float); } ret.BufferFormats = f; ret.Strides = new uint[] { offset }; ret.Offsets = new uint[] { 0 }; ret.Buffers = null; ret.IndexBuffer = ResourceId.Null; return ret; } CommonPipelineState.VBuffer[] vbs = m_Core.CurPipelineState.GetVBuffers(); ResourceId[] bs = new ResourceId[vbs.Length]; uint[] s = new uint[vbs.Length]; uint[] o = new uint[vbs.Length]; for (int i = 0; i < vbs.Length; i++) { bs[i] = vbs[i].Buffer; s[i] = vbs[i].ByteStride; o[i] = vbs[i].ByteOffset; } { var vinputs = m_Core.CurPipelineState.GetVertexInputs(); f = new FormatElement[vinputs.Length]; int i = 0; foreach (var a in vinputs) { f[i] = new FormatElement(a.Name, a.VertexBuffer, a.RelativeByteOffset, a.PerInstance, false, // row major matrix 1, // matrix dimension a.Format); i++; } } ResourceId ibuffer = ResourceId.Null; uint ioffset = 0; ResourceFormat ifmt = null; m_Core.CurPipelineState.GetIBuffer(out ibuffer, out ioffset, out ifmt); if (draw != null && (draw.flags & DrawcallFlags.UseIBuffer) == 0) { ibuffer = ResourceId.Null; ioffset = 0; } ret.BufferFormats = f; ret.Strides = s; ret.Offsets = o; ret.Buffers = bs; ret.IndexFormat = new FormatElement("", 0, 0, false, false, 1, ifmt); ret.IndexBuffer = ibuffer; ret.IndexOffset = ioffset; return ret; }
private void UI_AutoFetchRenderComponents(MeshDataStage stage, bool pos) { var ui = GetUIState(stage); if (pos) { int posEl = -1; if (ui.m_Input != null && ui.m_Input.BufferFormats != null) { // prioritise system value over general "POSITION" string matching for (int i = 0; i < ui.m_Input.BufferFormats.Length; i++) { FormatElement el = ui.m_Input.BufferFormats[i]; if (el.systemValue == SystemAttribute.Position) { posEl = i; break; } } for (int i = 0; posEl == -1 && i < ui.m_Input.BufferFormats.Length; i++) { FormatElement el = ui.m_Input.BufferFormats[i]; if (el.name.ToUpperInvariant() == "POSITION" || el.name.ToUpperInvariant() == "POSITION0" || el.name.ToUpperInvariant() == "POS" || el.name.ToUpperInvariant() == "POS0") { posEl = i; break; } } } m_PosElement[(int)stage] = posEl; } else { int secondEl = -1; if (ui.m_Input != null && ui.m_Input.BufferFormats != null) { // prioritise TEXCOORD over general COLOR for (int i = 0; i < ui.m_Input.BufferFormats.Length; i++) { FormatElement el = ui.m_Input.BufferFormats[i]; if (el.name.ToUpperInvariant() == "TEXCOORD" || el.name.ToUpperInvariant() == "TEXCOORD0" || el.name.ToUpperInvariant() == "TEX" || el.name.ToUpperInvariant() == "TEX0" || el.name.ToUpperInvariant() == "UV" || el.name.ToUpperInvariant() == "UV0") { secondEl = i; break; } } for (int i = 0; secondEl == -1 && i < ui.m_Input.BufferFormats.Length; i++) { FormatElement el = ui.m_Input.BufferFormats[i]; if (el.name.ToUpperInvariant() == "COLOR" || el.name.ToUpperInvariant() == "COLOR0" || el.name.ToUpperInvariant() == "COL" || el.name.ToUpperInvariant() == "COL0") { secondEl = i; break; } } } m_SecondElement[(int)stage] = secondEl; } }
public UIState(MeshDataStage stage) { m_Stage = stage; }
public PostVSMeshData GetPostVSData(MeshDataStage stage) { IntPtr mem = CustomMarshal.Alloc(typeof(PostVSMeshData)); PostVSMeshData ret = null; bool success = ReplayRenderer_GetPostVSData(m_Real, stage, mem); if (success) ret = (PostVSMeshData)CustomMarshal.PtrToStructure(mem, typeof(PostVSMeshData), true); CustomMarshal.Free(mem); return ret; }
private UIState GetUIState(MeshDataStage type) { if (type == MeshDataStage.VSIn) return m_VSIn; if (type == MeshDataStage.VSOut) return m_VSOut; if (type == MeshDataStage.GSOut) return m_GSOut; return null; }
private static extern bool ReplayRenderer_GetPostVSData(IntPtr real, UInt32 instID, MeshDataStage stage, IntPtr outdata);
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 UI_SetRowsData(MeshDataStage type, Dataset data, int horizScroll) { var state = GetUIState(type); var bufView = state.m_GridView; if(bufView.IsDisposed) return; // only do this once, VSIn is guaranteed to be set (even if it's empty data) if(type == MeshDataStage.VSIn) CalcCellFloatWidth(); Input input = state.m_Input; if(data.Buffers == null) return; bufView.RowCount = 0; state.m_Data = data; { byte[][] d = data.Buffers; state.m_Stream = new Stream[d.Length]; state.m_Reader = new BinaryReader[d.Length]; state.m_MinBounds = null; state.m_MaxBounds = null; var bufferFormats = input.BufferFormats; foreach (var el in bufferFormats) { if (el.buffer < state.m_Stream.Length && state.m_Stream[el.buffer] == null) { if (d[el.buffer] == null) { state.m_Stream[el.buffer] = new MemoryStream(m_Zeroes); state.m_Reader[el.buffer] = new BinaryReader(state.m_Stream[el.buffer]); } else { state.m_Stream[el.buffer] = new MemoryStream(d[el.buffer]); state.m_Reader[el.buffer] = new BinaryReader(state.m_Stream[el.buffer]); } } } state.m_RawStride = 0; foreach (var el in bufferFormats) state.m_RawStride += el.ByteSize; state.m_Rows = new object[data.IndexCount][]; if (!MeshView) { state.m_RawData = d[0]; this.BeginInvoke(new Action(() => { UI_ShowRows(state, horizScroll); })); } else { state.m_RawData = new byte[state.m_RawStride * data.IndexCount]; UI_FillRawData(state, horizScroll); } } }