@@ -91,6 +91,7 @@ public ElementInfo(int vertexCount, int indexCount, in TDrawInfo drawInfo, float
9191 private ElementInfo [ ] drawsQueue ;
9292 private int drawsQueueCount ;
9393 private Texture [ ] drawTextures ;
94+ private List < Buffer > lastFrameBuffers ;
9495
9596 private readonly int vertexStructSize ;
9697 private readonly int indexStructSize ;
@@ -141,6 +142,8 @@ protected BatchBase(GraphicsDevice device, EffectBytecode defaultEffectByteCode,
141142 // Creates the vertex buffer (shared by within a device context).
142143 // TODO: find a better way to do that, and check resource disposal
143144 ResourceContextPool = graphicsDevice . GetOrCreateSharedData ( resourceBufferInfo . ResourceKey , d => new ThreadLocal < DeviceResourceContext > ( ( ) => new DeviceResourceContext ( graphicsDevice , vertexDeclaration , resourceBufferInfo ) , true ) ) ;
145+
146+ lastFrameBuffers = new ( ) ;
144147 }
145148
146149 protected override void Destroy ( )
@@ -172,6 +175,10 @@ protected void Begin(GraphicsContext graphicsContext, EffectInstance effect, Spr
172175 {
173176 CheckEndHasBeenCalled ( "begin" ) ;
174177
178+ foreach ( var buffer in lastFrameBuffers )
179+ GraphicsContext . Allocator . ReleaseReference ( buffer ) ;
180+ lastFrameBuffers . Clear ( ) ;
181+
175182 ResourceContext = ResourceContextPool . Value ;
176183
177184 GraphicsContext = graphicsContext ;
@@ -418,120 +425,70 @@ private void DrawBatchPerTexture(Texture texture, ElementInfo[] sprites, int off
418425
419426 private void DrawBatchPerTextureAndPass ( ElementInfo [ ] sprites , int offset , int count )
420427 {
421- while ( count > 0 )
428+ ResourceContext . VertexBufferPosition = ResourceContext . VertexCount ;
429+ ResourceContext . IndexBufferPosition = ResourceContext . IndexCount ;
430+ for ( int end = offset + count ; offset < end ; )
422431 {
423- // How many index/vertex do we want to draw?
424- var indexCount = 0 ;
425- var vertexCount = 0 ;
426- var batchSize = 0 ;
427-
428- while ( batchSize < count )
432+ if ( ResourceContext . VertexBufferPosition == ResourceContext . VertexCount || ResourceContext . IndexBufferPosition == ResourceContext . IndexCount ) // Buffer is full, fetch the next ones
429433 {
430- var spriteIndex = offset + batchSize ;
431- ref var spriteElementInfo = ref sprites [ spriteIndex ] ;
434+ ResourceContext . VertexBufferPosition = 0 ;
435+ ResourceContext . IndexBufferPosition = 0 ;
432436
433- // How many sprites does the D3D vertex buffer have room for?
434- var remainingVertexSpace = ResourceContext . VertexCount - ResourceContext . VertexBufferPosition - vertexCount ;
435- var remainingIndexSpace = ResourceContext . IndexCount - ResourceContext . IndexBufferPosition - indexCount ;
437+ ResourceContext . VertexBuffer = GraphicsContext . Allocator . GetTemporaryBuffer ( new BufferDescription ( ResourceContext . VertexCount * vertexStructSize , BufferFlags . VertexBuffer , GraphicsResourceUsage . Dynamic ) ) ;
438+ GraphicsContext . CommandList . SetVertexBuffer ( 0 , ResourceContext . VertexBuffer , 0 , vertexStructSize ) ;
439+ lastFrameBuffers . Add ( ResourceContext . VertexBuffer ) ;
436440
437- // if there is not enough place left for either the indices or vertices of the current element...,
438- if ( spriteElementInfo . IndexCount > remainingIndexSpace || spriteElementInfo . VertexCount > remainingVertexSpace )
441+ if ( ResourceContext . IsIndexBufferDynamic )
439442 {
440- // if we haven't started the current batch yet, we restart at the beginning of the buffers.
441- if ( batchSize == 0 )
442- {
443- ResourceContext . VertexBufferPosition = 0 ;
444- ResourceContext . IndexBufferPosition = 0 ;
445- continue ;
446- }
447-
448- // else we perform the draw call and batch remaining elements in next draw call.
449- break ;
443+ ResourceContext . IndexBuffer = GraphicsContext . Allocator . GetTemporaryBuffer ( new BufferDescription ( ResourceContext . IndexCount * indexStructSize , BufferFlags . IndexBuffer , GraphicsResourceUsage . Dynamic ) ) ;
444+ GraphicsContext . CommandList . SetIndexBuffer ( ResourceContext . IndexBuffer , 0 , indexStructSize == sizeof ( int ) ) ;
445+ lastFrameBuffers . Add ( ResourceContext . IndexBuffer ) ;
450446 }
451-
452- ++ batchSize ;
447+ }
448+
449+ int indexCount = 0 , vertexCount = 0 ;
450+ int batchStart = offset ;
451+ for ( int vertexLeft = ResourceContext . VertexCount - ResourceContext . VertexBufferPosition , indexLeft = ResourceContext . IndexCount - ResourceContext . IndexBufferPosition ;
452+ offset < end && vertexCount < vertexLeft && indexCount < indexLeft ;
453+ offset ++ )
454+ {
455+ ref var spriteElementInfo = ref sprites [ offset ] ;
456+
453457 vertexCount += spriteElementInfo . VertexCount ;
454458 indexCount += spriteElementInfo . IndexCount ;
455459 }
456460
457- // Sets the data directly to the buffer in memory
458461 var offsetVertexInBytes = ResourceContext . VertexBufferPosition * vertexStructSize ;
459462 var offsetIndexInBytes = ResourceContext . IndexBufferPosition * indexStructSize ;
460463
461- if ( ResourceContext . VertexBufferPosition == 0 )
462- {
463- if ( ResourceContext . VertexBuffer != null )
464- GraphicsContext . Allocator . ReleaseReference ( ResourceContext . VertexBuffer ) ;
465- ResourceContext . VertexBuffer = GraphicsContext . Allocator . GetTemporaryBuffer ( new BufferDescription ( ResourceContext . VertexCount * vertexStructSize , BufferFlags . VertexBuffer , GraphicsResourceUsage . Dynamic ) ) ;
466- GraphicsContext . CommandList . SetVertexBuffer ( 0 , ResourceContext . VertexBuffer , 0 , vertexStructSize ) ;
467- }
464+ var mappedIndices = new MappedResource ( ) ;
465+ var mappedVertices = GraphicsContext . CommandList . MapSubresource ( ResourceContext . VertexBuffer , 0 , MapMode . WriteNoOverwrite , false , offsetVertexInBytes , vertexCount * vertexStructSize ) ;
466+ if ( ResourceContext . IsIndexBufferDynamic )
467+ mappedIndices = GraphicsContext . CommandList . MapSubresource ( ResourceContext . IndexBuffer , 0 , MapMode . WriteNoOverwrite , false , offsetIndexInBytes , indexCount * indexStructSize ) ;
468468
469- if ( ResourceContext . IsIndexBufferDynamic && ResourceContext . IndexBufferPosition == 0 )
470- {
471- if ( ResourceContext . IndexBuffer != null )
472- GraphicsContext . Allocator . ReleaseReference ( ResourceContext . IndexBuffer ) ;
473- ResourceContext . IndexBuffer = GraphicsContext . Allocator . GetTemporaryBuffer ( new BufferDescription ( ResourceContext . IndexCount * indexStructSize , BufferFlags . IndexBuffer , GraphicsResourceUsage . Dynamic ) ) ;
474- GraphicsContext . CommandList . SetIndexBuffer ( ResourceContext . IndexBuffer , 0 , indexStructSize == sizeof ( int ) ) ;
475- }
469+ var vertexPointer = mappedVertices . DataBox . DataPointer ;
470+ var indexPointer = mappedIndices . DataBox . DataPointer ;
476471
477- // ------------------------------------------------------------------------------------------------------------
478- // CAUTION: Performance problem under x64 resolved by this special codepath:
479- // For some unknown reasons, It seems that writing directly to the pointer returned by the MapSubresource is
480- // extremely inefficient using x64 but using a temporary buffer and performing a mempcy to the locked region
481- // seems to be running at the same speed than x86
482- // ------------------------------------------------------------------------------------------------------------
483- // TODO Check again why we need this code
484- //if (IntPtr.Size == 8)
485- //{
486- // if (x64TempBuffer == null)
487- // {
488- // x64TempBuffer = ToDispose(new DataBuffer(Utilities.SizeOf<VertexPositionColorTexture>() * MaxBatchSize * VerticesPerSprite));
489- // }
490-
491- // // Perform the update of all vertices on a temporary buffer
492- // var texturePtr = (VertexPositionColorTexture*)x64TempBuffer.DataPointer;
493- // for (int i = 0; i < batchSize; i++)
494- // {
495- // UpdateBufferValuesFromElementInfo(ref sprites[offset + i], ref texturePtr, deltaX, deltaY);
496- // }
497-
498- // // Then copy this buffer in one shot
499- // resourceContext.VertexBuffer.SetData(GraphicsDevice, new DataPointer(x64TempBuffer.DataPointer, batchSize * VerticesPerSprite * Utilities.SizeOf<VertexPositionColorTexture>()), offsetInBytes, noOverwrite);
500- //}
501- //else
472+ for ( var i = batchStart ; i < offset ; i ++ )
502473 {
503- var mappedIndices = new MappedResource ( ) ;
504- var mappedVertices = GraphicsContext . CommandList . MapSubresource ( ResourceContext . VertexBuffer , 0 , MapMode . WriteNoOverwrite , false , offsetVertexInBytes , vertexCount * vertexStructSize ) ;
505- if ( ResourceContext . IsIndexBufferDynamic )
506- mappedIndices = GraphicsContext . CommandList . MapSubresource ( ResourceContext . IndexBuffer , 0 , MapMode . WriteNoOverwrite , false , offsetIndexInBytes , indexCount * indexStructSize ) ;
507-
508- var vertexPointer = mappedVertices . DataBox . DataPointer ;
509- var indexPointer = mappedIndices . DataBox . DataPointer ;
474+ ref var spriteElementInfo = ref sprites [ i ] ;
510475
511- for ( var i = 0 ; i < batchSize ; i ++ )
512- {
513- var spriteIndex = offset + i ;
514- ref var spriteElementInfo = ref sprites [ spriteIndex ] ;
476+ UpdateBufferValuesFromElementInfo ( ref spriteElementInfo , vertexPointer , indexPointer , ResourceContext . VertexBufferPosition ) ;
515477
516- UpdateBufferValuesFromElementInfo ( ref spriteElementInfo , vertexPointer , indexPointer , ResourceContext . VertexBufferPosition ) ;
517-
518- ResourceContext . VertexBufferPosition += spriteElementInfo . VertexCount ;
519- vertexPointer += vertexStructSize * spriteElementInfo . VertexCount ;
520- indexPointer += indexStructSize * spriteElementInfo . IndexCount ;
521- }
522-
523- GraphicsContext . CommandList . UnmapSubresource ( mappedVertices ) ;
524- if ( ResourceContext . IsIndexBufferDynamic )
525- GraphicsContext . CommandList . UnmapSubresource ( mappedIndices ) ;
478+ ResourceContext . VertexBufferPosition += spriteElementInfo . VertexCount ;
479+ vertexPointer += vertexStructSize * spriteElementInfo . VertexCount ;
480+ indexPointer += indexStructSize * spriteElementInfo . IndexCount ;
526481 }
527482
483+ GraphicsContext . CommandList . UnmapSubresource ( mappedVertices ) ;
484+ if ( ResourceContext . IsIndexBufferDynamic )
485+ GraphicsContext . CommandList . UnmapSubresource ( mappedIndices ) ;
486+
528487 // Draw from the specified index
529488 GraphicsContext . CommandList . DrawIndexed ( indexCount , ResourceContext . IndexBufferPosition ) ;
530489
531490 // Update position, offset and remaining count
532491 ResourceContext . IndexBufferPosition += indexCount ;
533- offset += batchSize ;
534- count -= batchSize ;
535492 }
536493 }
537494
0 commit comments