public void AddVertices <T>(BatchInfo material, VertexMode vertexMode, T[] vertexBuffer, int vertexCount) where T : struct, IVertexData { if (vertexCount == 0) { return; } if (vertexBuffer == null || vertexBuffer.Length == 0) { return; } if (vertexCount > vertexBuffer.Length) { vertexCount = vertexBuffer.Length; } if (material == null) { material = Material.Checkerboard.Res.InfoDirect; } if (this.pickingIndex != 0) { ColorRgba clr = new ColorRgba((this.pickingIndex << 8) | 0xFF); for (int i = 0; i < vertexCount; ++i) { vertexBuffer[i].Color = clr; } material = new BatchInfo(material); material.Technique = DrawTechnique.Picking; if (material.Textures == null) { material.MainTexture = Texture.White; } } else if (material.Technique == null || !material.Technique.IsAvailable) { material = new BatchInfo(material); material.Technique = DrawTechnique.Solid; } // When rendering without depth writing, use z sorting everywhere - there's no real depth buffering! bool zSort = !this.DepthWrite || material.Technique.Res.NeedsZSort; List <IDrawBatch> buffer = zSort ? this.drawBufferZSort : this.drawBuffer; float zSortIndex = zSort ? DrawBatch <T> .CalcZSortIndex(vertexBuffer, vertexCount) : 0.0f; if (buffer.Count > 0 && buffer[buffer.Count - 1].CanAppendJIT <T>( zSort ? 1.0f / this.zSortAccuracy : 0.0f, zSortIndex, material, vertexMode)) { buffer[buffer.Count - 1].AppendJIT(vertexBuffer, vertexCount); } else { buffer.Add(new DrawBatch <T>(material, vertexMode, vertexBuffer, vertexCount, zSortIndex)); } ++this.numRawBatches; }
/// <summary> /// Adds an already prepared batch to the drawing devices rendering schedule. /// </summary> /// <param name="batch"></param> public void AddBatch(DrawBatch batch) { bool sortByDepth = (this.projection == ProjectionMode.Screen) || batch.Material.Technique.Res.NeedsZSort; RawList <DrawBatch> batchBuffer = sortByDepth ? this.batchBufferBlended : this.batchBufferSolid; batchBuffer.Add(batch); ++this.numRawBatches; }
private void AggregateBatches(RawList <SortItem> sortItems, RawList <VertexDrawItem> drawItems, RawList <DrawBatch> batches) { VertexDrawItem[] drawData = drawItems.Data; SortItem[] sortData = sortItems.Data; SortItem activeSortItem = sortData[0]; VertexDrawItem activeItem = drawData[activeSortItem.DrawItemIndex]; int beginBatchIndex = 0; // Find sequences of draw items that can be batched together int count = sortItems.Count; for (int sortIndex = 1; sortIndex <= count; sortIndex++) { // Skip items until we can no longer put the next one into the same batch if (sortIndex < count) { SortItem sortItem = sortData[sortIndex]; if (activeItem.CanShareBatchWith(ref drawData[sortItem.DrawItemIndex])) { continue; } } // Create a batch for all previous items VertexBuffer vertexBuffer = this.vertexBuffers[activeItem.TypeIndex][activeItem.BufferIndex]; DrawBatch batch = new DrawBatch( vertexBuffer, this.batchIndexPool.Rent(sortIndex - beginBatchIndex), activeItem.Mode, activeItem.Material); for (int i = beginBatchIndex; i < sortIndex; i++) { batch.VertexRanges.Add(new VertexDrawRange { Index = drawData[sortData[i].DrawItemIndex].Offset, Count = drawData[sortData[i].DrawItemIndex].Count }); } batches.Add(batch); // Proceed with the current item being the new sharing reference if (sortIndex < count) { beginBatchIndex = sortIndex; activeSortItem = sortData[sortIndex]; activeItem = drawData[activeSortItem.DrawItemIndex]; } } }
public void Append(DrawBatch <T> other) { if (this.vertexCount + other.vertexCount > this.vertices.Length) { int newArrSize = MathF.Max(16, this.vertexCount * 2, this.vertexCount + other.vertexCount); Array.Resize(ref this.vertices, newArrSize); } Array.Copy(other.vertices, 0, this.vertices, this.vertexCount, other.vertexCount); this.vertexCount += other.vertexCount; if (this.material.Technique.Res.NeedsZSort) { CalcZSortIndex(); } }
public void UploadToVBO(List <IDrawBatch> batches) { int vertexCount = 0; T[] vertexData = null; if (batches.Count == 1) { // Only one batch? Don't bother copying data DrawBatch <T> b = batches[0] as DrawBatch <T>; vertexData = b.vertices; vertexCount = b.vertices.Length; } else { // Check how many vertices we got vertexCount = batches.Sum(t => t.VertexCount); // Allocate a static / shared buffer for uploading vertices if (uploadBuffer == null) { uploadBuffer = new T[Math.Max(vertexCount, 64)]; } else if (uploadBuffer.Length < vertexCount) { Array.Resize(ref uploadBuffer, Math.Max(vertexCount, uploadBuffer.Length * 2)); } // Collect vertex data in one array int curVertexPos = 0; vertexData = uploadBuffer; for (int i = 0; i < batches.Count; i++) { DrawBatch <T> b = batches[i] as DrawBatch <T>; Array.Copy(b.vertices, 0, vertexData, curVertexPos, b.vertexCount); curVertexPos += b.vertexCount; } } // Submit vertex data to GPU this.vertices[0].UploadToVBO(vertexData, vertexCount); }
public void AddVertices <T>(BatchInfo material, VertexMode vertexMode, T[] vertexBuffer, int vertexCount) where T : struct, IVertexData { if (vertexCount == 0) { return; } if (vertexBuffer == null || vertexBuffer.Length == 0) { return; } if (vertexCount > vertexBuffer.Length) { vertexCount = vertexBuffer.Length; } if (material == null) { material = Material.Checkerboard.Res.InfoDirect; } if (this.pickingIndex != 0) { ColorRgba clr = new ColorRgba((this.pickingIndex << 8) | 0xFF); for (int i = 0; i < vertexCount; ++i) { vertexBuffer[i].Color = clr; } material = new BatchInfo(material); material.Technique = DrawTechnique.Picking; if (material.Textures == null) { material.MainTexture = Texture.White; } } else if (material.Technique == null || !material.Technique.IsAvailable) { material = new BatchInfo(material); material.Technique = DrawTechnique.Solid; } // When rendering without depth writing, use z sorting everywhere - there's no real depth buffering! bool zSort = !this.DepthWrite || material.Technique.Res.NeedsZSort; List <IDrawBatch> buffer = zSort ? this.drawBufferZSort : this.drawBuffer; float zSortIndex = zSort ? DrawBatch <T> .CalcZSortIndex(vertexBuffer, vertexCount) : 0.0f; // Determine if we can append the incoming vertices into the previous batch IDrawBatch prevBatch = buffer.Count > 0 ? buffer[buffer.Count - 1] : null; if (prevBatch != null && // ToDo: Move into CanAppendJIT on next major version step: // Make sure to not generate batches that will be in the Large Object Heap (>= 85k bytes) // because this will trigger lots and lots of Gen2 collections over time. vertexCount + prevBatch.VertexCount < 1024 && // Check if the batches do match enough for being merged prevBatch.CanAppendJIT <T>( zSort ? 1.0f : 0.0f, // Obsolete as of 2016-06-17, can be replcaed with zSort bool. zSortIndex, material, vertexMode)) { prevBatch.AppendJIT(vertexBuffer, vertexCount); } else { buffer.Add(new DrawBatch <T>(material, vertexMode, vertexBuffer, vertexCount, zSortIndex)); } ++this.numRawBatches; }