diff --git a/sources/core/Stride.Core.Serialization/Serialization/LZ4/LZ4Stream.cs b/sources/core/Stride.Core.Serialization/Serialization/LZ4/LZ4Stream.cs index b9434fe49e..3813c791b5 100644 --- a/sources/core/Stride.Core.Serialization/Serialization/LZ4/LZ4Stream.cs +++ b/sources/core/Stride.Core.Serialization/Serialization/LZ4/LZ4Stream.cs @@ -380,7 +380,7 @@ public override unsafe int Read(byte[] buffer, int offset, int count) fixed (byte* pDst = buffer) { Debug.Assert(pSrc is not null); - Unsafe.CopyBlockUnaligned(pDst + offset, pSrc + bufferOffset, (uint)chunk); + Utilities.CopyWithAlignmentFallback(pDst + offset, pSrc + bufferOffset, (uint)chunk); } } @@ -511,7 +511,7 @@ public override unsafe void Write(byte[] buffer, int offset, int count) fixed (byte* pDst = dataBuffer) { Debug.Assert(pDst is not null); - Unsafe.CopyBlockUnaligned(pDst + bufferOffset, pSrc + offset, (uint)chunk); + Utilities.CopyWithAlignmentFallback(pDst + bufferOffset, pSrc + offset, (uint)chunk); } } diff --git a/sources/core/Stride.Core.Serialization/Storage/Blob.cs b/sources/core/Stride.Core.Serialization/Storage/Blob.cs index 10068704d6..ae2210e3e6 100644 --- a/sources/core/Stride.Core.Serialization/Storage/Blob.cs +++ b/sources/core/Stride.Core.Serialization/Storage/Blob.cs @@ -24,7 +24,7 @@ internal unsafe Blob(ObjectDatabase objectDatabase, ObjectId objectId, IntPtr co Debug.Assert(size >= 0); this.Size = size; this.Content = Marshal.AllocHGlobal(size); - Unsafe.CopyBlockUnaligned((void*)this.Content, (void*)content, (uint)size); + Utilities.CopyWithAlignmentFallback((void*)this.Content, (void*)content, (uint)size); } internal unsafe Blob(ObjectDatabase objectDatabase, ObjectId objectId, Stream stream) diff --git a/sources/core/Stride.Core.Serialization/Streaming/ContentChunk.cs b/sources/core/Stride.Core.Serialization/Streaming/ContentChunk.cs index 282a06bf54..fc418a068c 100644 --- a/sources/core/Stride.Core.Serialization/Streaming/ContentChunk.cs +++ b/sources/core/Stride.Core.Serialization/Streaming/ContentChunk.cs @@ -104,7 +104,7 @@ public unsafe IntPtr GetData(DatabaseFileProvider fileProvider) var read = (uint)stream.Read(buffer, 0, (int)Math.Min(count, bufferCapacity)); if (read <= 0) break; - Unsafe.CopyBlockUnaligned(chunkBytesPtr, bufferStart, read); + Utilities.CopyWithAlignmentFallback(chunkBytesPtr, bufferStart, read); chunkBytesPtr += read; count -= read; } while (count > 0); diff --git a/sources/core/Stride.Core/UnmanagedArray.cs b/sources/core/Stride.Core/UnmanagedArray.cs index 3f939525c6..67e1ded34a 100644 --- a/sources/core/Stride.Core/UnmanagedArray.cs +++ b/sources/core/Stride.Core/UnmanagedArray.cs @@ -8,15 +8,13 @@ namespace Stride.Core; [Obsolete("Obtain Memory using GC.Allocate*Array or a Stride-specific allocator mechanism.")] public class UnmanagedArray : IDisposable where T : struct { - private readonly int sizeOfT; private readonly bool isShared; [Obsolete("Obtain Memory using GC.Allocate*Array or a Stride-specific allocator mechanism.")] public UnmanagedArray(int length) { Length = length; - sizeOfT = Unsafe.SizeOf(); - var finalSize = length * sizeOfT; + var finalSize = length * Unsafe.SizeOf(); Pointer = Utilities.AllocateMemory(finalSize); isShared = false; } @@ -43,8 +41,10 @@ public T this[int index] unsafe { var bptr = (byte*)Pointer; - bptr += index * sizeOfT; - res = Unsafe.ReadUnaligned(bptr); + bptr += index * Unsafe.SizeOf(); + // Pointer is aligned, we expect the struct to be aligned as well; + // If the user decides to Pack=1, this scope is the least of their worries + res = Unsafe.Read(bptr); } return res; @@ -60,8 +60,10 @@ public T this[int index] unsafe { var bptr = (byte*)Pointer; - bptr += index * sizeOfT; - Unsafe.WriteUnaligned(bptr, value); + bptr += index * Unsafe.SizeOf(); + // Pointer is aligned, we expect the struct to be aligned as well; + // If the user decides to Pack=1, this scope is the least of their worries + Unsafe.Write(bptr, value); } } } @@ -72,7 +74,6 @@ public unsafe void Read(T[] destination, int offset = 0) { throw new ArgumentOutOfRangeException(nameof(offset)); } - // Interop.Read((void*)Pointer, destination, offset, destination.Length); new Span((void*)Pointer, destination.Length - offset).CopyTo(destination.AsSpan(offset)); } @@ -87,8 +88,7 @@ public void Read(T[] destination, int pointerByteOffset, int arrayOffset, int ar { var ptr = (byte*)Pointer; ptr += pointerByteOffset; - // Interop.Read(ptr, destination, arrayOffset, arrayLen); - new Span(ptr, sizeOfT * arrayLen) + new Span(ptr, Unsafe.SizeOf() * arrayLen) .CopyTo(destination.AsSpan(arrayOffset, arrayLen)); } } @@ -99,7 +99,6 @@ public unsafe void Write(T[] source, int offset = 0) { throw new ArgumentOutOfRangeException(); } - // Interop.Write((void*)Pointer, source, offset, source.Length); source.AsSpan(offset).CopyTo(new Span((void*)Pointer, source.Length - offset)); } @@ -112,7 +111,6 @@ public unsafe void Write(T[] source, int pointerByteOffset, int arrayOffset, int var ptr = (byte*)Pointer; ptr += pointerByteOffset; - // Interop.Write(ptr, source, arrayOffset, arrayLen); source.AsSpan(arrayOffset, arrayLen).CopyTo(new Span(ptr, arrayLen)); } diff --git a/sources/core/Stride.Core/Utilities.cs b/sources/core/Stride.Core/Utilities.cs index ada2910eb6..805764d584 100644 --- a/sources/core/Stride.Core/Utilities.cs +++ b/sources/core/Stride.Core/Utilities.cs @@ -34,6 +34,50 @@ namespace Stride.Core; /// public static class Utilities { + // MUST BE A METHOD AND AGGRESSIVELY INLINED, OTHERWISE THE JIT WILL NOT ELIMINATE THE BRANCH + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsUnalignedSafe() => + RuntimeInformation.ProcessArchitecture is Architecture.X64 or Architecture.X86 or Architecture.Arm64; + + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe void CopyWithAlignmentFallback(ref byte destination, ref readonly byte source, uint byteCount) + { + if (IsUnalignedSafe()) + fixed (void* src = &source, dst = &destination) + Buffer.MemoryCopy(src, dst, byteCount, byteCount); + else + Unsafe.CopyBlockUnaligned(ref destination, in source, byteCount); + } + + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe void CopyWithAlignmentFallback(void* destination, void* source, uint byteCount) + { + if (IsUnalignedSafe()) + Buffer.MemoryCopy(source, destination, byteCount, byteCount); + else + Unsafe.CopyBlockUnaligned(destination, source, byteCount); + } + + /// + /// Zero out memory at the address provided + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe void Clear(void* startAddress, uint byteCount) + { + // Span swaps between InitBlockUnaligned and _ZeroMemory depending on the size + new Span(startAddress, (int)byteCount).Clear(); + } + + /// + /// Some of the architecture dotnet runs on do not support arbitrary unaligned reads or writes, + /// use this instead of other memcopy if you aren't sure whether the pointers you passed in are aligned. + /// + static void AlignmentFallbackDoc() { } + /// /// Allocate an aligned memory buffer. /// diff --git a/sources/engine/Stride.Engine/Animations/AnimationBlender.cs b/sources/engine/Stride.Engine/Animations/AnimationBlender.cs index d1a71e01da..aa4dc65f36 100644 --- a/sources/engine/Stride.Engine/Animations/AnimationBlender.cs +++ b/sources/engine/Stride.Engine/Animations/AnimationBlender.cs @@ -179,7 +179,7 @@ public static unsafe void Blend(CoreAnimationOperation blendOperation, float ble if (factorLeft > 0.0f && factorRight == 0.0f) { *resultData++ = 1.0f; - Unsafe.CopyBlockUnaligned(resultData, sourceLeftData, (uint)channel.Size); + Utilities.CopyWithAlignmentFallback(resultData, sourceLeftData, (uint)channel.Size); continue; } @@ -187,7 +187,7 @@ public static unsafe void Blend(CoreAnimationOperation blendOperation, float ble if (factorRight > 0.0f && factorLeft == 0.0f) { *resultData++ = 1.0f; - Unsafe.CopyBlockUnaligned(resultData, sourceRightData, (uint)channel.Size); + Utilities.CopyWithAlignmentFallback(resultData, sourceRightData, (uint)channel.Size); continue; } @@ -202,7 +202,7 @@ public static unsafe void Blend(CoreAnimationOperation blendOperation, float ble switch (channel.BlendType) { case BlendType.Blit: - Unsafe.CopyBlockUnaligned( + Utilities.CopyWithAlignmentFallback( resultData, blendFactor < 0.5f ? sourceLeftData : sourceRightData, (uint)channel.Size); @@ -229,7 +229,7 @@ public static unsafe void Blend(CoreAnimationOperation blendOperation, float ble switch (channel.BlendType) { case BlendType.Blit: - Unsafe.CopyBlockUnaligned(resultData, sourceLeftData, (uint)channel.Size); + Utilities.CopyWithAlignmentFallback(resultData, sourceLeftData, (uint)channel.Size); break; case BlendType.Float2: Vector2 rightValue2; @@ -257,7 +257,7 @@ public static unsafe void Blend(CoreAnimationOperation blendOperation, float ble switch (channel.BlendType) { case BlendType.Blit: - Unsafe.CopyBlockUnaligned(resultData, sourceLeftData, (uint)channel.Size); + Utilities.CopyWithAlignmentFallback(resultData, sourceLeftData, (uint)channel.Size); break; case BlendType.Float2: Vector2 rightValue2; diff --git a/sources/engine/Stride.Engine/Animations/AnimationClipEvaluator.cs b/sources/engine/Stride.Engine/Animations/AnimationClipEvaluator.cs index 80ca9a84e7..99a5bcf0b8 100644 --- a/sources/engine/Stride.Engine/Animations/AnimationClipEvaluator.cs +++ b/sources/engine/Stride.Engine/Animations/AnimationClipEvaluator.cs @@ -114,7 +114,7 @@ public unsafe void AddCurveValues(CompressedTimeSpan newTime, AnimationClipResul var channel = Channels.Items[index]; // For now, objects are not supported, so treat everything as a blittable struct. - channel.Curve?.AddValue(newTime, (IntPtr)(structures + channel.Offset + sizeof(float))); + channel.Curve?.AddValue(newTime, (structures + channel.Offset + sizeof(float))); } } } diff --git a/sources/engine/Stride.Engine/Animations/AnimationCurve.cs b/sources/engine/Stride.Engine/Animations/AnimationCurve.cs index 25e15ed83d..1153d3be57 100644 --- a/sources/engine/Stride.Engine/Animations/AnimationCurve.cs +++ b/sources/engine/Stride.Engine/Animations/AnimationCurve.cs @@ -50,7 +50,7 @@ public abstract class AnimationCurve /// /// The new time. /// The location. - public abstract void AddValue(CompressedTimeSpan newTime, IntPtr location); + public abstract unsafe void AddValue(CompressedTimeSpan newTime, byte* location); /// /// Meant for internal use, to call AnimationData{T}.FromAnimationChannels() without knowing the generic type. @@ -142,9 +142,9 @@ public int FindKeyIndex(CompressedTimeSpan time) } /// - public override unsafe void AddValue(CompressedTimeSpan newTime, nint location) + public override unsafe void AddValue(CompressedTimeSpan newTime, byte* location) { - var value = Unsafe.ReadUnaligned((void*)location); + var value = Unsafe.ReadUnaligned(location); KeyFrames.Add(new(newTime, value)); } diff --git a/sources/engine/Stride.Engine/Updater/UpdatableField.cs b/sources/engine/Stride.Engine/Updater/UpdatableField.cs index 539f406448..9b8fc74920 100644 --- a/sources/engine/Stride.Engine/Updater/UpdatableField.cs +++ b/sources/engine/Stride.Engine/Updater/UpdatableField.cs @@ -73,7 +73,7 @@ ldarg data [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void SetBlittable(IntPtr obj, IntPtr data) { - Unsafe.CopyBlockUnaligned((void*)obj, (void*)data, (uint)Size); + Utilities.CopyWithAlignmentFallback((void*)obj, (void*)data, (uint)Size); } /// diff --git a/sources/engine/Stride.Graphics/Buffer.cs b/sources/engine/Stride.Graphics/Buffer.cs index 638aaad092..1979d571e6 100644 --- a/sources/engine/Stride.Graphics/Buffer.cs +++ b/sources/engine/Stride.Graphics/Buffer.cs @@ -326,7 +326,7 @@ public unsafe void GetData(CommandList commandList, Buffer stagingTexture, Sp // Map the staging resource to a CPU accessible memory var mappedResource = commandList.MapSubresource(stagingTexture, 0, MapMode.Read); fixed (void* pointer = toData) - Unsafe.CopyBlockUnaligned(pointer, (void*)mappedResource.DataBox.DataPointer, (uint)toDataInBytes); + Utilities.CopyWithAlignmentFallback(pointer, (void*)mappedResource.DataBox.DataPointer, (uint)toDataInBytes); // Make sure that we unmap the resource in case of an exception commandList.UnmapSubresource(mappedResource); } @@ -386,7 +386,7 @@ public unsafe void SetData(CommandList commandList, ReadOnlySpan fromData, throw new ArgumentException("offset is only supported for textured declared with ResourceUsage.Default", "offsetInBytes"); var mappedResource = commandList.MapSubresource(this, 0, Usage == GraphicsResourceUsage.Staging ? MapMode.Write : MapMode.WriteDiscard); - Unsafe.CopyBlockUnaligned((void*)mappedResource.DataBox.DataPointer, pointer, (uint)sizeInBytes); + Utilities.CopyWithAlignmentFallback((void*)mappedResource.DataBox.DataPointer, pointer, (uint)sizeInBytes); commandList.UnmapSubresource(mappedResource); } } diff --git a/sources/engine/Stride.Graphics/Data/ImageTextureSerializer.cs b/sources/engine/Stride.Graphics/Data/ImageTextureSerializer.cs index f262236357..7f79e06314 100644 --- a/sources/engine/Stride.Graphics/Data/ImageTextureSerializer.cs +++ b/sources/engine/Stride.Graphics/Data/ImageTextureSerializer.cs @@ -122,7 +122,7 @@ private static unsafe void DeserializeImage(ContentManager contentManager, Image if (!chunk.IsLoaded) throw new ContentStreamingException("Data chunk is not loaded.", storage); - Unsafe.CopyBlockUnaligned((void*)bufferPtr, (void*)data, (uint)chunk.Size); + Utilities.CopyWithAlignmentFallback((void*)bufferPtr, (void*)data, (uint)chunk.Size); bufferPtr += chunk.Size; } } diff --git a/sources/engine/Stride.Graphics/Direct3D12/Buffer.Direct3D12.cs b/sources/engine/Stride.Graphics/Direct3D12/Buffer.Direct3D12.cs index 58492b7a29..520b212a7c 100644 --- a/sources/engine/Stride.Graphics/Direct3D12/Buffer.Direct3D12.cs +++ b/sources/engine/Stride.Graphics/Direct3D12/Buffer.Direct3D12.cs @@ -122,7 +122,7 @@ public unsafe void Recreate(IntPtr dataPointer) if (heapType == HeapType.Upload) { var uploadMemory = NativeResource.Map(0); - Unsafe.CopyBlockUnaligned((void*) uploadMemory, (void*) dataPointer, (uint) SizeInBytes); + Core.Utilities.CopyWithAlignmentFallback((void*) uploadMemory, (void*) dataPointer, (uint) SizeInBytes); NativeResource.Unmap(0); } else @@ -132,7 +132,7 @@ public unsafe void Recreate(IntPtr dataPointer) SharpDX.Direct3D12.Resource uploadResource; int uploadOffset; var uploadMemory = GraphicsDevice.AllocateUploadBuffer(SizeInBytes, out uploadResource, out uploadOffset); - Unsafe.CopyBlockUnaligned((void*) uploadMemory, (void*) dataPointer, (uint) SizeInBytes); + Core.Utilities.CopyWithAlignmentFallback((void*) uploadMemory, (void*) dataPointer, (uint) SizeInBytes); // TODO D3D12 lock NativeCopyCommandList usages var commandList = GraphicsDevice.NativeCopyCommandList; diff --git a/sources/engine/Stride.Graphics/Direct3D12/CommandList.Direct3D12.cs b/sources/engine/Stride.Graphics/Direct3D12/CommandList.Direct3D12.cs index 2e52e571b1..2c437b7865 100644 --- a/sources/engine/Stride.Graphics/Direct3D12/CommandList.Direct3D12.cs +++ b/sources/engine/Stride.Graphics/Direct3D12/CommandList.Direct3D12.cs @@ -777,7 +777,7 @@ public unsafe void Copy(GraphicsResource source, GraphicsResource destination) var destinationMapped = destinationTexture.NativeResource.Map(0); var sourceMapped = sourceTexture.NativeResource.Map(0, new SharpDX.Direct3D12.Range { Begin = 0, End = size }); - Unsafe.CopyBlockUnaligned((void*) destinationMapped, (void*) sourceMapped, (uint) size); + Core.Utilities.CopyWithAlignmentFallback((void*) destinationMapped, (void*) sourceMapped, (uint) size); sourceTexture.NativeResource.Unmap(0); destinationTexture.NativeResource.Unmap(0); @@ -976,7 +976,7 @@ internal unsafe void UpdateSubresource(GraphicsResource resource, int subResourc var uploadSize = region.Right - region.Left; var uploadMemory = GraphicsDevice.AllocateUploadBuffer(region.Right - region.Left, out var uploadResource, out var uploadOffset); - Unsafe.CopyBlockUnaligned((void*) uploadMemory, (void*) databox.DataPointer, (uint) uploadSize); + Core.Utilities.CopyWithAlignmentFallback((void*) uploadMemory, (void*) databox.DataPointer, (uint) uploadSize); ResourceBarrierTransition(resource, GraphicsResourceState.CopyDestination); FlushResourceBarriers(); diff --git a/sources/engine/Stride.Graphics/Direct3D12/QueryPool.Direct3D12.cs b/sources/engine/Stride.Graphics/Direct3D12/QueryPool.Direct3D12.cs index bf8670d5ad..a85f28cb83 100644 --- a/sources/engine/Stride.Graphics/Direct3D12/QueryPool.Direct3D12.cs +++ b/sources/engine/Stride.Graphics/Direct3D12/QueryPool.Direct3D12.cs @@ -26,7 +26,7 @@ public unsafe bool TryGetData(long[] dataArray) var mappedData = readbackBuffer.Map(0); fixed (long* dataPointer = &dataArray[0]) { - Unsafe.CopyBlockUnaligned(dataPointer, (void*) mappedData, (uint) QueryCount * 8); + Core.Utilities.CopyWithAlignmentFallback(dataPointer, (void*) mappedData, (uint) QueryCount * 8); } readbackBuffer.Unmap(subresource: 0); return true; diff --git a/sources/engine/Stride.Graphics/Direct3D12/Texture.Direct3D12.cs b/sources/engine/Stride.Graphics/Direct3D12/Texture.Direct3D12.cs index 79126f8f30..846ff28342 100644 --- a/sources/engine/Stride.Graphics/Direct3D12/Texture.Direct3D12.cs +++ b/sources/engine/Stride.Graphics/Direct3D12/Texture.Direct3D12.cs @@ -150,7 +150,7 @@ private unsafe void InitializeFromImpl(DataBox[] dataBoxes = null) var dataPointerCurrent = databox.DataPointer; for (int rowIndex = 0; rowIndex < mipHeight; rowIndex++) { - Unsafe.CopyBlockUnaligned((void*) uploadMemoryCurrent, (void*) dataPointerCurrent, (uint) mipRowPitch); + Core.Utilities.CopyWithAlignmentFallback((void*) uploadMemoryCurrent, (void*) dataPointerCurrent, (uint) mipRowPitch); uploadMemoryCurrent += mipRowPitch; dataPointerCurrent += databox.RowPitch; } @@ -208,7 +208,7 @@ private unsafe void InitializeFromImpl(DataBox[] dataBoxes = null) var dataPointerCurrent = dataPointer + z * databox.SlicePitch; for (int y = 0; y < rowCount; ++y) { - Unsafe.CopyBlockUnaligned((void*) uploadMemoryCurrent, (void*) dataPointerCurrent, (uint) rowSize); + Utilities.CopyWithAlignmentFallback((void*) uploadMemoryCurrent, (void*) dataPointerCurrent, (uint) rowSize); uploadMemoryCurrent += destRowPitch; dataPointerCurrent += databox.RowPitch; } diff --git a/sources/engine/Stride.Graphics/Font/CharacterBitmap.cs b/sources/engine/Stride.Graphics/Font/CharacterBitmap.cs index 307b6de5fe..5fe8784b53 100644 --- a/sources/engine/Stride.Graphics/Font/CharacterBitmap.cs +++ b/sources/engine/Stride.Graphics/Font/CharacterBitmap.cs @@ -68,8 +68,8 @@ private static unsafe void CopyAndAddBordersFromGrays(nint data, nint dataBytes, var rowsLessBorders = rows - (borderSize.Y << 1); var resetBorderLineSize = width * borderSize.Y; - Unsafe.InitBlockUnaligned((byte*)dataBytes, 0, (uint)resetBorderLineSize); - Unsafe.InitBlockUnaligned((byte*)dataBytes + width * rows - resetBorderLineSize, 0, (uint)resetBorderLineSize); // set last border lines to null + Utilities.Clear((byte*)dataBytes, (uint)resetBorderLineSize); + Utilities.Clear((byte*)dataBytes + width * rows - resetBorderLineSize, (uint)resetBorderLineSize); // set last border lines to null var src = (byte*)data; var dst = (byte*)dataBytes + resetBorderLineSize; @@ -104,8 +104,8 @@ private static unsafe void CopyAndAddBordersFromMono(nint data, nint dataBytes, var rowsLessBorders = rows - (borderSize.Y << 1); var resetBorderLineSize = (uint)(width * borderSize.Y); - Unsafe.InitBlockUnaligned((byte*)dataBytes, 0, resetBorderLineSize); // set first border lines to null - Unsafe.InitBlockUnaligned((byte*)dataBytes + rows * width - resetBorderLineSize, 0, resetBorderLineSize); // set last border lines to null + Utilities.Clear((byte*)dataBytes, resetBorderLineSize); // set first border lines to null + Utilities.Clear((byte*)dataBytes + rows * width - resetBorderLineSize, resetBorderLineSize); // set last border lines to null var rowSrc = (byte*)data; var dst = (byte*)dataBytes + resetBorderLineSize; diff --git a/sources/engine/Stride.Graphics/OpenGL/Texture.OpenGL.cs b/sources/engine/Stride.Graphics/OpenGL/Texture.OpenGL.cs index 6faf21b9c8..1451f9b43d 100644 --- a/sources/engine/Stride.Graphics/OpenGL/Texture.OpenGL.cs +++ b/sources/engine/Stride.Graphics/OpenGL/Texture.OpenGL.cs @@ -3,6 +3,7 @@ #if STRIDE_GRAPHICS_API_OPENGL using System; using System.Runtime.CompilerServices; +using Stride.Core; using Stride.Core.Mathematics; namespace Stride.Graphics @@ -598,7 +599,7 @@ private unsafe void UploadInitialData(BufferTargetARB bufferTarget, DataBox[] da if (data != IntPtr.Zero) { - Unsafe.CopyBlockUnaligned((void*) (bufferData + offset), (void*) data, (uint) (width * height * depth * TexturePixelSize)); + Utilities.CopyWithAlignmentFallback((void*) (bufferData + offset), (void*) data, (uint) (width * height * depth * TexturePixelSize)); } offset += width*height*TexturePixelSize; diff --git a/sources/engine/Stride.Graphics/Rendering/EffectParameterUpdater.cs b/sources/engine/Stride.Graphics/Rendering/EffectParameterUpdater.cs index 21bb144e0a..f45244ffb3 100644 --- a/sources/engine/Stride.Graphics/Rendering/EffectParameterUpdater.cs +++ b/sources/engine/Stride.Graphics/Rendering/EffectParameterUpdater.cs @@ -74,7 +74,7 @@ public unsafe void Update(GraphicsDevice graphicsDevice, ResourceGroupAllocator if (parameters.DataValues != null && resourceGroup.ConstantBuffer.Size > 0) { fixed (byte* dataValues = parameters.DataValues) - Unsafe.CopyBlockUnaligned( + Utilities.CopyWithAlignmentFallback( destination: (void*)resourceGroup.ConstantBuffer.Data, source: dataValues + bufferStartOffset, byteCount: (uint)resourceGroup.ConstantBuffer.Size); diff --git a/sources/engine/Stride.Graphics/ResourceGroupBufferUploader.cs b/sources/engine/Stride.Graphics/ResourceGroupBufferUploader.cs index 748f5fb689..5002df6997 100644 --- a/sources/engine/Stride.Graphics/ResourceGroupBufferUploader.cs +++ b/sources/engine/Stride.Graphics/ResourceGroupBufferUploader.cs @@ -76,7 +76,7 @@ public unsafe void Apply(CommandList commandList, ResourceGroup[] resourceGroups if (hasResourceRenaming) { var mappedConstantBuffer = commandList.MapSubresource(preallocatedBuffer, 0, MapMode.WriteDiscard); - Unsafe.CopyBlockUnaligned((void*)mappedConstantBuffer.DataBox.DataPointer, (void*)resourceGroup.ConstantBuffer.Data, (uint)resourceGroup.ConstantBuffer.Size); + Utilities.CopyWithAlignmentFallback((void*)mappedConstantBuffer.DataBox.DataPointer, (void*)resourceGroup.ConstantBuffer.Data, (uint)resourceGroup.ConstantBuffer.Size); commandList.UnmapSubresource(mappedConstantBuffer); } else diff --git a/sources/engine/Stride.Graphics/Texture.cs b/sources/engine/Stride.Graphics/Texture.cs index 3cab88d66a..f9e9c7e40b 100644 --- a/sources/engine/Stride.Graphics/Texture.cs +++ b/sources/engine/Stride.Graphics/Texture.cs @@ -863,7 +863,7 @@ public unsafe bool GetData(CommandList commandList, Texture stagingTexture, S if (box.RowPitch == rowStride && boxDepthStride == textureDepthStride && !isFlippedTexture) { fixed(void* destPtr = toData) - Unsafe.CopyBlockUnaligned(destPtr, (void*)box.DataPointer, (uint)mipMapSize); + Utilities.CopyWithAlignmentFallback(destPtr, (void*)box.DataPointer, (uint)mipMapSize); } else { @@ -884,7 +884,7 @@ public unsafe bool GetData(CommandList commandList, Texture stagingTexture, S for (int i = height - 1; i >= 0; i--) { // Copy a single row - Unsafe.CopyBlockUnaligned(destPtr, sourcePtr, (uint)rowStride); + Utilities.CopyWithAlignmentFallback(destPtr, sourcePtr, (uint)rowStride); sourcePtr -= box.RowPitch; destPtr += rowStride; } @@ -894,7 +894,7 @@ public unsafe bool GetData(CommandList commandList, Texture stagingTexture, S for (int i = 0; i < height; i++) { // Copy a single row - Unsafe.CopyBlockUnaligned(destPtr, sourcePtr, (uint)rowStride); + Utilities.CopyWithAlignmentFallback(destPtr, sourcePtr, (uint)rowStride); sourcePtr += box.RowPitch; destPtr += rowStride; } @@ -1037,7 +1037,7 @@ public unsafe void SetData(CommandList commandList, Span fromData, int arr // The fast way: If same stride, we can directly copy the whole texture in one shot if (box.RowPitch == rowStride && boxDepthStride == textureDepthStride) { - Unsafe.CopyBlockUnaligned((void*)box.DataPointer, pointer, (uint)sizeOfTextureData); + Utilities.CopyWithAlignmentFallback((void*)box.DataPointer, pointer, (uint)sizeOfTextureData); } else { @@ -1052,7 +1052,7 @@ public unsafe void SetData(CommandList commandList, Span fromData, int arr // Iterate on each line for (int i = 0; i < height; i++) { - Unsafe.CopyBlockUnaligned(destPtr, sourcePtr, (uint)rowStride); + Utilities.CopyWithAlignmentFallback(destPtr, sourcePtr, (uint)rowStride); destPtr += box.RowPitch; sourcePtr += rowStride; } diff --git a/sources/engine/Stride.Graphics/VertexHelper.cs b/sources/engine/Stride.Graphics/VertexHelper.cs index efb1e7a1f7..0f461e6f80 100644 --- a/sources/engine/Stride.Graphics/VertexHelper.cs +++ b/sources/engine/Stride.Graphics/VertexHelper.cs @@ -175,7 +175,7 @@ public static unsafe VertexTransformResult GenerateMultiTextureCoordinates(Verte var newVertexOffset = 0; for (int i = 0; i < vertexCount; ++i) { - Unsafe.CopyBlockUnaligned(newBuffer + newVertexOffset, oldBuffer + oldVertexOffset, (uint)vertexStride); + Utilities.CopyWithAlignmentFallback(newBuffer + newVertexOffset, oldBuffer + oldVertexOffset, (uint)vertexStride); var textureCoord = *(Vector2*)&oldBuffer[oldVertexOffset + vertexUVOffset]; for (int j = 0; j < newVertexElements.Count; j++) @@ -351,7 +351,7 @@ public static unsafe VertexTransformResult GenerateTangentBinormal(VertexDeclara var newVertexOffset = 0; for (int i = 0; i < vertexCount; ++i) { - Unsafe.CopyBlockUnaligned(newBuffer + newVertexOffset, oldBuffer + oldVertexOffset, (uint)oldVertexStride); + Utilities.CopyWithAlignmentFallback(newBuffer + newVertexOffset, oldBuffer + oldVertexOffset, (uint)oldVertexStride); var normal = *(Vector3*)&oldBuffer[oldVertexOffset + normalOffset]; var newTangentPtr = ((float*)(&newBuffer[newVertexOffset + tangentOffset])); diff --git a/sources/engine/Stride.Graphics/Vulkan/Buffer.Vulkan.cs b/sources/engine/Stride.Graphics/Vulkan/Buffer.Vulkan.cs index a532eba672..56aa0b2e89 100644 --- a/sources/engine/Stride.Graphics/Vulkan/Buffer.Vulkan.cs +++ b/sources/engine/Stride.Graphics/Vulkan/Buffer.Vulkan.cs @@ -3,6 +3,7 @@ #if STRIDE_GRAPHICS_API_VULKAN using System; using System.Runtime.CompilerServices; +using Stride.Core; using Vortice.Vulkan; using static Vortice.Vulkan.Vulkan; @@ -183,7 +184,7 @@ public unsafe void Recreate(IntPtr dataPointer) { void* uploadMemory; vkMapMemory(GraphicsDevice.NativeDevice, NativeMemory, 0, (ulong) SizeInBytes, VkMemoryMapFlags.None, &uploadMemory); - Unsafe.CopyBlockUnaligned(uploadMemory, (void*) dataPointer, (uint) SizeInBytes); + Utilities.CopyWithAlignmentFallback(uploadMemory, (void*) dataPointer, (uint) SizeInBytes); vkUnmapMemory(GraphicsDevice.NativeDevice, NativeMemory); } else @@ -191,7 +192,7 @@ public unsafe void Recreate(IntPtr dataPointer) var sizeInBytes = bufferDescription.SizeInBytes; var uploadMemory = GraphicsDevice.AllocateUploadBuffer(sizeInBytes, out var uploadResource, out var uploadOffset); - Unsafe.CopyBlockUnaligned((void*) uploadMemory, (void*) dataPointer, (uint) sizeInBytes); + Utilities.CopyWithAlignmentFallback((void*) uploadMemory, (void*) dataPointer, (uint) sizeInBytes); // Barrier var memoryBarrier = new VkBufferMemoryBarrier(uploadResource, VkAccessFlags.HostWrite, VkAccessFlags.TransferRead, (ulong) uploadOffset, (ulong) sizeInBytes); diff --git a/sources/engine/Stride.Graphics/Vulkan/CommandList.Vulkan.cs b/sources/engine/Stride.Graphics/Vulkan/CommandList.Vulkan.cs index 0830f13bd9..d217968da4 100644 --- a/sources/engine/Stride.Graphics/Vulkan/CommandList.Vulkan.cs +++ b/sources/engine/Stride.Graphics/Vulkan/CommandList.Vulkan.cs @@ -1198,7 +1198,7 @@ internal unsafe void UpdateSubresource(GraphicsResource resource, int subResourc var uploadMemory = GraphicsDevice.AllocateUploadBuffer(lengthInBytes + alignmentMask, out var uploadResource, out var uploadOffset); var alignment = ((uploadOffset + alignmentMask) & ~alignmentMask) - uploadOffset; - Unsafe.CopyBlockUnaligned((void*) (uploadMemory + alignment), (void*) databox.DataPointer, (uint) lengthInBytes); + Utilities.CopyWithAlignmentFallback((void*) (uploadMemory + alignment), (void*) databox.DataPointer, (uint) lengthInBytes); var uploadBufferMemoryBarrier = new VkBufferMemoryBarrier(uploadResource, VkAccessFlags.HostWrite, VkAccessFlags.TransferRead, (ulong) (uploadOffset + alignment), (ulong) lengthInBytes); diff --git a/sources/engine/Stride.Graphics/Vulkan/Texture.Vulkan.cs b/sources/engine/Stride.Graphics/Vulkan/Texture.Vulkan.cs index c138ce2872..98d295e3b4 100644 --- a/sources/engine/Stride.Graphics/Vulkan/Texture.Vulkan.cs +++ b/sources/engine/Stride.Graphics/Vulkan/Texture.Vulkan.cs @@ -3,6 +3,7 @@ #if STRIDE_GRAPHICS_API_VULKAN using System; using System.Runtime.CompilerServices; +using Stride.Core; using Vortice.Vulkan; using static Vortice.Vulkan.Vulkan; @@ -339,7 +340,7 @@ private unsafe void InitializeData(DataBox[] dataBoxes) uploadMemory += alignment; uploadOffset += alignment; - Unsafe.CopyBlockUnaligned((void*) uploadMemory, (void*) (dataBoxes[i].DataPointer), (uint) slicePitch); + Utilities.CopyWithAlignmentFallback((void*) uploadMemory, (void*) (dataBoxes[i].DataPointer), (uint) slicePitch); if (Usage == GraphicsResourceUsage.Staging) { diff --git a/sources/engine/Stride.Particles/ParticlePool.cs b/sources/engine/Stride.Particles/ParticlePool.cs index 08ba47adc5..319313cf40 100644 --- a/sources/engine/Stride.Particles/ParticlePool.cs +++ b/sources/engine/Stride.Particles/ParticlePool.cs @@ -241,10 +241,10 @@ private unsafe void CopyParticleData(int dst, int src) foreach (var field in fields.Values) { var accessor = new ParticleFieldAccessor(field); - Unsafe.CopyBlockUnaligned((void*) dstParticle[accessor], (void*) srcParticle[accessor], (uint) field.Size); + Utilities.CopyWithAlignmentFallback((void*) dstParticle[accessor], (void*) srcParticle[accessor], (uint) field.Size); } #else - Unsafe.CopyBlockUnaligned((void*)dstParticle.Pointer, (void*)srcParticle.Pointer, (uint)ParticleSize); + Utilities.CopyWithAlignmentFallback((void*)dstParticle.Pointer, (void*)srcParticle.Pointer, (uint)ParticleSize); #endif } @@ -393,16 +393,16 @@ private unsafe void ReallocateForFieldAdded(nint oldPool, int oldCapacity, int o #if PARTICLES_SOA // Easy case - the new field is added to the end. Copy the existing memory block into the new one - Unsafe.CopyBlockUnaligned((void*) newPool, (void*) oldPool, (uint) (oldSize * oldCapacity)); - Unsafe.InitBlockUnaligned((void*) (newPool + oldSize * oldCapacity), 0, (uint) ((newSize - oldSize) * oldCapacity)); + Utilities.CopyWithAlignmentFallback((void*) newPool, (void*) oldPool, (uint) (oldSize * oldCapacity)); + Utilities.Clear((void*) (newPool + oldSize * oldCapacity), (uint) ((newSize - oldSize) * oldCapacity)); #else // Clear the memory first instead of once per particle - Unsafe.InitBlockUnaligned((void*)newPool, 0, (uint)(newSize * newCapacity)); + Utilities.Clear((void*)newPool, (uint)(newSize * newCapacity)); // Complex case - needs to copy the head of each particle for (var i = 0; i < oldCapacity; i++) { - Unsafe.CopyBlockUnaligned((byte*)newPool + i * newSize, (byte*)oldPool + i * oldSize, (uint)oldSize); + Utilities.CopyWithAlignmentFallback((byte*)newPool + i * newSize, (byte*)oldPool + i * oldSize, (uint)oldSize); } #endif } @@ -431,7 +431,7 @@ private unsafe void ReallocateForCapacityChanged(nint oldPool, int oldCapacity, #if PARTICLES_SOA // Clear the memory first instead of once per particle - Unsafe.InitBlockUnaligned((void*) newPool, 0, (uint) (newSize * newCapacity)); + Utilities.Clear((void*) newPool, (uint) (newSize * newCapacity)); var oldOffset = 0; var newOffset = 0; @@ -440,7 +440,7 @@ private unsafe void ReallocateForCapacityChanged(nint oldPool, int oldCapacity, foreach (var field in fields.Values) { var copySize = Math.Min(oldCapacity, newCapacity) * field.Size; - Unsafe.CopyBlockUnaligned((void*) (newPool + newOffset), (void*) (oldPool + oldOffset), (uint) copySize); + Utilities.CopyWithAlignmentFallback((void*) (newPool + newOffset), (void*) (oldPool + oldOffset), (uint) copySize); oldOffset += (field.Size * oldCapacity); newOffset += (field.Size * newCapacity); @@ -449,12 +449,12 @@ private unsafe void ReallocateForCapacityChanged(nint oldPool, int oldCapacity, if (newCapacity > oldCapacity) { var size = (uint)(newSize * oldCapacity); - Unsafe.CopyBlockUnaligned((byte*)newPool, (byte*)oldPool, size); - Unsafe.InitBlockUnaligned((byte*)newPool + size, 0, (uint)(newSize * (newCapacity - oldCapacity))); + Utilities.CopyWithAlignmentFallback((byte*)newPool, (byte*)oldPool, size); + Utilities.Clear((byte*)newPool + size, (uint)(newSize * (newCapacity - oldCapacity))); } else { - Unsafe.CopyBlockUnaligned((void*)newPool, (void*)oldPool, (uint)(newSize * newCapacity)); + Utilities.CopyWithAlignmentFallback((void*)newPool, (void*)oldPool, (uint)(newSize * newCapacity)); } #endif } @@ -526,13 +526,13 @@ private unsafe void ReallocateForFieldRemoved(IntPtr oldPool, int oldCapacity, i continue; #error This is broken. This will AV. - Unsafe.CopyBlockUnaligned((byte*)newPool + fieldOffset, (void*)field.Offset, (uint)(field.Size * ParticleCapacity)); + Utilities.CopyWithAlignmentFallback((byte*)newPool + fieldOffset, (void*)field.Offset, (uint)(field.Size * ParticleCapacity)); fieldOffset += field.Size * ParticleCapacity; } #else // Clear the memory first instead of once per particle - Unsafe.InitBlockUnaligned((void*)newPool, 0, (uint)(newSize * newCapacity)); + Utilities.Clear((void*)newPool, (uint)(newSize * newCapacity)); // Complex case - needs to copy up to two parts of each particle var firstHalfSize = 0; @@ -560,7 +560,7 @@ private unsafe void ReallocateForFieldRemoved(IntPtr oldPool, int oldCapacity, i { for (var i = 0; i < oldCapacity; i++) { - Unsafe.CopyBlockUnaligned((byte*)newPool + i * newSize, (byte*)oldPool + i * oldSize, (uint)firstHalfSize); + Utilities.CopyWithAlignmentFallback((byte*)newPool + i * newSize, (byte*)oldPool + i * oldSize, (uint)firstHalfSize); } } @@ -570,7 +570,7 @@ private unsafe void ReallocateForFieldRemoved(IntPtr oldPool, int oldCapacity, i for (var i = 0; i < oldCapacity; i++) { - Unsafe.CopyBlockUnaligned((byte*)newPool + i * newSize + firstHalfSize, (byte*)oldPool + i * oldSize + secondHalfOffset, (uint)secondHalfSize); + Utilities.CopyWithAlignmentFallback((byte*)newPool + i * newSize + firstHalfSize, (byte*)oldPool + i * oldSize + secondHalfOffset, (uint)secondHalfSize); } } #endif diff --git a/sources/engine/Stride.Particles/VertexLayouts/ParticleBufferState.cs b/sources/engine/Stride.Particles/VertexLayouts/ParticleBufferState.cs index 39cfcca20a..1ab6d1fa60 100644 --- a/sources/engine/Stride.Particles/VertexLayouts/ParticleBufferState.cs +++ b/sources/engine/Stride.Particles/VertexLayouts/ParticleBufferState.cs @@ -3,6 +3,7 @@ using System; using System.Runtime.CompilerServices; +using Stride.Core; namespace Stride.Particles.VertexLayouts { @@ -62,7 +63,7 @@ public void SetVerticesPerSegment(int verticesForFirstSegment, int verticesForMi /// Pointer to the source data public unsafe void SetAttribute(AttributeAccessor accessor, nint ptrRef) { - Unsafe.CopyBlockUnaligned((byte*)VertexBuffer + accessor.Offset, (void*)ptrRef, (uint)accessor.Size); + Utilities.CopyWithAlignmentFallback((byte*)VertexBuffer + accessor.Offset, (void*)ptrRef, (uint)accessor.Size); } /// @@ -74,7 +75,7 @@ public unsafe void SetAttributePerParticle(AttributeAccessor accessor, nint ptrR { for (var i = 0; i < vertexBuilder.VerticesPerParticle; i++) { - Unsafe.CopyBlockUnaligned((byte*)VertexBuffer + accessor.Offset + i * VertexStride, (void*)ptrRef, (uint)accessor.Size); + Utilities.CopyWithAlignmentFallback((byte*)VertexBuffer + accessor.Offset + i * VertexStride, (void*)ptrRef, (uint)accessor.Size); } } @@ -87,7 +88,7 @@ public unsafe void SetAttributePerSegment(AttributeAccessor accessor, nint ptrRe { for (var i = 0; i < VerticesPerSegCurrent; i++) { - Unsafe.CopyBlockUnaligned((byte*)VertexBuffer + accessor.Offset + i * VertexStride, (void*)ptrRef, (uint)accessor.Size); + Utilities.CopyWithAlignmentFallback((byte*)VertexBuffer + accessor.Offset + i * VertexStride, (void*)ptrRef, (uint)accessor.Size); } } diff --git a/sources/engine/Stride.Rendering/Extensions/HalfBufferExtensions.cs b/sources/engine/Stride.Rendering/Extensions/HalfBufferExtensions.cs index 55553683f5..7d17f7908c 100644 --- a/sources/engine/Stride.Rendering/Extensions/HalfBufferExtensions.cs +++ b/sources/engine/Stride.Rendering/Extensions/HalfBufferExtensions.cs @@ -114,7 +114,7 @@ public static unsafe void CompactHalf(ref VertexBufferBinding vertexBufferBindin else { // Copy as is - Unsafe.CopyBlockUnaligned(newBufferElementPtr, oldBufferElementPtr, (uint)element.VertexElementWithOffset.Size); + Utilities.CopyWithAlignmentFallback(newBufferElementPtr, oldBufferElementPtr, (uint)element.VertexElementWithOffset.Size); } } diff --git a/sources/engine/Stride.Rendering/Extensions/IndexExtensions.cs b/sources/engine/Stride.Rendering/Extensions/IndexExtensions.cs index 7dba87f285..606265f9fe 100644 --- a/sources/engine/Stride.Rendering/Extensions/IndexExtensions.cs +++ b/sources/engine/Stride.Rendering/Extensions/IndexExtensions.cs @@ -52,7 +52,7 @@ public static unsafe void RemoveIndexBuffer(this MeshDraw meshData) for (int i = 0; i < indexBuffer.Count; ++i) { var index = ((int*)indexBufferStart)[i]; - Unsafe.CopyBlockUnaligned(newVerticesStart + i * stride, vertexBufferStart + index * stride, (uint)stride); + Utilities.CopyWithAlignmentFallback(newVerticesStart + i * stride, vertexBufferStart + index * stride, (uint)stride); } } @@ -85,7 +85,7 @@ public static unsafe void GenerateIndexBuffer(this MeshDraw meshData, VertexDecl var vertexBufferDataCurrent = vertexBufferDataStart; for (int i = 0; i < vertices.Length; ++i) { - Unsafe.CopyBlockUnaligned(vertexBufferDataCurrent, oldVertexBufferDataStart + oldVertexStride * vertices[i], (uint)newVertexStride); + Utilities.CopyWithAlignmentFallback(vertexBufferDataCurrent, oldVertexBufferDataStart + oldVertexStride * vertices[i], (uint)newVertexStride); vertexBufferDataCurrent += newVertexStride; } meshData.VertexBuffers[0] = new VertexBufferBinding(new BufferData(BufferFlags.VertexBuffer, vertexBufferData).ToSerializableVersion(), declaration, indexMapping.Vertices.Length); @@ -96,7 +96,7 @@ public static unsafe void GenerateIndexBuffer(this MeshDraw meshData, VertexDecl fixed (int* indexDataStart = &indexMapping.Indices[0]) fixed (byte* indexBufferDataStart = &indexBufferData[0]) { - Unsafe.CopyBlockUnaligned(indexBufferDataStart, indexDataStart, (uint)indexBufferData.Length); + Utilities.CopyWithAlignmentFallback(indexBufferDataStart, indexDataStart, (uint)indexBufferData.Length); meshData.IndexBuffer = new IndexBufferBinding(new BufferData(BufferFlags.IndexBuffer, indexBufferData).ToSerializableVersion(), true, indexMapping.Indices.Length); } } @@ -286,7 +286,7 @@ public static unsafe void GenerateIndexBufferAEN(this MeshDraw meshData) fixed (int* indexDataStart = &newIndices[0]) fixed (byte* indexBufferDataStart = &indexBufferData[0]) { - Unsafe.CopyBlockUnaligned(indexBufferDataStart, indexDataStart, (uint)indexBufferData.Length); + Utilities.CopyWithAlignmentFallback(indexBufferDataStart, indexDataStart, (uint)indexBufferData.Length); } meshData.IndexBuffer = new IndexBufferBinding(new BufferData(BufferFlags.IndexBuffer, indexBufferData).ToSerializableVersion(), true, triangleCount * 12); diff --git a/sources/engine/Stride.Rendering/Extensions/MergeExtensions.cs b/sources/engine/Stride.Rendering/Extensions/MergeExtensions.cs index 9dbcf0cc5b..b48db0ecea 100644 --- a/sources/engine/Stride.Rendering/Extensions/MergeExtensions.cs +++ b/sources/engine/Stride.Rendering/Extensions/MergeExtensions.cs @@ -91,7 +91,7 @@ public static unsafe MeshDraw MergeDrawData(IList meshDrawDatas, bool var sourceBuffer = meshDrawData.VertexBuffers[0].Buffer.GetSerializationData(); fixed (byte* sourceBufferDataStart = &sourceBuffer.Content[0]) { - Unsafe.CopyBlockUnaligned(destBufferDataCurrent, sourceBufferDataStart, (uint)sourceBuffer.Content.Length); + Utilities.CopyWithAlignmentFallback(destBufferDataCurrent, sourceBufferDataStart, (uint)sourceBuffer.Content.Length); destBufferDataCurrent += sourceBuffer.Content.Length; } } @@ -135,7 +135,7 @@ public static unsafe MeshDraw MergeDrawData(IList meshDrawDatas, bool fixed (byte* sourceBufferDataStart = &sourceBufferContent[0]) { - Unsafe.CopyBlockUnaligned(destBufferDataCurrent, sourceBufferDataStart, + Utilities.CopyWithAlignmentFallback(destBufferDataCurrent, sourceBufferDataStart, (uint)sourceBufferContent.Length); destBufferDataCurrent += sourceBufferContent.Length; } diff --git a/sources/engine/Stride.Rendering/Extensions/PolySortExtensions.cs b/sources/engine/Stride.Rendering/Extensions/PolySortExtensions.cs index 1610284892..7552d49e83 100644 --- a/sources/engine/Stride.Rendering/Extensions/PolySortExtensions.cs +++ b/sources/engine/Stride.Rendering/Extensions/PolySortExtensions.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; +using Stride.Core; using Stride.Core.Mathematics; using Stride.Graphics; using Stride.Graphics.Data; @@ -72,7 +73,7 @@ public static unsafe void SortMeshPolygons(this MeshDraw meshData, Vector3 viewD foreach (var index in sortedIndices) { - Unsafe.CopyBlockUnaligned( + Utilities.CopyWithAlignmentFallback( destination: newIndexBufferPointer, source: oldIndexDataStart + index * polyIndicesSize, byteCount: polyIndicesSize); diff --git a/sources/engine/Stride.Rendering/Extensions/SplitExtensions.cs b/sources/engine/Stride.Rendering/Extensions/SplitExtensions.cs index 33c4eeae9a..56b0bc3859 100644 --- a/sources/engine/Stride.Rendering/Extensions/SplitExtensions.cs +++ b/sources/engine/Stride.Rendering/Extensions/SplitExtensions.cs @@ -2,6 +2,7 @@ // Distributed under the MIT license. See the LICENSE.md file in the project root for more information. using System.Collections.Generic; using System.Runtime.CompilerServices; +using Stride.Core; using Stride.Graphics; using Stride.Graphics.Data; using Stride.Rendering; @@ -124,7 +125,7 @@ public static unsafe List SplitMesh(MeshDraw meshDrawData, bool can32b { //copy vertex buffer foreach (var index in splitInfo.UsedIndices) - Unsafe.CopyBlockUnaligned( + Utilities.CopyWithAlignmentFallback( destination: newVertexBufferPtr + stride * splitInfo.IndexRemapping[index], source: vertexBufferPtr + stride * index, byteCount: (uint)stride); diff --git a/sources/engine/Stride.Rendering/Extensions/VertexExtensions.cs b/sources/engine/Stride.Rendering/Extensions/VertexExtensions.cs index fbee5cdc02..8e1e5d54cb 100644 --- a/sources/engine/Stride.Rendering/Extensions/VertexExtensions.cs +++ b/sources/engine/Stride.Rendering/Extensions/VertexExtensions.cs @@ -43,7 +43,7 @@ public static unsafe T[] GetVertexBufferData(this MeshDraw meshData, params s { foreach (var vertexElementWithOffset in offsets) { - Unsafe.CopyBlockUnaligned(ptrOutput, ptrInput + vertexElementWithOffset.Offset, (uint)vertexElementWithOffset.Size); + Utilities.CopyWithAlignmentFallback(ptrOutput, ptrInput + vertexElementWithOffset.Offset, (uint)vertexElementWithOffset.Size); ptrOutput += vertexElementWithOffset.Size; } ptrInput += declaration.VertexStride; diff --git a/sources/engine/Stride.Rendering/Rendering/Lights/RenderLightCollectionGroup.cs b/sources/engine/Stride.Rendering/Rendering/Lights/RenderLightCollectionGroup.cs index a2efbec1ea..3e054e3d6b 100644 --- a/sources/engine/Stride.Rendering/Rendering/Lights/RenderLightCollectionGroup.cs +++ b/sources/engine/Stride.Rendering/Rendering/Lights/RenderLightCollectionGroup.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; +using Stride.Core; using Stride.Core.Collections; namespace Stride.Rendering.Lights @@ -119,14 +120,13 @@ public RenderLightCollection FindLightCollectionByGroup(RenderGroup group) /// public Type LightType { get; } - internal unsafe void Clear() + internal void Clear() { allLights.Clear(); allLightsWithShadows.Clear(); allMasks.Clear(); - fixed (void* ptr = groupMasks) - Unsafe.InitBlockUnaligned(ptr, 0, (uint)groupMasks.Length * sizeof(uint)); + groupMasks.AsSpan().Clear(); // Only clear collections that were previously allocated (no need to iterate on all collections from the pool) foreach (var collection in lightCollectionPool) diff --git a/sources/engine/Stride.Rendering/Rendering/LogicalGroupExtensions.cs b/sources/engine/Stride.Rendering/Rendering/LogicalGroupExtensions.cs index 6a83f52c84..c854758604 100644 --- a/sources/engine/Stride.Rendering/Rendering/LogicalGroupExtensions.cs +++ b/sources/engine/Stride.Rendering/Rendering/LogicalGroupExtensions.cs @@ -56,7 +56,7 @@ public static unsafe void UpdateLogicalGroup(this ResourceGroup resourceGroup, r var mappedDrawLighting = (byte*)resourceGroup.ConstantBuffer.Data + logicalGroup.ConstantBufferOffset; fixed (byte* dataValues = sourceParameters.DataValues) - Unsafe.CopyBlockUnaligned(mappedDrawLighting, dataValues + sourceOffset, (uint)logicalGroup.ConstantBufferSize); + Utilities.CopyWithAlignmentFallback(mappedDrawLighting, dataValues + sourceOffset, (uint)logicalGroup.ConstantBufferSize); } } } diff --git a/sources/engine/Stride.Rendering/Rendering/Materials/MaterialRenderFeature.cs b/sources/engine/Stride.Rendering/Rendering/Materials/MaterialRenderFeature.cs index 59f571b19b..fc1da0898b 100644 --- a/sources/engine/Stride.Rendering/Rendering/Materials/MaterialRenderFeature.cs +++ b/sources/engine/Stride.Rendering/Rendering/Materials/MaterialRenderFeature.cs @@ -398,7 +398,7 @@ public static unsafe bool UpdateMaterial(RenderSystem renderSystem, RenderDrawCo { var mappedCB = (byte*)materialInfo.Resources.ConstantBuffer.Data; fixed (byte* dataValues = materialInfo.ParameterCollection.DataValues) - Unsafe.CopyBlockUnaligned(mappedCB, dataValues, (uint)materialInfo.Resources.ConstantBuffer.Size); + Utilities.CopyWithAlignmentFallback(mappedCB, dataValues, (uint)materialInfo.Resources.ConstantBuffer.Size); } return true; diff --git a/sources/engine/Stride.Rendering/Rendering/SkinningRenderFeature.cs b/sources/engine/Stride.Rendering/Rendering/SkinningRenderFeature.cs index c453dfb92c..3ef0e1fad7 100644 --- a/sources/engine/Stride.Rendering/Rendering/SkinningRenderFeature.cs +++ b/sources/engine/Stride.Rendering/Rendering/SkinningRenderFeature.cs @@ -137,7 +137,7 @@ public override unsafe void Prepare(RenderDrawContext context) fixed (Matrix* blendMatricesPtr = renderModelObjectInfo) { - Unsafe.CopyBlockUnaligned(mappedCB, blendMatricesPtr, (uint)renderModelObjectInfo.Length * (uint)sizeof(Matrix)); + Utilities.CopyWithAlignmentFallback(mappedCB, blendMatricesPtr, (uint)renderModelObjectInfo.Length * (uint)sizeof(Matrix)); } } }); diff --git a/sources/engine/Stride/Graphics/DDSHelper.cs b/sources/engine/Stride/Graphics/DDSHelper.cs index f67759c7bf..85600c9192 100644 --- a/sources/engine/Stride/Graphics/DDSHelper.cs +++ b/sources/engine/Stride/Graphics/DDSHelper.cs @@ -1070,7 +1070,7 @@ public static unsafe void SaveToDDSStream(PixelBuffer[] pixelBuffers, int count, int pixsize = pixelBuffers[index].BufferStride; Debug.Assert((uint)pixsize <= buffer.Length); fixed (byte* pinned = buffer) { - Unsafe.CopyBlockUnaligned(pinned, source: (void*)pixelBuffers[index].DataPointer, (uint)pixsize); + Utilities.CopyWithAlignmentFallback(pinned, source: (void*)pixelBuffers[index].DataPointer, (uint)pixsize); } stream.Write(buffer, 0, pixsize); ++index; @@ -1146,7 +1146,7 @@ private static unsafe Image CreateImageFromDDS(IntPtr pDDS, int offset, int size if (metadata.Format.IsCompressed()) { - Unsafe.CopyBlockUnaligned((void*)pDest, (void*)pSrc, (uint)Math.Min(images[index].BufferStride, imagesDst[index].BufferStride)); + Utilities.CopyWithAlignmentFallback((void*)pDest, (void*)pSrc, (uint)Math.Min(images[index].BufferStride, imagesDst[index].BufferStride)); } else { @@ -1515,7 +1515,7 @@ internal static unsafe void CopyScanline(IntPtr pDestination, int outSize, IntPt if (pDestination == pSource) return; - Unsafe.CopyBlockUnaligned((void*)pDestination, source: (void*)pSource, (uint)Math.Min(outSize, inSize)); + Utilities.CopyWithAlignmentFallback((void*)pDestination, source: (void*)pSource, (uint)Math.Min(outSize, inSize)); } /// @@ -1628,7 +1628,7 @@ internal static unsafe void SwizzleScanline(IntPtr pDestination, int outSize, In if (pDestination == pSource) return; - Unsafe.CopyBlockUnaligned((void*)pDestination, source: (void*)pSource, (uint)Math.Min(outSize, inSize)); + Utilities.CopyWithAlignmentFallback((void*)pDestination, source: (void*)pSource, (uint)Math.Min(outSize, inSize)); } } diff --git a/sources/engine/Stride/Graphics/Image.cs b/sources/engine/Stride/Graphics/Image.cs index 4f9c568672..a6f38b2d64 100644 --- a/sources/engine/Stride/Graphics/Image.cs +++ b/sources/engine/Stride/Graphics/Image.cs @@ -195,7 +195,7 @@ public void Dispose() /// public unsafe void Clear() { - Unsafe.InitBlockUnaligned((void*)buffer, 0, (uint)totalSizeInBytes); + Utilities.Clear((void*)buffer, (uint)totalSizeInBytes); } /// diff --git a/sources/engine/Stride/Graphics/ImageHelper.cs b/sources/engine/Stride/Graphics/ImageHelper.cs index 814084e05d..59b0ad6e51 100644 --- a/sources/engine/Stride/Graphics/ImageHelper.cs +++ b/sources/engine/Stride/Graphics/ImageHelper.cs @@ -34,7 +34,7 @@ public static unsafe Image LoadFromMemory(IntPtr pSource, int size, bool makeACo if (makeACopy) { var buffer = Utilities.AllocateMemory(size); - Unsafe.CopyBlockUnaligned((void*)buffer, source: (void*)pSource, (uint)size); + Utilities.CopyWithAlignmentFallback((void*)buffer, source: (void*)pSource, (uint)size); pSource = buffer; makeACopy = false; } diff --git a/sources/engine/Stride/Graphics/PixelBuffer.cs b/sources/engine/Stride/Graphics/PixelBuffer.cs index 3276ebc864..9875707bf3 100644 --- a/sources/engine/Stride/Graphics/PixelBuffer.cs +++ b/sources/engine/Stride/Graphics/PixelBuffer.cs @@ -150,7 +150,7 @@ public unsafe void CopyTo(PixelBuffer pixelBuffer) // If buffers have same size, than we can copy it directly if (this.BufferStride == pixelBuffer.BufferStride) { - Unsafe.CopyBlockUnaligned((void*)pixelBuffer.DataPointer, source: (void*)DataPointer, (uint)BufferStride); + Utilities.CopyWithAlignmentFallback((void*)pixelBuffer.DataPointer, source: (void*)DataPointer, (uint)BufferStride); } else { @@ -161,7 +161,7 @@ public unsafe void CopyTo(PixelBuffer pixelBuffer) // Copy per scanline for (int i = 0; i < Height; i++) { - Unsafe.CopyBlockUnaligned(dstPointer, srcPointer, (uint)rowStride); + Utilities.CopyWithAlignmentFallback(dstPointer, srcPointer, (uint)rowStride); srcPointer += this.RowStride; dstPointer += pixelBuffer.RowStride; } diff --git a/sources/engine/Stride/Graphics/StandardImageHelper.Android.cs b/sources/engine/Stride/Graphics/StandardImageHelper.Android.cs index 09e593c723..0c6ac2e581 100644 --- a/sources/engine/Stride/Graphics/StandardImageHelper.Android.cs +++ b/sources/engine/Stride/Graphics/StandardImageHelper.Android.cs @@ -102,7 +102,7 @@ private static void SaveFromMemory(PixelBuffer[] pixelBuffers, int count, ImageD } else if (description.Format == PixelFormat.B8G8R8A8_UNorm || description.Format == PixelFormat.B8G8R8A8_UNorm_SRgb) { - Unsafe.CopyBlockUnaligned((void*)pixelData, (void*)pSrc, (uint)sizeToCopy); + Utilities.CopyWithAlignmentFallback((void*)pixelData, (void*)pSrc, (uint)sizeToCopy); } else { diff --git a/sources/engine/Stride/Graphics/StandardImageHelper.Windows.cs b/sources/engine/Stride/Graphics/StandardImageHelper.Windows.cs index af10ec64ac..37750c0be2 100644 --- a/sources/engine/Stride/Graphics/StandardImageHelper.Windows.cs +++ b/sources/engine/Stride/Graphics/StandardImageHelper.Windows.cs @@ -34,7 +34,7 @@ public static unsafe Image LoadFromMemory(IntPtr pSource, int size, bool makeACo // Directly load image as RGBA instead of BGRA, because OpenGL ES devices don't support it out of the box (extension). //image.Description.Format = PixelFormat.R8G8B8A8_UNorm; //CopyMemoryBGRA(image.PixelBuffer[0].DataPointer, bitmapData.Scan0, image.PixelBuffer[0].BufferStride); - Unsafe.CopyBlockUnaligned((void*)image.PixelBuffer[0].DataPointer, (void*)bitmapData.Scan0, (uint)image.PixelBuffer[0].BufferStride); + Utilities.CopyWithAlignmentFallback((void*)image.PixelBuffer[0].DataPointer, (void*)bitmapData.Scan0, (uint)image.PixelBuffer[0].BufferStride); } finally { @@ -97,7 +97,7 @@ private static unsafe void SaveFromMemory(PixelBuffer[] pixelBuffers, int count, } else if (format == PixelFormat.B8G8R8A8_UNorm || format == PixelFormat.B8G8R8A8_UNorm_SRgb) { - Unsafe.CopyBlockUnaligned((void*)bitmapData.Scan0, (void*)pixelBuffers[0].DataPointer, (uint)pixelBuffers[0].BufferStride); + Utilities.CopyWithAlignmentFallback((void*)bitmapData.Scan0, (void*)pixelBuffers[0].DataPointer, (uint)pixelBuffers[0].BufferStride); } else if (format == PixelFormat.R8_UNorm || format == PixelFormat.A8_UNorm) { diff --git a/sources/engine/Stride/Rendering/ParameterCollection.cs b/sources/engine/Stride/Rendering/ParameterCollection.cs index fa8c7cf7dd..4b5d605a79 100644 --- a/sources/engine/Stride/Rendering/ParameterCollection.cs +++ b/sources/engine/Stride/Rendering/ParameterCollection.cs @@ -78,13 +78,16 @@ public unsafe ParameterCollection(ParameterCollection parameterCollection) if (parameterCollection.DataValues != null) { if (parameterCollection.DataValues.Length == 0) + { DataValues = []; - else { + } + else + { DataValues = new byte[parameterCollection.DataValues.Length]; fixed (byte* dataValuesSources = parameterCollection.DataValues) fixed (byte* dataValuesDest = DataValues) { - Unsafe.CopyBlockUnaligned(dataValuesDest, dataValuesSources, (uint)DataValues.Length); + Utilities.CopyWithAlignmentFallback(dataValuesDest, dataValuesSources, (uint)DataValues.Length); } } } @@ -322,14 +325,18 @@ public unsafe T[] GetValues(ValueParameterKey key) where T : struct var stride = Align(Unsafe.SizeOf()); var values = new T[parameter.Count]; - ref var data = ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(DataValues), parameter.Offset); - for (int i = 0; i < values.Length; ++i) + fixed (byte* dataValues = DataValues) { - values[i] = Unsafe.ReadUnaligned(ref data); - data = ref Unsafe.Add(ref data, stride); - } + var dataPtr = dataValues + parameter.Offset; - return values; + for (int i = 0; i < values.Length; ++i) + { + values[i] = Unsafe.Read(dataPtr); + dataPtr += stride; + } + + return values; + } } /// @@ -357,7 +364,7 @@ public unsafe void CopyTo(ValueParameterKey key, ParameterCollection desti fixed (byte* sourceDataValues = DataValues) fixed (byte* destDataValues = destination.DataValues) { - Unsafe.CopyBlockUnaligned( + Utilities.CopyWithAlignmentFallback( destination: destDataValues + destParameter.Offset, source: sourceDataValues + sourceParameter.Offset, (uint)sizeInBytes); @@ -371,7 +378,10 @@ public unsafe void CopyTo(ValueParameterKey key, ParameterCollection desti /// /// public unsafe void Set(ValueParameter parameter, T value) where T : struct - => Unsafe.WriteUnaligned(ref DataValues[parameter.Offset], value); + { + fixed (void* ptr = &DataValues[parameter.Offset]) + Unsafe.Write(ptr, value); + } /// /// Sets a blittable value. @@ -380,7 +390,10 @@ public unsafe void Set(ValueParameter parameter, T value) where T : struct /// /// public unsafe void Set(ValueParameter parameter, ref T value) where T : struct - => Unsafe.WriteUnaligned(ref DataValues[parameter.Offset], value); + { + fixed (void* ptr = &DataValues[parameter.Offset]) + Unsafe.Write(ptr, value); + } /// /// Sets blittable values. @@ -399,11 +412,15 @@ public unsafe void Set(ValueParameter parameter, int count, ref T firstVal throw new IndexOutOfRangeException(); } - ref var data = ref DataValues[parameter.Offset]; - for (var i = 0; i < count; i++) + fixed (byte* dataValues = DataValues) { - Unsafe.WriteUnaligned(ref data, Unsafe.Add(ref firstValue, i)); - data = ref Unsafe.Add(ref data, stride); + var dataPtr = dataValues + parameter.Offset; + + for (int i = 0; i < count; ++i) + { + Unsafe.Write(dataPtr, Unsafe.Add(ref firstValue, i)); + dataPtr += stride; + } } } @@ -446,7 +463,10 @@ public void Set(ObjectParameterAccessor parameterAccessor, T value) /// /// public unsafe T Get(ValueParameter parameter) where T : struct - => Unsafe.ReadUnaligned(ref DataValues[parameter.Offset]); + { + fixed (void* ptr = &DataValues[parameter.Offset]) + return Unsafe.Read(ptr); + } /// /// Gets a permutation. @@ -802,7 +822,7 @@ public unsafe void Copy() { fixed (byte* destDataValues = destination.DataValues) fixed (byte* sourceDataValues = source.DataValues) - Unsafe.CopyBlockUnaligned( + Utilities.CopyWithAlignmentFallback( destination: destDataValues + range.DestStart, source: sourceDataValues + range.SourceStart, byteCount: (uint)range.Size); @@ -815,7 +835,7 @@ private unsafe void PerformFastCopy(ParameterCollectionLayout destinationLayout) { fixed (byte* destPtr = destination.DataValues) fixed (byte* sourcePtr = source.DataValues) - Unsafe.CopyBlockUnaligned(destPtr, sourcePtr, (uint)destinationLayout.BufferSize); + Utilities.CopyWithAlignmentFallback(destPtr, sourcePtr, (uint)destinationLayout.BufferSize); var resourceCount = destinationLayout.ResourceCount; for (int i = 0; i < resourceCount; ++i) diff --git a/sources/tools/Stride.Importer.3D/MeshConverter.cs b/sources/tools/Stride.Importer.3D/MeshConverter.cs index e7e64621ff..83a7529dc1 100644 --- a/sources/tools/Stride.Importer.3D/MeshConverter.cs +++ b/sources/tools/Stride.Importer.3D/MeshConverter.cs @@ -1157,7 +1157,7 @@ private unsafe void CreateTextureFile(Silk.NET.Assimp.Texture* texture, string p fixed (byte* bufferPointer = buffer) { var sourcePointer = (byte*)texture->PcData; - System.Runtime.CompilerServices.Unsafe.CopyBlockUnaligned(bufferPointer, sourcePointer, arraySize); + Core.Utilities.CopyWithAlignmentFallback(bufferPointer, sourcePointer, arraySize); } System.IO.File.WriteAllBytes(path, buffer); } diff --git a/sources/tools/Stride.TextureConverter/Backend/TexLibraries/ArrayTexLib.cs b/sources/tools/Stride.TextureConverter/Backend/TexLibraries/ArrayTexLib.cs index 9c4604ec1b..cdd9a3d186 100644 --- a/sources/tools/Stride.TextureConverter/Backend/TexLibraries/ArrayTexLib.cs +++ b/sources/tools/Stride.TextureConverter/Backend/TexLibraries/ArrayTexLib.cs @@ -2,6 +2,7 @@ // Distributed under the MIT license. See the LICENSE.md file in the project root for more information. using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using Stride.Core; using Stride.Core.Diagnostics; using Stride.Graphics; using Stride.TextureConverter.Requests; @@ -124,7 +125,7 @@ private unsafe void Create(TexImage array, ArrayCreationRequest request) current = request.TextureList[i]; buffer = arrayData + offset1; offset1 += current.DataSize; - Unsafe.CopyBlockUnaligned((void*)buffer, (void*)current.Data, (uint)current.DataSize); + Utilities.CopyWithAlignmentFallback((void*)buffer, (void*)current.Data, (uint)current.DataSize); offset2 = 0; currentData = buffer; @@ -258,7 +259,7 @@ private unsafe void Update(TexImage array, ArrayUpdateRequest request) for (int i = 0; i < subImageCount; ++i) { - Unsafe.CopyBlockUnaligned( + Utilities.CopyWithAlignmentFallback( destination: (void*)array.SubImageArray[indice].Data, source: (void*)request.Texture.SubImageArray[i].Data, byteCount: (uint)request.Texture.SubImageArray[i].DataSize); @@ -301,7 +302,7 @@ private unsafe void Insert(TexImage array, ArrayInsertionRequest request) { subImages[i] = array.SubImageArray[i]; subImages[i].Data = bufferData + offset; - Unsafe.CopyBlockUnaligned((void*)subImages[i].Data, (void*)array.SubImageArray[i].Data, (uint)array.SubImageArray[i].DataSize); + Utilities.CopyWithAlignmentFallback((void*)subImages[i].Data, (void*)array.SubImageArray[i].Data, (uint)array.SubImageArray[i].DataSize); offset += array.SubImageArray[i].DataSize; } @@ -310,7 +311,7 @@ private unsafe void Insert(TexImage array, ArrayInsertionRequest request) for (int i = 0; i < subImageCount; ++i) { subImages[ct] = request.Texture.SubImageArray[i]; - Unsafe.CopyBlockUnaligned((void*)subImages[ct].Data, (void*)request.Texture.SubImageArray[i].Data, (uint)request.Texture.SubImageArray[i].DataSize); + Utilities.CopyWithAlignmentFallback((void*)subImages[ct].Data, (void*)request.Texture.SubImageArray[i].Data, (uint)request.Texture.SubImageArray[i].DataSize); offset += request.Texture.SubImageArray[i].DataSize; ++ct; } @@ -320,7 +321,7 @@ private unsafe void Insert(TexImage array, ArrayInsertionRequest request) { subImages[ct] = array.SubImageArray[i]; subImages[ct].Data = bufferData + offset; - Unsafe.CopyBlockUnaligned((void*)subImages[ct].Data, (void*)array.SubImageArray[i].Data, (uint)array.SubImageArray[i].DataSize); + Utilities.CopyWithAlignmentFallback((void*)subImages[ct].Data, (void*)array.SubImageArray[i].Data, (uint)array.SubImageArray[i].DataSize); offset += array.SubImageArray[i].DataSize; ++ct; } @@ -368,7 +369,7 @@ private unsafe void Remove(TexImage array, ArrayElementRemovalRequest request) { subImages[i] = array.SubImageArray[i]; subImages[i].Data = buffer + offset; - Unsafe.CopyBlockUnaligned((void*)subImages[i].Data, (void*)array.SubImageArray[i].Data, (uint)array.SubImageArray[i].DataSize); + Utilities.CopyWithAlignmentFallback((void*)subImages[i].Data, (void*)array.SubImageArray[i].Data, (uint)array.SubImageArray[i].DataSize); offset += array.SubImageArray[i].DataSize; } @@ -376,7 +377,7 @@ private unsafe void Remove(TexImage array, ArrayElementRemovalRequest request) { subImages[indice] = array.SubImageArray[i]; subImages[indice].Data = buffer + offset; - Unsafe.CopyBlockUnaligned((void*)subImages[indice].Data, (void*)array.SubImageArray[i].Data, (uint)array.SubImageArray[i].DataSize); + Utilities.CopyWithAlignmentFallback((void*)subImages[indice].Data, (void*)array.SubImageArray[i].Data, (uint)array.SubImageArray[i].DataSize); offset += array.SubImageArray[i].DataSize; ++indice; } diff --git a/sources/tools/Stride.TextureConverter/Backend/TexLibraries/AtlasTexLibrary.cs b/sources/tools/Stride.TextureConverter/Backend/TexLibraries/AtlasTexLibrary.cs index 9fb0fb0503..0c2b5267e8 100644 --- a/sources/tools/Stride.TextureConverter/Backend/TexLibraries/AtlasTexLibrary.cs +++ b/sources/tools/Stride.TextureConverter/Backend/TexLibraries/AtlasTexLibrary.cs @@ -210,7 +210,7 @@ private unsafe void Update(TexAtlas atlas, AtlasUpdateRequest request) for (int j = 0; j < h; ++j) { - Unsafe.CopyBlockUnaligned( + Utilities.CopyWithAlignmentFallback( destination: (byte*)atlasData + j * atlas.SubImageArray[i].RowPitch + yOffset + xOffset, source: subImageData + j * request.Texture.SubImageArray[i].RowPitch, byteCount: (uint)request.Texture.SubImageArray[i].RowPitch); @@ -291,7 +291,7 @@ private unsafe void ExtractTexture(TexAtlas atlas, TexImage texture, TexAtlas.Te { srcPtr = atlasData + j * atlas.SubImageArray[i].RowPitch + yOffset + xOffset; destPtr = textureData + j * rowPitch; - Unsafe.CopyBlockUnaligned((void*)destPtr, (void*)srcPtr, (uint)rowPitch); + Utilities.CopyWithAlignmentFallback((void*)destPtr, (void*)srcPtr, (uint)rowPitch); } offset += slicePitch; @@ -554,7 +554,7 @@ private unsafe void CopyTexturesIntoAtlasMemory(Node node, TexAtlas atlas) { var destPtr = atlasData + j * atlas.SubImageArray[i].RowPitch + yOffset + xOffset; var srcPtr = textureData + j * node.Texture.SubImageArray[i].RowPitch; - Unsafe.CopyBlockUnaligned(destPtr, srcPtr, (uint)node.Texture.SubImageArray[i].RowPitch); + Utilities.CopyWithAlignmentFallback(destPtr, srcPtr, (uint)node.Texture.SubImageArray[i].RowPitch); } x = x <= 1 ? 0 : x >>= 1; diff --git a/sources/tools/Stride.TextureConverter/Backend/TexLibraries/FITexLib.cs b/sources/tools/Stride.TextureConverter/Backend/TexLibraries/FITexLib.cs index 26fb63cbfb..6fe0e8985e 100644 --- a/sources/tools/Stride.TextureConverter/Backend/TexLibraries/FITexLib.cs +++ b/sources/tools/Stride.TextureConverter/Backend/TexLibraries/FITexLib.cs @@ -115,7 +115,7 @@ public unsafe void EndLibrary(TexImage image) image.SubImageArray[i].RowPitch = rowPitch; image.SubImageArray[i].SlicePitch = slicePitch; - Unsafe.CopyBlockUnaligned((void*)image.SubImageArray[i].Data, (void*)FreeImage.GetBits(libraryData.Bitmaps[i]), (uint)size); + Utilities.CopyWithAlignmentFallback((void*)image.SubImageArray[i].Data, (void*)FreeImage.GetBits(libraryData.Bitmaps[i]), (uint)size); offset += size; } } diff --git a/sources/tools/Stride.TextureConverter/Backend/TexLibraries/PvrttTexLib.cs b/sources/tools/Stride.TextureConverter/Backend/TexLibraries/PvrttTexLib.cs index fc14fbd580..ce1938c449 100644 --- a/sources/tools/Stride.TextureConverter/Backend/TexLibraries/PvrttTexLib.cs +++ b/sources/tools/Stride.TextureConverter/Backend/TexLibraries/PvrttTexLib.cs @@ -134,7 +134,7 @@ public unsafe void StartLibrary(TexImage image) { for (uint k = 0; k < image.MipmapCount; ++k) { - Unsafe.CopyBlockUnaligned( + Core.Utilities.CopyWithAlignmentFallback( (void*)libraryData.Texture.GetDataPtr(k, j, i), (void*)image.SubImageArray[imageCount].Data, (uint)(image.SubImageArray[imageCount].DataSize * depth)); @@ -405,7 +405,7 @@ private unsafe void Export(TexImage image, PvrTextureLibraryData libraryData, Ex { for (uint k = 0; k < newMipMapCount; ++k) { - Unsafe.CopyBlockUnaligned( + Core.Utilities.CopyWithAlignmentFallback( destination: (void*)texture.GetDataPtr(k, j, i), source: (void*)libraryData.Texture.GetDataPtr(k, j, i), byteCount: libraryData.Header.GetDataSize((int)k, false, false)); @@ -556,14 +556,14 @@ private unsafe void TransposeFaceData(TexImage image, PvrTextureLibraryData libr var source = (byte*)image.Data + sourceOffset; var dest = temporaryBuffer + destOffset; - Unsafe.CopyBlockUnaligned(dest, source, slice); + Core.Utilities.CopyWithAlignmentFallback(dest, source, slice); } sourceRowOffset += checked((int)(slice * (uint)image.FaceCount)); } // Copy data back to the library - Unsafe.CopyBlockUnaligned( + Core.Utilities.CopyWithAlignmentFallback( destination: (void*)libraryData.Texture.GetDataPtr(), source: temporaryBuffer, byteCount: (uint)image.DataSize); diff --git a/sources/tools/Stride.TextureConverter/Backend/TexLibraries/StrideTexLibrary.cs b/sources/tools/Stride.TextureConverter/Backend/TexLibraries/StrideTexLibrary.cs index 5794de6744..9d72f2cf1b 100644 --- a/sources/tools/Stride.TextureConverter/Backend/TexLibraries/StrideTexLibrary.cs +++ b/sources/tools/Stride.TextureConverter/Backend/TexLibraries/StrideTexLibrary.cs @@ -210,7 +210,7 @@ private unsafe void Export(TexImage image, StrideTextureLibraryData libraryDataf { for (int j = 0; j < ct; ++j) { - Unsafe.CopyBlockUnaligned( + Utilities.CopyWithAlignmentFallback( (void*)sdImage.PixelBuffer[ct2].DataPointer, (void*)sdImage.PixelBuffer[j + i * SubImagePerArrayElement].DataPointer, (uint)sdImage.PixelBuffer[j + i * SubImagePerArrayElement].BufferStride); @@ -268,7 +268,7 @@ private unsafe void Export(TexImage image, StrideTextureLibraryData libraryDataf for (int i = 0; i < image.ArraySize * newMipMapCount; ++i) { if (i == newMipMapCount || (i > newMipMapCount && (i % newMipMapCount == 0))) j += gap; - Unsafe.CopyBlockUnaligned((void*)sdImage.PixelBuffer[i].DataPointer, (void*)image.SubImageArray[j].Data, (uint)image.SubImageArray[j].DataSize); + Utilities.CopyWithAlignmentFallback((void*)sdImage.PixelBuffer[i].DataPointer, (void*)image.SubImageArray[j].Data, (uint)image.SubImageArray[j].DataSize); ++j; } } @@ -305,7 +305,7 @@ private unsafe void Export(TexImage image, StrideTextureLibraryData libraryDataf throw new InvalidOperationException("Image size different than expected."); } - Unsafe.CopyBlockUnaligned((void*)sdImage.DataPointer, (void*)image.Data, (uint)image.DataSize); + Utilities.CopyWithAlignmentFallback((void*)sdImage.DataPointer, (void*)image.Data, (uint)image.DataSize); } using (var fileStream = new FileStream(request.FilePath, FileMode.Create, FileAccess.Write)) @@ -367,7 +367,7 @@ private unsafe void ExportToStride(TexImage image, StrideTextureLibraryData libr throw new InvalidOperationException("Image size different than expected."); } - Unsafe.CopyBlockUnaligned((void*)sdImage.DataPointer, (void*)image.Data, (uint)image.DataSize); + Utilities.CopyWithAlignmentFallback((void*)sdImage.DataPointer, (void*)image.Data, (uint)image.DataSize); request.XkImage = sdImage; } diff --git a/sources/tools/Stride.TextureConverter/Backend/Wrappers/DxtNetWrapper.cs b/sources/tools/Stride.TextureConverter/Backend/Wrappers/DxtNetWrapper.cs index 24b0718709..d1d234e34a 100644 --- a/sources/tools/Stride.TextureConverter/Backend/Wrappers/DxtNetWrapper.cs +++ b/sources/tools/Stride.TextureConverter/Backend/Wrappers/DxtNetWrapper.cs @@ -935,7 +935,7 @@ internal static int GetAlphaDepth(String filePath) fixed (byte* ptr = buffer) { DDSHeaderDX9* headerPtr = &header; - Unsafe.CopyBlockUnaligned(headerPtr, ptr, (uint)headerSize); + Stride.Core.Utilities.CopyWithAlignmentFallback(headerPtr, ptr, (uint)headerSize); } if (header.dwMagic != 0x20534444 || header.dwPfSize != 32) return -1; diff --git a/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/Classes/MemoryArray.cs b/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/Classes/MemoryArray.cs index 95d06e65c1..e2c74269a0 100644 --- a/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/Classes/MemoryArray.cs +++ b/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/Classes/MemoryArray.cs @@ -6,6 +6,7 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; +using Stride.Core; namespace FreeImageAPI { @@ -247,7 +248,7 @@ private T GetValueInternal(int index) return (T)(object)(FI4BIT)(((index % 2) == 0) ? (baseAddress[index / 2] >> 4) : (baseAddress[index / 2] & 0x0F)); } - Unsafe.CopyBlockUnaligned(ptr, baseAddress + (index * size), (uint) size); + Utilities.CopyWithAlignmentFallback(ptr, baseAddress + (index * size), (uint) size); return buffer[0]; } @@ -297,7 +298,7 @@ private void SetValueInternal(T value, int index) else { buffer[0] = value; - Unsafe.CopyBlockUnaligned(baseAddress + (index * size), ptr, (uint) size); + Utilities.CopyWithAlignmentFallback(baseAddress + (index * size), ptr, (uint) size); } } @@ -337,7 +338,7 @@ public T[] GetValues(int index, int length) { ref byte dst = ref Unsafe.As(ref data[0]); ref byte src = ref Unsafe.AsRef(baseAddress + (size * index)); - Unsafe.CopyBlockUnaligned(ref dst, ref src, (uint) (size * length)); + Utilities.CopyWithAlignmentFallback(ref dst, ref src, (uint) (size * length)); } return data; } @@ -381,7 +382,7 @@ public void SetValues(T[] values, int index) { ref byte dst = ref Unsafe.AsRef(baseAddress + (index * size)); ref byte src = ref Unsafe.As(ref values[0]); - Unsafe.CopyBlockUnaligned(ref dst, ref src, (uint) (size * length)); + Utilities.CopyWithAlignmentFallback(ref dst, ref src, (uint) (size * length)); } } @@ -450,7 +451,7 @@ public void CopyTo(T[] array, int sourceIndex, int destinationIndex, int length) { ref byte dst = ref Unsafe.As(ref array[destinationIndex]); ref byte src = ref Unsafe.AsRef(baseAddress + (size * sourceIndex)); - Unsafe.CopyBlockUnaligned(ref dst, ref src, (uint) (size * length)); + Utilities.CopyWithAlignmentFallback(ref dst, ref src, (uint) (size * length)); } } @@ -493,7 +494,7 @@ public void CopyFrom(T[] array, int sourceIndex, int destinationIndex, int lengt { ref byte dst = ref Unsafe.AsRef(baseAddress + (size * destinationIndex)); ref byte src = ref Unsafe.As(ref array[sourceIndex]); - Unsafe.CopyBlockUnaligned(ref dst, ref src, (uint) (size * length)); + Utilities.CopyWithAlignmentFallback(ref dst, ref src, (uint) (size * length)); } } @@ -520,7 +521,7 @@ public byte[] ToByteArray() ref byte dst = ref result[0]; ref byte src = ref Unsafe.AsRef(baseAddress); - Unsafe.CopyBlockUnaligned(ref dst, ref src, (uint) result.Length); + Utilities.CopyWithAlignmentFallback(ref dst, ref src, (uint) result.Length); return result; } diff --git a/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/Classes/MetadataTag.cs b/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/Classes/MetadataTag.cs index 532374e88a..24907ce8df 100644 --- a/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/Classes/MetadataTag.cs +++ b/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/Classes/MetadataTag.cs @@ -39,6 +39,7 @@ using System.Runtime.CompilerServices; using System.Collections.Generic; using System.Diagnostics; +using Stride.Core; namespace FreeImageAPI.Metadata { @@ -412,7 +413,7 @@ public object Value ref byte dst = ref MemoryMarshal.GetArrayDataReference(array); ref byte src = ref Unsafe.AsRef((void*) FreeImage.GetTagValue(tag)); - Unsafe.CopyBlockUnaligned(ref dst, ref src, Length); + Utilities.CopyWithAlignmentFallback(ref dst, ref src, Length); return array; } @@ -532,7 +533,7 @@ private unsafe bool SetArrayValue(object value, FREE_IMAGE_MDTYPE type) ref byte dst = ref data[0]; ref byte src = ref MemoryMarshal.GetArrayDataReference(array); - Unsafe.CopyBlockUnaligned(ref dst, ref src, Length); + Utilities.CopyWithAlignmentFallback(ref dst, ref src, Length); } return FreeImage.SetTagValue(tag, data); @@ -627,7 +628,7 @@ public unsafe PropertyItem GetPropertyItem() ref byte dst = ref item.Value[0]; ref byte src = ref Unsafe.AsRef((void*) FreeImage.GetTagValue(tag)); - Unsafe.CopyBlockUnaligned(ref dst, ref src, Length); + Utilities.CopyWithAlignmentFallback(ref dst, ref src, Length); return item; } diff --git a/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/Classes/Palette.cs b/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/Classes/Palette.cs index 1f5adf6fca..0eabacfbe0 100644 --- a/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/Classes/Palette.cs +++ b/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/Classes/Palette.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using FreeImageAPI.Metadata; +using Stride.Core; namespace FreeImageAPI { @@ -397,7 +398,7 @@ public void Load(BinaryReader reader) ref byte dst = ref Unsafe.AsRef(baseAddress); ref byte src = ref data[0]; - Unsafe.CopyBlockUnaligned(ref dst, ref src, (uint) data.Length); + Utilities.CopyWithAlignmentFallback(ref dst, ref src, (uint) data.Length); } } diff --git a/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/FreeImageWrapper.cs b/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/FreeImageWrapper.cs index e28a0fed36..9dbbc21a4a 100644 --- a/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/FreeImageWrapper.cs +++ b/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/FreeImageWrapper.cs @@ -44,7 +44,7 @@ using System.Runtime.InteropServices; using FreeImageAPI.IO; using FreeImageAPI.Metadata; - +using Stride.Core; using StridePixelFormat = Stride.Graphics.PixelFormat; namespace FreeImageAPI @@ -630,7 +630,7 @@ public static unsafe FIBITMAP ConvertFromRawBits( ref byte dst = ref Unsafe.AsRef((byte*) GetScanLine(dib, i)); ref byte src = ref Unsafe.AsRef(addr); - Unsafe.CopyBlockUnaligned(ref dst, ref src, GetLine(dib)); + Utilities.CopyWithAlignmentFallback(ref dst, ref src, GetLine(dib)); addr += pitch; } @@ -642,7 +642,7 @@ public static unsafe FIBITMAP ConvertFromRawBits( ref byte dst = ref Unsafe.AsRef((byte*) GetScanLine(dib, i)); ref byte src = ref Unsafe.AsRef(addr); - Unsafe.CopyBlockUnaligned(ref dst, ref src, GetLine(dib)); + Utilities.CopyWithAlignmentFallback(ref dst, ref src, GetLine(dib)); addr += pitch; } @@ -1963,7 +1963,7 @@ public static unsafe IntPtr GetHbitmap(FIBITMAP dib, IntPtr hdc, bool unload) // Copy the data into the dc ref byte dst = ref Unsafe.AsRef((void*) ppvBits); ref byte src = ref Unsafe.AsRef((void*) GetBits(dib)); - Unsafe.CopyBlockUnaligned(ref dst, ref src, GetHeight(dib) * GetPitch(dib)); + Utilities.CopyWithAlignmentFallback(ref dst, ref src, GetHeight(dib) * GetPitch(dib)); // Success: we unload the bitmap if (unload) @@ -2941,7 +2941,7 @@ public static unsafe byte[] GetTransparencyTableEx(FIBITMAP dib) ref byte dst = ref result[0]; ref byte src = ref Unsafe.AsRef((byte*) GetTransparencyTable(dib)); - Unsafe.CopyBlockUnaligned(ref dst, ref src, count); + Utilities.CopyWithAlignmentFallback(ref dst, ref src, count); return result; } @@ -3747,7 +3747,7 @@ static void CopyMemory(IntPtr dest, IntPtr src, int paletteColors) ref byte dstMemory = ref Unsafe.AsRef((void*) dest); ref byte srcMemory = ref Unsafe.AsRef((void*) src); - Unsafe.CopyBlockUnaligned(ref dstMemory, ref srcMemory, (uint) (paletteColors * sizeof(RGBQUAD))); + Utilities.CopyWithAlignmentFallback(ref dstMemory, ref srcMemory, (uint) (paletteColors * sizeof(RGBQUAD))); } } @@ -4466,7 +4466,7 @@ private static unsafe void CopyPalette(FIBITMAP src, FIBITMAP dst) ref byte dstPalleteBytes = ref Unsafe.AsRef((RGBQUAD*) GetPalette(dst)); ref byte srcPalleteBytes = ref Unsafe.AsRef((RGBQUAD*) GetPalette(src)); - Unsafe.CopyBlockUnaligned(ref dstPalleteBytes, ref srcPalleteBytes, size); + Utilities.CopyWithAlignmentFallback(ref dstPalleteBytes, ref srcPalleteBytes, size); } private static unsafe Scanline[] Get04BitScanlines(FIBITMAP dib) diff --git a/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/Structs/FIICCPROFILE.cs b/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/Structs/FIICCPROFILE.cs index cff7dc26de..7ee48a8c31 100644 --- a/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/Structs/FIICCPROFILE.cs +++ b/sources/tools/Stride.TextureConverter/Backend/Wrappers/FINetWrapper/Structs/FIICCPROFILE.cs @@ -36,6 +36,7 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using Stride.Core; namespace FreeImageAPI { @@ -106,7 +107,7 @@ public unsafe byte[] Data ref byte dst = ref result[0]; ref byte src = ref Unsafe.AsRef((void*) DataPointer); - Unsafe.CopyBlockUnaligned(ref dst, ref src, Size); + Utilities.CopyWithAlignmentFallback(ref dst, ref src, Size); return result; } diff --git a/sources/tools/Stride.TextureConverter/Frontend/TexImage.cs b/sources/tools/Stride.TextureConverter/Frontend/TexImage.cs index c56f361ee3..0b406b645f 100644 --- a/sources/tools/Stride.TextureConverter/Frontend/TexImage.cs +++ b/sources/tools/Stride.TextureConverter/Frontend/TexImage.cs @@ -280,7 +280,7 @@ public virtual unsafe object Clone(bool CopyMemory) Disposed = this.Disposed, }; - if (CopyMemory) Unsafe.CopyBlockUnaligned((void*)newTex.Data, (void*)Data, (uint)DataSize); + if (CopyMemory) Utilities.CopyWithAlignmentFallback((void*)newTex.Data, (void*)Data, (uint)DataSize); int offset = 0; for (int i = 0; i < this.SubImageArray.Length; ++i)