]> O.S.I.I.S - jp/vke.net.git/commitdiff
Memory<T> and Span<T> introduction
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sun, 31 May 2020 15:02:11 +0000 (17:02 +0200)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sun, 31 May 2020 15:02:11 +0000 (17:02 +0200)
Directory.Build.props
addons/CrowWindow/CrowWindow.csproj
addons/gltfLoader/glTFLoader.cs
samples/DistanceFieldFontTest/Program.cs
samples/Textured/main.cs
samples/crowWin/crowWin.csproj
samples/deferred/main.cs
vke/src/ExtensionMethods.cs
vke/src/StbImage.cs
vke/src/base/Image.cs
vke/vke.csproj

index b77bc6b5f5f3ed6c0f5b278ddf587577d7231843..a755d5ddd368ce8c066f84f6840163cf7e47d894 100644 (file)
@@ -7,13 +7,13 @@
                <VkeReleaseVersion>0.1.20</VkeReleaseVersion>
                <VkePackageVersion>$(VkeReleaseVersion)-beta</VkePackageVersion>
                <UseStbSharp>true</UseStbSharp>
-               <UseMemoryPools>true</UseMemoryPools>
+               <UseMemoryPools>false</UseMemoryPools>
                <LangVersion>7.2</LangVersion>
 
        </PropertyGroup>
        
        <PropertyGroup Condition=" '$(UseMemoryPools)' == 'true'">
-               <DefineConstants>$(DefineConstants);MEMORY_POOLS</DefineConstants>
+               <DefineConstants>$(DefineConstants);_MEMORY_POOLS</DefineConstants>
        </PropertyGroup>
        <PropertyGroup Condition=" '$(UseStbSharp)' == 'true'">
                <DefineConstants>$(DefineConstants);STB_SHARP</DefineConstants>
index 58bbead52d2a27d6eb5e86356d5437413988bbcc..a02a429aed3abdbd662067a9f4e77e65deeb8599 100644 (file)
@@ -17,7 +17,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Crow" Version="0.9.2-beta" />
+    <PackageReference Include="Crow" Version="0.9.0-beta" />
   </ItemGroup>
   <ItemGroup>
     <Compile Remove="main.cs" />
index ee4f940d7dece29e4793761a7996cfee949eaebb..cce4019ec211b68f119b06cc8f03906ee2f4b2a3 100644 (file)
@@ -16,6 +16,7 @@ using System.Linq;
 namespace vke.glTF {
        using static Vulkan.Utils;
        using static vke.Model;
+       using System.Runtime.CompilerServices;
 
        /// <summary>
        /// Loading context with I as the vertex index type (uint16,uint32)
@@ -76,8 +77,7 @@ namespace vke.glTF {
                public GL.Gltf gltf;
                public string baseDirectory;
 
-               public byte[][] loadedBuffers;
-               public GCHandle[] bufferHandles;
+               public Memory<byte>[] loadedBuffers;
 
                List<Mesh> meshes;
                string path;
@@ -88,8 +88,7 @@ namespace vke.glTF {
                        cmdPool = _cmdPool;
                        baseDirectory = Path.GetDirectoryName (path);
                        gltf = Interface.LoadModel (path);
-                       loadedBuffers = new byte [gltf.Buffers.Length] [];
-                       bufferHandles = new GCHandle [gltf.Buffers.Length];
+                       loadedBuffers = new Memory<byte> [gltf.Buffers.Length];
                }
 
                static byte[] loadDataUri (GL.Image img) {
@@ -102,7 +101,7 @@ namespace vke.glTF {
                }
 
                void ensureBufferIsLoaded (int bufferIdx) {
-                       if (loadedBuffers[bufferIdx] == null) {
+                       if (loadedBuffers[bufferIdx].IsEmpty) {
                                //load full buffer
                                string uri = gltf.Buffers[bufferIdx].Uri;
                                if (string.IsNullOrEmpty(uri))//glb
@@ -111,7 +110,6 @@ namespace vke.glTF {
                                        loadedBuffers[bufferIdx] = loadDataUri (gltf.Buffers[bufferIdx]);//TODO:check this func=>System.Buffers.Text.Base64.EncodeToUtf8InPlace
                                else
                                        loadedBuffers[bufferIdx] = File.ReadAllBytes (Path.Combine (baseDirectory, gltf.Buffers[bufferIdx].Uri));
-                               bufferHandles[bufferIdx] = GCHandle.Alloc (loadedBuffers[bufferIdx], GCHandleType.Pinned);
                        }
                }
 
@@ -159,10 +157,10 @@ namespace vke.glTF {
                                stagging.Map ();
 
                                unsafe {
-                                       byte* stagVertPtrInit = (byte*)stagging.MappedData.ToPointer ();
-                                       byte* stagIdxPtrInit = (byte*)(stagging.MappedData.ToPointer ()) + vertSize;
-                                       byte* stagVertPtr = stagVertPtrInit;
-                                       byte* stagIdxPtr = stagIdxPtrInit;
+
+                                       Span<byte> stagVertPtrInit = new Span<byte>(stagging.MappedData.ToPointer (), (int)vertSize);
+                                       Span<byte> stagIdxPtrInit = new Span<byte>((byte*)stagging.MappedData.ToPointer() + vertSize, (int)idxSize);
+                                       Span<byte> stagVertPtr = stagVertPtrInit, stagIdxPtr = stagIdxPtrInit;
 
                                        foreach (GL.Mesh mesh in gltf.Meshes) {
 
@@ -206,90 +204,92 @@ namespace vke.glTF {
                                                        prim.bb.isValid = true;
 
                                                        //Interleaving vertices
-                                                       byte * inPosPtr = null, inNormPtr = null, inUvPtr = null, inUv1Ptr = null;
+                                                       Span<byte> inPosPtr = Span<byte>.Empty, inNormPtr = Span<byte>.Empty, inUvPtr = Span<byte>.Empty, inUv1Ptr = Span<byte>.Empty;
 
                                                        GL.BufferView bv = gltf.BufferViews[(int)AccPos.BufferView];
-                                                       inPosPtr = (byte*)bufferHandles[bv.Buffer].AddrOfPinnedObject ().ToPointer ();
-                                                       inPosPtr += AccPos.ByteOffset + bv.ByteOffset;
+                                                       inPosPtr = loadedBuffers[bv.Buffer].Span.Slice (AccPos.ByteOffset + bv.ByteOffset);
 
                                                        if (AccNorm != null) {
                                                                bv = gltf.BufferViews[(int)AccNorm.BufferView];
-                                                               inNormPtr = (byte*)bufferHandles[bv.Buffer].AddrOfPinnedObject ().ToPointer ();
-                                                               inNormPtr += AccNorm.ByteOffset + bv.ByteOffset;
+                                                               inNormPtr = loadedBuffers[bv.Buffer].Span.Slice (AccNorm.ByteOffset + bv.ByteOffset);
                                                        }
                                                        if (AccUv != null) {
                                                                bv = gltf.BufferViews[(int)AccUv.BufferView];
-                                                               inUvPtr = (byte*)bufferHandles[bv.Buffer].AddrOfPinnedObject ().ToPointer ();
-                                                               inUvPtr += AccUv.ByteOffset + bv.ByteOffset;
+                                                               inUvPtr = loadedBuffers[bv.Buffer].Span.Slice (AccUv.ByteOffset + bv.ByteOffset);
                                                        }
                                                        if (AccUv1 != null) {
                                                                bv = gltf.BufferViews[(int)AccUv1.BufferView];
-                                                               inUv1Ptr = (byte*)bufferHandles[bv.Buffer].AddrOfPinnedObject ().ToPointer ();
-                                                               inUv1Ptr += AccUv1.ByteOffset + bv.ByteOffset;
+                                                               inUv1Ptr = loadedBuffers[bv.Buffer].Span.Slice (AccUv1.ByteOffset + bv.ByteOffset);
                                                        }
 
                                                        //TODO: use vertex attributes scan for copying data if they exists
                                                        for (int j = 0; j < prim.vertexCount; j++) {
-                                                               System.Buffer.MemoryCopy (inPosPtr, stagVertPtr, 12, 12);
-                                                               inPosPtr += 12;
-                                                               if (inNormPtr != null) {
-                                                                       System.Buffer.MemoryCopy (inNormPtr, stagVertPtr + 12, 12, 12);
-                                                                       inNormPtr += 12;
+                                                               inPosPtr.Slice (0, 12).CopyTo (stagVertPtr);
+                                                               inPosPtr = inPosPtr.Slice(12);
+                                                               if (!inNormPtr.IsEmpty) {
+                                                                       inNormPtr.Slice (0, 12).CopyTo (stagVertPtr.Slice (12));
+                                                                       inNormPtr = inNormPtr.Slice (12);
                                                                }
                                                                if (inUvPtr != null) {
-                                                                       System.Buffer.MemoryCopy (inUvPtr, stagVertPtr + 24, 8, 8);
-                                                                       inUvPtr += 8;
+                                                                       inUvPtr.Slice (0, 8).CopyTo (stagVertPtr.Slice (24));
+                                                                       inUvPtr = inUvPtr.Slice (8);
                                                                }
                                                                if (inUv1Ptr != null) {
-                                                                       System.Buffer.MemoryCopy (inUv1Ptr, stagVertPtr + 32, 8, 8);
-                                                                       inUv1Ptr += 8;
+                                                                       inUv1Ptr.Slice (0, 8).CopyTo (stagVertPtr.Slice (32));
+                                                                       inUv1Ptr = inUvPtr.Slice (8);
                                                                }
-                                                               stagVertPtr += vertexByteSize;
+                                                               stagVertPtr = stagVertPtr.Slice (vertexByteSize);
                                                        }
 
+                                                       /*Span<byte> s = stagVertPtrInit;
+                                                       for (int i = 0; i < s.Length; i++)
+                                                               Console.Write (s[i].ToString ("X2") + (i % 32 == 0 ? "\n" : " "));*/
+
+
                                                        //indices loading
                                                        if (p.Indices != null) {
                                                                GL.Accessor acc = gltf.Accessors[(int)p.Indices];
                                                                bv = gltf.BufferViews[(int)acc.BufferView];
 
-                                                               byte* inIdxPtr = (byte*)bufferHandles[bv.Buffer].AddrOfPinnedObject ().ToPointer ();
-                                                               inIdxPtr += acc.ByteOffset + bv.ByteOffset;
+                                                               Span<byte> inIdxPtr = loadedBuffers[bv.Buffer].Span.Slice (acc.ByteOffset + bv.ByteOffset);
 
                                                                //TODO:double check this, I dont seems to increment stag pointer
                                                                if (acc.ComponentType == GL.Accessor.ComponentTypeEnum.UNSIGNED_SHORT) {
                                                                        if (indexType == VkIndexType.Uint16) {
-                                                                               System.Buffer.MemoryCopy (inIdxPtr, stagIdxPtr, (long)acc.Count * 2, (long)acc.Count * 2);
-                                                                               stagIdxPtr += (long)acc.Count * 2;
+                                                                               inIdxPtr.Slice (0, acc.Count * 2).CopyTo (stagIdxPtr);
+                                                                               stagIdxPtr = stagIdxPtr.Slice (acc.Count * 2);
                                                                        } else {
-                                                                               uint* usPtr = (uint*)stagIdxPtr;
-                                                                               ushort* inPtr = (ushort*)inIdxPtr;
-                                                                               for (int i = 0; i < acc.Count; i++) 
-                                                                                       usPtr[i] = inPtr[i];                                                                            
-                                                                               stagIdxPtr += (long)acc.Count * 4;
+
+                                                                               Span<uint> usPtr = MemoryMarshal.Cast<byte, uint> (stagIdxPtr);
+                                                                               Span<ushort> inPtr = MemoryMarshal.Cast < byte, ushort> (inIdxPtr);
+                                                                               for (int i = 0; i < acc.Count; i++)
+                                                                                       usPtr[i] = inPtr[i];
+                                                                               stagIdxPtr = stagIdxPtr.Slice (acc.Count * 4);
                                                                        }
                                                                } else if (acc.ComponentType == GL.Accessor.ComponentTypeEnum.UNSIGNED_INT) {
                                                                        if (indexType == VkIndexType.Uint32) {
-                                                                               System.Buffer.MemoryCopy (inIdxPtr, stagIdxPtr, (long)acc.Count * 4, (long)acc.Count * 4);
-                                                                               stagIdxPtr += (long)acc.Count * 4;
+                                                                               inIdxPtr.Slice (0, acc.Count * 4).CopyTo (stagIdxPtr);
+                                                                               stagIdxPtr = stagIdxPtr.Slice (acc.Count * 4);
                                                                        } else {
-                                                                               ushort* usPtr = (ushort*)stagIdxPtr;
-                                                                               uint* inPtr = (uint*)inIdxPtr;
+                                                                               Span<ushort> usPtr = MemoryMarshal.Cast<byte, ushort> (stagIdxPtr);
+                                                                               Span<uint> inPtr = MemoryMarshal.Cast<byte, uint> (inIdxPtr);
+
                                                                                for (int i = 0; i < acc.Count; i++) 
                                                                                        usPtr[i] = (ushort)inPtr[i];
-                                                                               stagIdxPtr += (long)acc.Count * 2;
+                                                                               stagIdxPtr = stagIdxPtr.Slice (acc.Count * 2);
                                                                        }
                                                                } else if (acc.ComponentType == GL.Accessor.ComponentTypeEnum.UNSIGNED_BYTE) {
                                                                        //convert
                                                                        if (indexType == VkIndexType.Uint16) {
-                                                                               ushort* usPtr = (ushort*)stagIdxPtr;
+                                                                               Span<ushort> usPtr = MemoryMarshal.Cast<byte, ushort> (stagIdxPtr);
                                                                                for (int i = 0; i < acc.Count; i++)
                                                                                        usPtr[i] = (ushort)inIdxPtr[i];
-                                                                               stagIdxPtr += (long)acc.Count * 2;
+                                                                               stagIdxPtr = stagIdxPtr.Slice (acc.Count * 2);
                                                                        } else {
-                                                                               uint* usPtr = (uint*)stagIdxPtr;
+                                                                               Span<uint> usPtr = MemoryMarshal.Cast<byte, uint> (stagIdxPtr);
                                                                                for (int i = 0; i < acc.Count; i++)
                                                                                        usPtr[i] = (uint)inIdxPtr[i];
-                                                                               stagIdxPtr += (long)acc.Count * 4;
+                                                                               stagIdxPtr = stagIdxPtr.Slice (acc.Count * 4);
                                                                        }
                                                                } else
                                                                        throw new NotImplementedException ();
@@ -304,6 +304,10 @@ namespace vke.glTF {
                                                }
                                                meshes.Add (m);
                                        }
+
+                                       /*ReadOnlySpan<byte> tmp = new ReadOnlySpan<byte> (stagging.MappedData.ToPointer (), (int)size);
+                                       Memory<byte> mtmp = new Memory<byte> (tmp.ToArray());
+                                       mtmp.Dump();*/
                                }
 
                                stagging.Unmap ();
@@ -433,7 +437,7 @@ namespace vke.glTF {
                                if (img.BufferView != null) {//load image from gltf buffer view
                                        GL.BufferView bv = gltf.BufferViews[(int)img.BufferView];
                                        ensureBufferIsLoaded (bv.Buffer);
-                                       vkimg = Image.Load (dev, bufferHandles[bv.Buffer].AddrOfPinnedObject () + bv.ByteOffset, (ulong)bv.ByteLength, VkImageUsageFlags.TransferSrc);
+                                       vkimg = Image.Load (dev, loadedBuffers[bv.Buffer].Slice (bv.ByteOffset), (ulong)bv.ByteLength, VkImageUsageFlags.TransferSrc);
                                } else if (img.Uri.StartsWith ("data:", StringComparison.Ordinal)) {//load base64 encoded image
                                        Debug.WriteLine ("loading embedded image {0} : {1}", img.Name, img.MimeType);
                                        vkimg = Image.Load (dev, glTFLoader.loadDataUri (img), VkImageUsageFlags.TransferSrc);
@@ -515,11 +519,7 @@ namespace vke.glTF {
                                if (img.BufferView != null) {//load image from gltf buffer view
                                        GL.BufferView bv = gltf.BufferViews[(int)img.BufferView];
                                        ensureBufferIsLoaded (bv.Buffer);
-                                       if (Image.USE_STB_SHARP)
-                                               vkimg = Image.Load (dev, transferQ, cmdPool, loadedBuffers[bv.Buffer].Skip(bv.ByteOffset).Take(bv.ByteLength).ToArray());
-                                       else
-                                               vkimg = Image.Load (dev, transferQ, cmdPool, bufferHandles[bv.Buffer].AddrOfPinnedObject () + bv.ByteOffset, (ulong)bv.ByteLength);
-
+                                       vkimg = Image.Load (dev, transferQ, cmdPool, loadedBuffers[bv.Buffer].Slice (bv.ByteOffset, bv.ByteLength));
                                } else if (img.Uri.StartsWith ("data:", StringComparison.Ordinal)) {//load base64 encoded image
                                        Debug.WriteLine ("loading embedded image {0} : {1}", img.Name, img.MimeType);
                                        vkimg = Image.Load (dev, transferQ, cmdPool, glTFLoader.loadDataUri (img));
@@ -619,8 +619,8 @@ namespace vke.glTF {
                                }
 
                                for (int i = 0; i < gltf.Buffers.Length; i++) {
-                                       if (bufferHandles[i].IsAllocated)
-                                               bufferHandles[i].Free ();
+                                       //if (bufferHandles[i].IsAllocated)
+                                               //bufferHandles[i].Free ();
                                }
 
                                isDisposed = true;
index 906931d07490466e19aff68bcc1cae38a02daf0c..52b55e02ae73a13780a699ff2dca47d106a100d9 100644 (file)
@@ -6,6 +6,7 @@ using Glfw;
 using Vulkan;
 using vke;
 using vke.DistanceFieldFont;
+using Image = vke.Image;
 
 namespace DistanceFieldFontTest {
 
index 3206cca9643ce8d3dd00352d29cfa8eb779973d1..f2702d6e36e18ab43fb0eb58fe8eedb16d3c4c0d 100644 (file)
@@ -4,6 +4,7 @@ using System.Runtime.InteropServices;
 using Glfw;
 using vke;
 using Vulkan;
+using Image = vke.Image;
 
 namespace Textured {
        /// <summary>
index 04611c08bf0928c898066cacd96a3918ae77a221..50911273b26a5c6086769526d157b20bfdfcdc06 100644 (file)
@@ -3,7 +3,7 @@
                <IncludeDefaultNoneItems>false</IncludeDefaultNoneItems>
        </PropertyGroup>
        <ItemGroup>
-               <PackageReference Include="Crow" Version="0.8.11-beta" />
+               <PackageReference Include="Crow" Version="0.9.0-beta" />
        </ItemGroup>
        <ItemGroup>
 <!--           <GLSLShader Remove="shaders\**\*.frag;shaders\**\*.vert;shaders\**\*.comp;shaders\**\*.geom" />-->
index 7cdcc8c03c6b47d328428e0078fcfb9931469cbb..1e32c50a70afeb30006302f4217cb25e8bf4fd88 100644 (file)
@@ -66,6 +66,10 @@ namespace deferred {
                string[] modelPathes = {
                                //"/mnt/devel/vkPinball/data/models/pinball.gltf",
                                //"/mnt/devel/pinball.net/data/test.glb",
+                               //Utils.DataDirectory + "models/Box.gltf",
+                               //Utils.DataDirectory + "models/cubeOnPlane.glb",
+                               //Utils.DataDirectory + "models/shadow.glb",
+                               Utils.DataDirectory + "models/cube.gltf",
                                Utils.DataDirectory + "models/DamagedHelmet/glTF/DamagedHelmet.gltf",
                                //Utils.DataDirectory + "models/shadow.glb",
                                Utils.DataDirectory + "models/Hubble.glb",
index 6b1b0f73d5abe121c71d3a26986e7d74b225a920..589ae2a9bcdf5edacf6b4d23ccaa6066d8339cd2 100644 (file)
@@ -181,5 +181,14 @@ namespace vke {
                        }
                }
                #endregion
+
+               #region temp
+               public static void Dump (this Memory<byte> mem) {
+                       Span<byte> s = mem.Span;
+                       for (int i = 0; i < s.Length; i++) 
+                               Console.Write (s[i].ToString("X2") + (i % 32 == 0 ? "\n" : " "));
+               }
+               #endregion
+
        }
 }
index 1ae1e423dea1b025f2e3692d820fd5a24036f6f0..5da7534469c16617aa3d975849e874ebfa1b82de 100644 (file)
@@ -12,9 +12,12 @@ namespace vke {
         static extern IntPtr Load ([MarshalAs (UnmanagedType.LPStr)] string filename, out int x, out int y, out int channels_in_file, int desired_channels);
 
                [DllImport (stblib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load_from_memory")]
-        static extern IntPtr Load (IntPtr bitmap, int byteCount, out int x, out int y, out int channels_in_file, int desired_channels);        
+        static extern IntPtr Load (IntPtr bitmap, int byteCount, out int x, out int y, out int channels_in_file, int desired_channels);
 
-        [DllImport (stblib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_image_free")]
+               [DllImport (stblib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_load_from_memory")]
+               static extern IntPtr Load2 (ref byte bitmap, int byteCount, out int x, out int y, out int channels_in_file, int desired_channels);
+
+               [DllImport (stblib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_image_free")]
         static extern void FreeImage (IntPtr img);
 
                public readonly IntPtr Handle;
@@ -49,6 +52,18 @@ namespace vke {
                                Channels = requestedChannels;
                }
                /// <summary>
+               /// Open image with STBI library
+               /// </summary>
+               /// <param name="bitmap">raw bitmap datas</param>
+               /// <param name="requestedChannels">Force returned channels count, set 0 for original count</param>
+               public StbImage (Memory<byte> bitmap, int requestedChannels = 4) {
+                       Handle = StbImage.Load2 (ref MemoryMarshal.GetReference(bitmap.Span), bitmap.Length, out Width, out Height, out Channels, requestedChannels);
+                       if (Handle == IntPtr.Zero)
+                               throw new Exception ($"STBI image loading error.");
+                       if (requestedChannels > 0)
+                               Channels = requestedChannels;
+               }
+               /// <summary>
                /// copy pixels to destination.
                /// </summary>
                /// <param name="destPtr">Destination pointer.</param>
index 9b3905fe5d0c0b5b2dcdeb04f5ccae83a9b981dc..0b01b4605e5fa529a38b492b6197f4082cf424a8 100644 (file)
@@ -2,6 +2,7 @@
 //
 // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 using System;
+using System.Buffers;
 using System.Diagnostics;
 using Vulkan;
 
@@ -159,6 +160,77 @@ namespace vke {
                                return false;*/
                        return true;
                }
+               /// <summary>
+               /// Load image from byte array containing full image file (jpg, png,...)
+               /// </summary>
+               public static Image Load (Device dev, Queue staggingQ, CommandPool staggingCmdPool,
+                       Memory<byte> bitmap, VkFormat format = VkFormat.Undefined,
+                       VkMemoryPropertyFlags memoryProps = VkMemoryPropertyFlags.DeviceLocal,
+                       VkImageTiling tiling = VkImageTiling.Optimal, bool generateMipmaps = true,
+                       VkImageType imageType = VkImageType.Image2D,
+                       VkImageUsageFlags usage = VkImageUsageFlags.Sampled | VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst) {
+
+                       if (format == VkFormat.Undefined)
+                               format = DefaultTextureFormat;
+                       if (tiling == VkImageTiling.Optimal)
+                               usage |= VkImageUsageFlags.TransferDst;
+                       if (generateMipmaps)
+                               usage |= (VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst);
+                       /*#if STB_SHARP
+                                               StbImageSharp.ImageResult stbi = StbImageSharp.ImageResult.FromMemory (stream, StbImageSharp.ColorComponents.RedGreenBlueAlpha);
+                                               uint mipLevels = generateMipmaps ? ComputeMipLevels (stbi.Width, stbi.Height) : 1;
+                                               image = new byte [stbi.Data.Length];
+                                               //rgba to argb for cairo.
+                                               for (int i = 0; i < stbi.Data.Length; i += 4) {
+                                                       image [i] = stbi.Data[i + 2];
+                                                       image [i + 1] = stbi.Data [i + 1];
+                                                       image [i + 2] = stbi.Data [i];
+                                                       image [i + 3] = stbi.Data [i + 3];
+                                               }
+                                               Dimensions = new Size (stbi.Width, stbi.Height);
+                       #else*/
+
+                       using (StbImage stbi = new StbImage (bitmap)) {
+                               uint mipLevels = generateMipmaps ? ComputeMipLevels (stbi.Width, stbi.Height) : 1;
+
+                               Image img = new Image (dev, format, usage, memoryProps, (uint)stbi.Width, (uint)stbi.Height, imageType,
+                                       VkSampleCountFlags.SampleCount1, tiling, mipLevels);
+
+                               img.load (staggingQ, staggingCmdPool, stbi.Handle, generateMipmaps);
+
+                               return img;
+                       }
+//#endif
+               }
+               /// <summary>
+               /// create host visible linear image without command from data pointed by IntPtr pointer containing full image file (jpg, png,...)
+               /// </summary>
+               public static Image Load (Device dev,
+                       Memory<byte> bitmap, ulong bitmapByteCount, VkImageUsageFlags usage = VkImageUsageFlags.TransferSrc,
+                       VkFormat format = VkFormat.Undefined,
+                       VkMemoryPropertyFlags memoryProps = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent,
+                       VkImageTiling tiling = VkImageTiling.Linear, bool generateMipmaps = false,
+                       VkImageType imageType = VkImageType.Image2D) {
+
+                       if (format == VkFormat.Undefined)
+                               format = DefaultTextureFormat;
+                       if (generateMipmaps)
+                               usage |= (VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst);
+
+                       using (StbImage stbi = new StbImage (bitmap)) {
+                               uint mipLevels = generateMipmaps ? ComputeMipLevels (stbi.Width, stbi.Height) : 1;
+
+                               Image img = new Image (dev, format, usage, memoryProps, (uint)stbi.Width, (uint)stbi.Height, imageType,
+                                       VkSampleCountFlags.SampleCount1, tiling, mipLevels);
+
+                               img.Map ();
+                               stbi.CoptyTo (img.MappedData);
+                               img.Unmap ();
+
+                               return img;
+                       }
+               }
+
                /// <summary>
                /// Load image from byte array containing full image file (jpg, png,...)
                /// </summary>
@@ -192,8 +264,7 @@ namespace vke {
                                usage |= VkImageUsageFlags.TransferDst;
                        if (generateMipmaps)
                                usage |= (VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst);
-#if STB_SHARP
-                       
+/*#if STB_SHARP
                        StbImageSharp.ImageResult stbi = StbImageSharp.ImageResult.FromMemory (stream, StbImageSharp.ColorComponents.RedGreenBlueAlpha);
                        uint mipLevels = generateMipmaps ? ComputeMipLevels (stbi.Width, stbi.Height) : 1;
                        image = new byte [stbi.Data.Length];
@@ -205,7 +276,7 @@ namespace vke {
                                image [i + 3] = stbi.Data [i + 3];
                        }
                        Dimensions = new Size (stbi.Width, stbi.Height);
-#else
+#else*/
                        using (StbImage stbi = new StbImage (bitmap, bitmapByteCount)) {
                                uint mipLevels = generateMipmaps ? ComputeMipLevels (stbi.Width, stbi.Height) : 1;
 
@@ -216,7 +287,7 @@ namespace vke {
 
                                return img;
                        }
-#endif
+//#endif
                }
 
                /// <summary>
index 23fbace4312276f5688ce306e527b68c4579fdf7..e920e5fc89fa1786309de79dff08fb517bbe3910 100644 (file)
 
        <ItemGroup>
                <PackageReference Include="SpirVTasks" Version="$(SpirVTasksPackageVersion)" />
-               <PackageReference Include="Vulkan" Version="0.2.2.2-beta" />
+               <PackageReference Include="Vulkan" Version="0.2.20-beta" />
                <PackageReference Include="shaderc.net" Version="0.1.0" />
                <PackageReference Include="glfw-sharp" Version="0.2.6-beta" />
        </ItemGroup>
+       
+       <ItemGroup>
+               <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.7.1" />
+       </ItemGroup>
+
+       <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
+               <PackageReference Include="System.Memory" Version="4.5.4" />
+       </ItemGroup>
+
        <ItemGroup>
                <GLSLShader Include="shaders\**\*.frag;shaders\**\*.vert;shaders\**\*.comp;shaders\**\*.geom" />
                <Compile Remove="build\**\*.cs;Properties\AssemblyInfo.cs;src\Renderer.cs;src\QueueFamily.cs" />