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 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; }