private void DrawBatchPerTextureAndPass(ElementInfo[] sprites, int offset, int count) { while (count > 0) { // How many index/vertex do we want to draw? var indexCount = 0; var vertexCount = 0; var batchSize = 0; while (batchSize < count) { var spriteIndex = offset + batchSize; // How many sprites does the D3D vertex buffer have room for? var remainingVertexSpace = ResourceContext.VertexCount - ResourceContext.VertexBufferPosition - vertexCount; var remainingIndexSpace = ResourceContext.IndexCount - ResourceContext.IndexBufferPosition - indexCount; // if there is not enough place let for either the indices or vertices of the current element..., if (sprites[spriteIndex].IndexCount > remainingIndexSpace || sprites[spriteIndex].VertexCount > remainingVertexSpace) { // if we haven't started the current batch yet, we restart at the beginning of the buffers. if (batchSize == 0) { ResourceContext.VertexBufferPosition = 0; ResourceContext.IndexBufferPosition = 0; continue; } // else we perform the draw call and batch remaining elements in next draw call. break; } ++batchSize; vertexCount += sprites[spriteIndex].VertexCount; indexCount += sprites[spriteIndex].IndexCount; } // Sets the data directly to the buffer in memory var offsetVertexInBytes = ResourceContext.VertexBufferPosition * vertexStructSize; var offsetIndexInBytes = ResourceContext.IndexBufferPosition * indexStructSize; var noOverwriteVertex = ResourceContext.VertexBufferPosition == 0 ? MapMode.WriteDiscard : MapMode.WriteNoOverwrite; var noOverwriteIndex = ResourceContext.IndexBufferPosition == 0 ? MapMode.WriteDiscard : MapMode.WriteNoOverwrite; // ------------------------------------------------------------------------------------------------------------ // CAUTION: Performance problem under x64 resolved by this special codepath: // For some unknown reasons, It seems that writing directly to the pointer returned by the MapSubresource is // extremely inefficient using x64 but using a temporary buffer and performing a mempcy to the locked region // seems to be running at the same speed than x86 // ------------------------------------------------------------------------------------------------------------ // TODO Check again why we need this code //if (IntPtr.Size == 8) //{ // if (x64TempBuffer == null) // { // x64TempBuffer = ToDispose(new DataBuffer(Utilities.SizeOf<VertexPositionColorTexture>() * MaxBatchSize * VerticesPerSprite)); // } // // Perform the update of all vertices on a temporary buffer // var texturePtr = (VertexPositionColorTexture*)x64TempBuffer.DataPointer; // for (int i = 0; i < batchSize; i++) // { // UpdateBufferValuesFromElementInfo(ref sprites[offset + i], ref texturePtr, deltaX, deltaY); // } // // Then copy this buffer in one shot // resourceContext.VertexBuffer.SetData(GraphicsDevice, new DataPointer(x64TempBuffer.DataPointer, batchSize * VerticesPerSprite * Utilities.SizeOf<VertexPositionColorTexture>()), offsetInBytes, noOverwrite); //} //else { var mappedIndices = new MappedResource(); var mappedVertices = GraphicsDevice.MapSubresource(ResourceContext.VertexBuffer, 0, noOverwriteVertex, false, offsetVertexInBytes, vertexCount * vertexStructSize); if (ResourceContext.IsIndexBufferDynamic) { mappedIndices = GraphicsDevice.MapSubresource(ResourceContext.IndexBuffer, 0, noOverwriteIndex, false, offsetIndexInBytes, indexCount * indexStructSize); } var vertexPointer = mappedVertices.DataBox.DataPointer; var indexPointer = mappedIndices.DataBox.DataPointer; for (var i = 0; i < batchSize; i++) { var spriteIndex = offset + i; UpdateBufferValuesFromElementInfo(ref sprites[spriteIndex], vertexPointer, indexPointer, ResourceContext.VertexBufferPosition); ResourceContext.VertexBufferPosition += sprites[spriteIndex].VertexCount; vertexPointer += vertexStructSize * sprites[spriteIndex].VertexCount; indexPointer += indexStructSize * sprites[spriteIndex].IndexCount; } GraphicsDevice.UnmapSubresource(mappedVertices); if (ResourceContext.IsIndexBufferDynamic) { GraphicsDevice.UnmapSubresource(mappedIndices); } } // Draw from the specified index GraphicsDevice.DrawIndexed(PrimitiveType.TriangleList, indexCount, ResourceContext.IndexBufferPosition); // Update position, offset and remaining count ResourceContext.IndexBufferPosition += indexCount; offset += batchSize; count -= batchSize; } }
public void UnmapSubresource(MappedResource unmapped) { NativeDeviceContext.UnmapSubresource(unmapped.Resource.NativeResource, unmapped.SubResourceIndex); }