forked from MoonsideGames/MoonWorks
				
			assets stream data directly into unmanaged memory
							parent
							
								
									3bd435746b
								
							
						
					
					
						commit
						1cf04a7279
					
				|  | @ -53,11 +53,8 @@ namespace MoonWorks.Audio | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// mostly borrowed from https://github.com/FNA-XNA/FNA/blob/b71b4a35ae59970ff0070dea6f8620856d8d4fec/src/Audio/SoundEffect.cs#L385 | 		// mostly borrowed from https://github.com/FNA-XNA/FNA/blob/b71b4a35ae59970ff0070dea6f8620856d8d4fec/src/Audio/SoundEffect.cs#L385 | ||||||
| 		public static StaticSound LoadWav(AudioDevice device, string filePath) | 		public static unsafe StaticSound LoadWav(AudioDevice device, string filePath) | ||||||
| 		{ | 		{ | ||||||
| 			// Sample data |  | ||||||
| 			byte[] data; |  | ||||||
| 
 |  | ||||||
| 			// WaveFormatEx data | 			// WaveFormatEx data | ||||||
| 			ushort wFormatTag; | 			ushort wFormatTag; | ||||||
| 			ushort nChannels; | 			ushort nChannels; | ||||||
|  | @ -68,8 +65,9 @@ namespace MoonWorks.Audio | ||||||
| 			int samplerLoopStart = 0; | 			int samplerLoopStart = 0; | ||||||
| 			int samplerLoopEnd = 0; | 			int samplerLoopEnd = 0; | ||||||
| 
 | 
 | ||||||
| 			using (BinaryReader reader = new BinaryReader(File.OpenRead(filePath))) | 			using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read); | ||||||
| 			{ | 			using var reader = new BinaryReader(stream); | ||||||
|  | 
 | ||||||
| 			// RIFF Signature | 			// RIFF Signature | ||||||
| 			string signature = new string(reader.ReadChars(4)); | 			string signature = new string(reader.ReadChars(4)); | ||||||
| 			if (signature != "RIFF") | 			if (signature != "RIFF") | ||||||
|  | @ -121,7 +119,9 @@ namespace MoonWorks.Audio | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			int waveDataLength = reader.ReadInt32(); | 			int waveDataLength = reader.ReadInt32(); | ||||||
| 				data = reader.ReadBytes(waveDataLength); | 			var waveDataBuffer = NativeMemory.Alloc((nuint) waveDataLength); | ||||||
|  | 			var waveDataSpan = new Span<byte>(waveDataBuffer, waveDataLength); | ||||||
|  | 			stream.ReadExactly(waveDataSpan); | ||||||
| 
 | 
 | ||||||
| 			// Scan for other chunks | 			// Scan for other chunks | ||||||
| 			while (reader.PeekChar() != -1) | 			while (reader.PeekChar() != -1) | ||||||
|  | @ -177,32 +177,32 @@ namespace MoonWorks.Audio | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			// End scan | 			// End scan | ||||||
| 			} |  | ||||||
| 
 | 
 | ||||||
| 			return new StaticSound( | 			var sound = new StaticSound( | ||||||
| 				device, | 				device, | ||||||
| 				wFormatTag, | 				wFormatTag, | ||||||
| 				wBitsPerSample, | 				wBitsPerSample, | ||||||
| 				nBlockAlign, | 				nBlockAlign, | ||||||
| 				nChannels, | 				nChannels, | ||||||
| 				nSamplesPerSec, | 				nSamplesPerSec, | ||||||
| 				data, | 				(nint) waveDataBuffer, | ||||||
| 				0, | 				(uint) waveDataLength, | ||||||
| 				(uint) data.Length | 				true | ||||||
| 			); | 			); | ||||||
|  | 
 | ||||||
|  | 			return sound; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		public unsafe StaticSound( | 		public StaticSound( | ||||||
| 			AudioDevice device, | 			AudioDevice device, | ||||||
| 			ushort formatTag, | 			ushort formatTag, | ||||||
| 			ushort bitsPerSample, | 			ushort bitsPerSample, | ||||||
| 			ushort blockAlign, | 			ushort blockAlign, | ||||||
| 			ushort channels, | 			ushort channels, | ||||||
| 			uint samplesPerSecond, | 			uint samplesPerSecond, | ||||||
| 			byte[] buffer, | 			IntPtr bufferPtr, | ||||||
| 			uint bufferOffset, /* number of bytes */ | 			uint bufferLengthInBytes, | ||||||
| 			uint bufferLength /* number of bytes */ | 			bool ownsBuffer) : base(device) | ||||||
| 		) : base(device) |  | ||||||
| 		{ | 		{ | ||||||
| 			FormatTag = formatTag; | 			FormatTag = formatTag; | ||||||
| 			BitsPerSample = bitsPerSample; | 			BitsPerSample = bitsPerSample; | ||||||
|  | @ -210,19 +210,17 @@ namespace MoonWorks.Audio | ||||||
| 			Channels = channels; | 			Channels = channels; | ||||||
| 			SamplesPerSecond = samplesPerSecond; | 			SamplesPerSecond = samplesPerSecond; | ||||||
| 
 | 
 | ||||||
| 			Handle = new FAudio.FAudioBuffer(); | 			Handle = new FAudio.FAudioBuffer | ||||||
| 			Handle.Flags = FAudio.FAUDIO_END_OF_STREAM; | 			{ | ||||||
| 			Handle.pContext = IntPtr.Zero; | 				Flags = FAudio.FAUDIO_END_OF_STREAM, | ||||||
| 			Handle.AudioBytes = bufferLength; | 				pContext = IntPtr.Zero, | ||||||
| 			Handle.pAudioData = (nint) NativeMemory.Alloc(bufferLength); | 				pAudioData = bufferPtr, | ||||||
| 			Marshal.Copy(buffer, (int) bufferOffset, Handle.pAudioData, (int) bufferLength); | 				AudioBytes = bufferLengthInBytes, | ||||||
| 			Handle.PlayBegin = 0; | 				PlayBegin = 0, | ||||||
| 			Handle.PlayLength = 0; | 				PlayLength = 0 | ||||||
|  | 			}; | ||||||
| 
 | 
 | ||||||
| 			LoopStart = 0; | 			OwnsBuffer = ownsBuffer; | ||||||
| 			LoopLength = 0; |  | ||||||
| 
 |  | ||||||
| 			OwnsBuffer = true; |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		public unsafe StaticSound( | 		public unsafe StaticSound( | ||||||
|  | @ -256,35 +254,6 @@ namespace MoonWorks.Audio | ||||||
| 			OwnsBuffer = true; | 			OwnsBuffer = true; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		public StaticSound( |  | ||||||
| 			AudioDevice device, |  | ||||||
| 			ushort formatTag, |  | ||||||
| 			ushort bitsPerSample, |  | ||||||
| 			ushort blockAlign, |  | ||||||
| 			ushort channels, |  | ||||||
| 			uint samplesPerSecond, |  | ||||||
| 			IntPtr bufferPtr, |  | ||||||
| 			uint bufferLengthInBytes) : base(device) |  | ||||||
| 		{ |  | ||||||
| 			FormatTag = formatTag; |  | ||||||
| 			BitsPerSample = bitsPerSample; |  | ||||||
| 			BlockAlign = blockAlign; |  | ||||||
| 			Channels = channels; |  | ||||||
| 			SamplesPerSecond = samplesPerSecond; |  | ||||||
| 
 |  | ||||||
| 			Handle = new FAudio.FAudioBuffer |  | ||||||
| 			{ |  | ||||||
| 				Flags = FAudio.FAUDIO_END_OF_STREAM, |  | ||||||
| 				pContext = IntPtr.Zero, |  | ||||||
| 				pAudioData = bufferPtr, |  | ||||||
| 				AudioBytes = bufferLengthInBytes, |  | ||||||
| 				PlayBegin = 0, |  | ||||||
| 				PlayLength = 0 |  | ||||||
| 			}; |  | ||||||
| 
 |  | ||||||
| 			OwnsBuffer = false; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		/// <summary> | 		/// <summary> | ||||||
| 		/// Gets a sound instance from the pool. | 		/// Gets a sound instance from the pool. | ||||||
| 		/// NOTE: If you lose track of instances, you will create garbage collection pressure! | 		/// NOTE: If you lose track of instances, you will create garbage collection pressure! | ||||||
|  |  | ||||||
|  | @ -15,10 +15,13 @@ namespace MoonWorks.Audio | ||||||
| 
 | 
 | ||||||
| 		public unsafe static StreamingSoundOgg Load(AudioDevice device, string filePath) | 		public unsafe static StreamingSoundOgg Load(AudioDevice device, string filePath) | ||||||
| 		{ | 		{ | ||||||
| 			var fileData = File.ReadAllBytes(filePath); | 			var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); | ||||||
| 			var fileDataPtr = NativeMemory.Alloc((nuint) fileData.Length); | 			var fileDataPtr = NativeMemory.Alloc((nuint) fileStream.Length); | ||||||
| 			Marshal.Copy(fileData, 0, (IntPtr) fileDataPtr, fileData.Length); | 			var fileDataSpan = new Span<byte>(fileDataPtr, (int) fileStream.Length); | ||||||
| 			var vorbisHandle = FAudio.stb_vorbis_open_memory((IntPtr) fileDataPtr, fileData.Length, out int error, IntPtr.Zero); | 			fileStream.ReadExactly(fileDataSpan); | ||||||
|  | 			fileStream.Close(); | ||||||
|  | 
 | ||||||
|  | 			var vorbisHandle = FAudio.stb_vorbis_open_memory((IntPtr) fileDataPtr, fileDataSpan.Length, out int error, IntPtr.Zero); | ||||||
| 			if (error != 0) | 			if (error != 0) | ||||||
| 			{ | 			{ | ||||||
| 				NativeMemory.Free(fileDataPtr); | 				NativeMemory.Free(fileDataPtr); | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| using System; | using System; | ||||||
| using System.IO; | using System.IO; | ||||||
|  | using System.Runtime.InteropServices; | ||||||
| using WellspringCS; | using WellspringCS; | ||||||
| 
 | 
 | ||||||
| namespace MoonWorks.Graphics.Font | namespace MoonWorks.Graphics.Font | ||||||
|  | @ -12,11 +13,15 @@ namespace MoonWorks.Graphics.Font | ||||||
| 
 | 
 | ||||||
|         public unsafe Font(string path) |         public unsafe Font(string path) | ||||||
|         { |         { | ||||||
|             var bytes = File.ReadAllBytes(path); | 	        var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read); | ||||||
| 			fixed (byte* pByte = &bytes[0]) | 	        var fileByteBuffer = NativeMemory.Alloc((nuint) fileStream.Length); | ||||||
| 			{ | 	        var fileByteSpan = new Span<byte>(fileByteBuffer, (int) fileStream.Length); | ||||||
| 				Handle = Wellspring.Wellspring_CreateFont((IntPtr) pByte, (uint) bytes.Length); | 	        fileStream.ReadExactly(fileByteSpan); | ||||||
| 			} | 	        fileStream.Close(); | ||||||
|  | 
 | ||||||
|  | 	        Handle = Wellspring.Wellspring_CreateFont((IntPtr) fileByteBuffer, (uint) fileByteSpan.Length); | ||||||
|  | 
 | ||||||
|  | 	        NativeMemory.Free(fileByteBuffer); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 		protected virtual void Dispose(bool disposing) | 		protected virtual void Dispose(bool disposing) | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| using RefreshCS; | using RefreshCS; | ||||||
| using System; | using System; | ||||||
| using System.IO; | using System.IO; | ||||||
|  | using System.Runtime.InteropServices; | ||||||
| 
 | 
 | ||||||
| namespace MoonWorks.Graphics | namespace MoonWorks.Graphics | ||||||
| { | { | ||||||
|  | @ -13,30 +14,29 @@ namespace MoonWorks.Graphics | ||||||
| 
 | 
 | ||||||
| 		public unsafe ShaderModule(GraphicsDevice device, string filePath) : base(device) | 		public unsafe ShaderModule(GraphicsDevice device, string filePath) : base(device) | ||||||
| 		{ | 		{ | ||||||
| 			using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) | 			using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read); | ||||||
| 			{ |  | ||||||
| 			Handle = CreateFromStream(device, stream); | 			Handle = CreateFromStream(device, stream); | ||||||
| 		} | 		} | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		public unsafe ShaderModule(GraphicsDevice device, Stream stream) : base(device) | 		public unsafe ShaderModule(GraphicsDevice device, Stream stream) : base(device) | ||||||
| 		{ | 		{ | ||||||
| 			Handle = CreateFromStream(device, stream); | 			Handle = CreateFromStream(device, stream); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		private unsafe static IntPtr CreateFromStream(GraphicsDevice device, Stream stream) | 		private static unsafe IntPtr CreateFromStream(GraphicsDevice device, Stream stream) | ||||||
| 		{ | 		{ | ||||||
| 			var bytecode = new byte[stream.Length]; | 			var bytecodeBuffer = NativeMemory.Alloc((nuint) stream.Length); | ||||||
| 			stream.Read(bytecode, 0, (int) stream.Length); | 			var bytecodeSpan = new Span<byte>(bytecodeBuffer, (int) stream.Length); | ||||||
|  | 			stream.ReadExactly(bytecodeSpan); | ||||||
| 
 | 
 | ||||||
| 			fixed (byte* ptr = bytecode) |  | ||||||
| 			{ |  | ||||||
| 			Refresh.ShaderModuleCreateInfo shaderModuleCreateInfo; | 			Refresh.ShaderModuleCreateInfo shaderModuleCreateInfo; | ||||||
| 				shaderModuleCreateInfo.codeSize = (UIntPtr) bytecode.Length; | 			shaderModuleCreateInfo.codeSize = (nuint) stream.Length; | ||||||
| 				shaderModuleCreateInfo.byteCode = (IntPtr) ptr; | 			shaderModuleCreateInfo.byteCode = (nint) bytecodeBuffer; | ||||||
| 
 | 
 | ||||||
| 				return Refresh.Refresh_CreateShaderModule(device.Handle, shaderModuleCreateInfo); | 			var shaderModule = Refresh.Refresh_CreateShaderModule(device.Handle, shaderModuleCreateInfo); | ||||||
| 			} | 
 | ||||||
|  | 			NativeMemory.Free(bytecodeBuffer); | ||||||
|  | 			return shaderModule; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| using System; | using System; | ||||||
| using System.IO; | using System.IO; | ||||||
|  | using System.Runtime.InteropServices; | ||||||
| using RefreshCS; | using RefreshCS; | ||||||
| 
 | 
 | ||||||
| namespace MoonWorks.Graphics | namespace MoonWorks.Graphics | ||||||
|  | @ -217,10 +218,9 @@ namespace MoonWorks.Graphics | ||||||
| 			return texture; | 			return texture; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		public static Texture LoadDDS(GraphicsDevice graphicsDevice, CommandBuffer commandBuffer, System.IO.Stream stream) | 		public unsafe static Texture LoadDDS(GraphicsDevice graphicsDevice, CommandBuffer commandBuffer, System.IO.Stream stream) | ||||||
| 		{ |  | ||||||
| 			using (var reader = new BinaryReader(stream)) |  | ||||||
| 		{ | 		{ | ||||||
|  | 			using var reader = new BinaryReader(stream); | ||||||
| 			Texture texture; | 			Texture texture; | ||||||
| 			int faces; | 			int faces; | ||||||
| 			ParseDDS(reader, out var format, out var width, out var height, out var levels, out var isCube); | 			ParseDDS(reader, out var format, out var width, out var height, out var levels, out var isCube); | ||||||
|  | @ -243,22 +243,20 @@ namespace MoonWorks.Graphics | ||||||
| 					var levelWidth = width >> j; | 					var levelWidth = width >> j; | ||||||
| 					var levelHeight = height >> j; | 					var levelHeight = height >> j; | ||||||
| 
 | 
 | ||||||
| 						var pixels = reader.ReadBytes( | 					var levelSize = CalculateDDSLevelSize(levelWidth, levelHeight, format); | ||||||
| 							Texture.CalculateDDSLevelSize( | 					var byteBuffer = NativeMemory.Alloc((nuint) levelSize); | ||||||
| 								levelWidth, | 					var byteSpan = new Span<byte>(byteBuffer, levelSize); | ||||||
| 								levelHeight, | 					stream.ReadExactly(byteSpan); | ||||||
| 								format |  | ||||||
| 							) |  | ||||||
| 						); |  | ||||||
| 
 | 
 | ||||||
| 					var textureSlice = new TextureSlice(texture, new Rect(0, 0, levelWidth, levelHeight), 0, (uint) i, (uint) j); | 					var textureSlice = new TextureSlice(texture, new Rect(0, 0, levelWidth, levelHeight), 0, (uint) i, (uint) j); | ||||||
| 						commandBuffer.SetTextureData(textureSlice, pixels); | 					commandBuffer.SetTextureData(textureSlice, (nint) byteBuffer, (uint) levelSize); | ||||||
|  | 
 | ||||||
|  | 					NativeMemory.Free(byteBuffer); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			return texture; | 			return texture; | ||||||
| 		} | 		} | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		/// <summary> | 		/// <summary> | ||||||
| 		/// Creates a 2D texture. | 		/// Creates a 2D texture. | ||||||
|  |  | ||||||
|  | @ -1,6 +1,8 @@ | ||||||
| /* Heavily based on https://github.com/FNA-XNA/FNA/blob/master/src/Media/Xiph/VideoPlayer.cs */ | /* Heavily based on https://github.com/FNA-XNA/FNA/blob/master/src/Media/Xiph/VideoPlayer.cs */ | ||||||
| using System; | using System; | ||||||
|  | using System.IO; | ||||||
| using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||||
|  | using SDL2; | ||||||
| 
 | 
 | ||||||
| namespace MoonWorks.Video | namespace MoonWorks.Video | ||||||
| { | { | ||||||
|  | @ -16,6 +18,7 @@ namespace MoonWorks.Video | ||||||
| 		internal IntPtr Handle; | 		internal IntPtr Handle; | ||||||
| 		private IntPtr rwData; | 		private IntPtr rwData; | ||||||
| 		private void* videoData; | 		private void* videoData; | ||||||
|  | 		private int videoDataLength; | ||||||
| 
 | 
 | ||||||
| 		public double FramesPerSecond => fps; | 		public double FramesPerSecond => fps; | ||||||
| 		public int Width => yWidth; | 		public int Width => yWidth; | ||||||
|  | @ -31,16 +34,19 @@ namespace MoonWorks.Video | ||||||
| 
 | 
 | ||||||
| 		public Video(string filename) | 		public Video(string filename) | ||||||
| 		{ | 		{ | ||||||
| 			if (!System.IO.File.Exists(filename)) | 			if (!File.Exists(filename)) | ||||||
| 			{ | 			{ | ||||||
| 				throw new ArgumentException("Video file not found!"); | 				throw new ArgumentException("Video file not found!"); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			var bytes = System.IO.File.ReadAllBytes(filename); | 			var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read); | ||||||
| 			videoData = NativeMemory.Alloc((nuint) bytes.Length); | 			videoDataLength = (int) fileStream.Length; | ||||||
| 			Marshal.Copy(bytes, 0, (IntPtr) videoData, bytes.Length); | 			videoData = NativeMemory.Alloc((nuint) videoDataLength); | ||||||
| 			rwData = SDL2.SDL.SDL_RWFromMem((IntPtr) videoData, bytes.Length); | 			var fileBufferSpan = new Span<byte>(videoData, videoDataLength); | ||||||
|  | 			fileStream.ReadExactly(fileBufferSpan); | ||||||
|  | 			fileStream.Close(); | ||||||
| 
 | 
 | ||||||
|  | 			rwData = SDL.SDL_RWFromMem((IntPtr) videoData, videoDataLength); | ||||||
| 			if (Theorafile.tf_open_callbacks(rwData, out Handle, callbacks) < 0) | 			if (Theorafile.tf_open_callbacks(rwData, out Handle, callbacks) < 0) | ||||||
| 			{ | 			{ | ||||||
| 				throw new ArgumentException("Invalid video file!"); | 				throw new ArgumentException("Invalid video file!"); | ||||||
|  | @ -98,6 +104,7 @@ namespace MoonWorks.Video | ||||||
| 
 | 
 | ||||||
| 				// free unmanaged resources (unmanaged objects) | 				// free unmanaged resources (unmanaged objects) | ||||||
| 				Theorafile.tf_close(ref Handle); | 				Theorafile.tf_close(ref Handle); | ||||||
|  | 				SDL.SDL_RWclose(rwData); | ||||||
| 				NativeMemory.Free(videoData); | 				NativeMemory.Free(videoData); | ||||||
| 
 | 
 | ||||||
| 				IsDisposed = true; | 				IsDisposed = true; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue