static void AppendFrameToC(StringBuilder cSrc, StringBuilder cArr, RenderedFrame frame, int minRectSize, int maxRectCount, ref int estBinSize) { /* * format of the rects data is as follows: * - first two bytes are the screen and rectangle colors * - following that are 1..n rectangles: * - 5 bytes per rectangle, with x,y,w,h each with 9 bit and 4 bit flags * - like so: ABCDxxxx xxxxxyyy yyyyyyww wwwwwwwh hhhhhhhh * - flag A indicates that this is the last rectangle, and following it is the start of a new frame * - flags BCD are not used * - end condition: screen and rect color are equal */ // prepare rectangle list: sort by size descending, then filter out all rectangles below the minimum size List <Rectangle> rects = frame.Rectangles .OrderByDescending((r) => r.Width * r.Height) .Where((r) => (r.Width * r.Height) > minRectSize) .Take(maxRectCount) .ToList(); // prepare member name and add pointer to c array string memberName = "rd_" + frame.Comment; cArr.Append(memberName).AppendLine(","); // write start: comment, then screen color (secondary) and rectangle color (primary) cSrc.Append(@$ "/* {frame.Comment} ({rects.Count} rects) */ const u8 {memberName}[] = {{
void Render(DrawEventArgs args) { var device = Renderer.Device; var context = device.ImmediateContext; context.InputAssembler.InputLayout = noteLayout; var target = Renderer.RenderTargetView; notesShader.SetShaders(context); noteConstants.ScreenAspect = (float)(args.RenderSize.Height / args.RenderSize.Width); noteConstants.NoteBorder = 0.0015f; noteConstants.ScreenWidth = (int)args.RenderSize.Width; noteConstants.ScreenHeight = (int)args.RenderSize.Height; SetNoteShaderConstants(context, noteConstants); context.ClearRenderTargetView(target, new Color4(0.4f, 0.4f, 0.4f, 1f)); //context.ClearRenderTargetView(target, new Color4(0.0f, 0.0f, 0.0f, 0f)); double top = ViewTop; double bottom = ViewBottom; double range = top - bottom; lock (noteArrays) { if (ViewBottom < lastBottomCache) { resetStartCache = true; } var viewLeft = ViewLeft; var viewRight = ViewRight; double viewRange = viewRight - viewLeft; Parallel.For(0, 128, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, k => { int pos = 0; float left = (float)((k - viewLeft) / viewRange); float right = (float)(((k + 1) - viewLeft) / viewRange); unsafe { RenderNote *rn = stackalloc RenderNote[noteBufferLength]; void flush() { lock (context) { FlushNoteBuffer( context, left, right, (IntPtr)rn, pos ); pos = 0; } } var notes = noteArrays[k]; int start = 0; if (resetStartCache) { for (; start < notes.Count; start++) { if (notes[start].End > bottom) { break; } } startNoteCache[k] = start; } else { start = startNoteCache[k]; } if (left > 1 || right < 0) { return; } for (int i = start; i < notes.Count; i++) { var n = notes[i]; if (n.End < bottom) { startNoteCache[k] = start; continue; } if (n.Start > top) { break; } rn[pos++] = new RenderNote() { color = noteColorCache[n.Track], end = (float)((n.End - bottom) / range), start = (float)((n.Start - bottom) / range), }; if (pos >= noteBufferLength) { flush(); } } flush(); } }); var returnView = new System.Windows.Thickness(viewLeft, top, viewRight, bottom); RenderedFrame?.Invoke(this, new ViewRenderedArgs(previousThickness)); previousThickness = returnView; resetStartCache = false; lastBottomCache = bottom; } }