public void Unmap() { if (UseBufferOffsets && mappedConstantBuffer.Resource != null) { using (new DefaultCommandListLock(commandList)) { commandList.UnmapSubresource(mappedConstantBuffer); mappedConstantBuffer = new MappedResource(); } } }
public void Map(CommandList commandList) { if (UseBufferOffsets) { using (new DefaultCommandListLock(commandList)) { this.commandList = commandList; mappedConstantBuffer = commandList.MapSubresource(constantBuffer, 0, MapMode.WriteNoOverwrite); Data = mappedConstantBuffer.DataBox.DataPointer; } } }
/// <summary> /// Begins text rendering (swaps and maps the vertex buffer to write to). /// </summary> /// <param name="graphicsContext">The current GraphicsContext.</param> public void End([NotNull] GraphicsContext graphicsContext) { if (graphicsContext == null) { throw new ArgumentNullException(nameof(graphicsContext)); } // Reallocate buffers if max number of characters is exceeded if (charsToRenderCount > maxCharacterCount) { maxCharacterCount = (int)(1.5f * charsToRenderCount); Initialize(graphicsContext, maxCharacterCount); } // Set the rendering parameters simpleEffect.Parameters.Set(TexturingKeys.Texture0, DebugSpriteFont); simpleEffect.Parameters.Set(SpriteEffectKeys.Color, TextColor); // Swap vertex buffer activeVertexBufferIndex = ++activeVertexBufferIndex >= VertexBufferCount ? 0 : activeVertexBufferIndex; // Map the vertex buffer to write to mappedVertexBuffer = graphicsContext.CommandList.MapSubresource(vertexBuffers[activeVertexBufferIndex], 0, MapMode.WriteDiscard); mappedVertexBufferPointer = mappedVertexBuffer.DataBox.DataPointer; unsafe { // Clear buffer first (because of the buffer mapping mode used) Utilities.ClearMemory(mappedVertexBufferPointer, 0x0, VertexBufferLength * sizeof(VertexPositionNormalTexture)); charsToRenderCount = 0; //Draw the strings var constantInfos = new RectangleF(GlyphWidth, GlyphHeight, DebugSpriteWidth, DebugSpriteHeight); foreach (var textInfo in stringsToDraw) { var textLength = textInfo.Text.Length; var textLengthPointer = new IntPtr(&textLength); Native.NativeInvoke.xnGraphicsFastTextRendererGenerateVertices(constantInfos, textInfo.RenderingInfo, textInfo.Text, out textLengthPointer, out mappedVertexBufferPointer); charsToRenderCount += *(int *)textLengthPointer.ToPointer(); } } // Unmap the vertex buffer graphicsContext.CommandList.UnmapSubresource(mappedVertexBuffer); mappedVertexBufferPointer = IntPtr.Zero; // Update pipeline state pipelineState.State.SetDefaults(); pipelineState.State.RootSignature = simpleEffect.RootSignature; pipelineState.State.EffectBytecode = simpleEffect.Effect.Bytecode; pipelineState.State.DepthStencilState = DepthStencilStates.None; pipelineState.State.BlendState = BlendStates.AlphaBlend; pipelineState.State.Output.CaptureState(graphicsContext.CommandList); pipelineState.State.InputElements = inputElementDescriptions[activeVertexBufferIndex]; pipelineState.Update(); graphicsContext.CommandList.SetPipelineState(pipelineState.CurrentState); // Update effect simpleEffect.UpdateEffect(graphicsContext.CommandList.GraphicsDevice); simpleEffect.Apply(graphicsContext); // Bind and draw graphicsContext.CommandList.SetVertexBuffer(0, vertexBuffersBinding[activeVertexBufferIndex].Buffer, vertexBuffersBinding[activeVertexBufferIndex].Offset, vertexBuffersBinding[activeVertexBufferIndex].Stride); graphicsContext.CommandList.SetIndexBuffer(indexBufferBinding.Buffer, 0, indexBufferBinding.Is32Bit); graphicsContext.CommandList.DrawIndexed(charsToRenderCount * 6); }
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; ref var spriteElementInfo = ref sprites[spriteIndex]; // 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 left for either the indices or vertices of the current element..., if (spriteElementInfo.IndexCount > remainingIndexSpace || spriteElementInfo.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 += spriteElementInfo.VertexCount; indexCount += spriteElementInfo.IndexCount; } // Sets the data directly to the buffer in memory var offsetVertexInBytes = ResourceContext.VertexBufferPosition * vertexStructSize; var offsetIndexInBytes = ResourceContext.IndexBufferPosition * indexStructSize; if (ResourceContext.VertexBufferPosition == 0) { if (ResourceContext.VertexBuffer != null) { GraphicsContext.Allocator.ReleaseReference(ResourceContext.VertexBuffer); } ResourceContext.VertexBuffer = GraphicsContext.Allocator.GetTemporaryBuffer(new BufferDescription(ResourceContext.VertexCount * vertexStructSize, BufferFlags.VertexBuffer, GraphicsResourceUsage.Dynamic)); GraphicsContext.CommandList.SetVertexBuffer(0, ResourceContext.VertexBuffer, 0, vertexStructSize); } if (ResourceContext.IsIndexBufferDynamic && ResourceContext.IndexBufferPosition == 0) { if (ResourceContext.IndexBuffer != null) { GraphicsContext.Allocator.ReleaseReference(ResourceContext.IndexBuffer); } ResourceContext.IndexBuffer = GraphicsContext.Allocator.GetTemporaryBuffer(new BufferDescription(ResourceContext.IndexCount * indexStructSize, BufferFlags.IndexBuffer, GraphicsResourceUsage.Dynamic)); GraphicsContext.CommandList.SetIndexBuffer(ResourceContext.IndexBuffer, 0, indexStructSize == sizeof(int)); } // ------------------------------------------------------------------------------------------------------------ // 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 = GraphicsContext.CommandList.MapSubresource(ResourceContext.VertexBuffer, 0, MapMode.WriteNoOverwrite, false, offsetVertexInBytes, vertexCount * vertexStructSize); if (ResourceContext.IsIndexBufferDynamic) { mappedIndices = GraphicsContext.CommandList.MapSubresource(ResourceContext.IndexBuffer, 0, MapMode.WriteNoOverwrite, 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; ref var spriteElementInfo = ref sprites[spriteIndex]; UpdateBufferValuesFromElementInfo(ref spriteElementInfo, vertexPointer, indexPointer, ResourceContext.VertexBufferPosition); ResourceContext.VertexBufferPosition += spriteElementInfo.VertexCount; vertexPointer += vertexStructSize * spriteElementInfo.VertexCount; indexPointer += indexStructSize * spriteElementInfo.IndexCount; } GraphicsContext.CommandList.UnmapSubresource(mappedVertices); if (ResourceContext.IsIndexBufferDynamic) { GraphicsContext.CommandList.UnmapSubresource(mappedIndices); } }
// TODO GRAPHICS REFACTOR what should we do with this? public void UnmapSubresource(MappedResource unmapped) { NativeDeviceContext.UnmapSubresource(unmapped.Resource.NativeResource, unmapped.SubResourceIndex); }
/// <summary> /// Unmap <param name="mapped"/> resource. /// </summary> /// <param name="mapped">The mapped resource.</param> public void UnmapSubresource(MappedResource mapped) { NullHelper.ToImplement(); }