CreateTextureFromDDS + respect buffer alignment
							parent
							
								
									1eae01c95c
								
							
						
					
					
						commit
						8229e5dd33
					
				|  | @ -19,7 +19,7 @@ namespace MoonWorks.Graphics | ||||||
| 		uint dataSize = 1024; | 		uint dataSize = 1024; | ||||||
| 
 | 
 | ||||||
| 		List<(GpuBuffer, uint, uint)> BufferUploads = new List<(GpuBuffer, uint, uint)>(); | 		List<(GpuBuffer, uint, uint)> BufferUploads = new List<(GpuBuffer, uint, uint)>(); | ||||||
| 		List<(Texture, uint, uint)> TextureUploads = new List<(Texture, uint, uint)>(); | 		List<(TextureSlice, uint)> TextureUploads = new List<(TextureSlice, uint)>(); | ||||||
| 
 | 
 | ||||||
| 		public ResourceInitializer(GraphicsDevice device) : base(device) | 		public ResourceInitializer(GraphicsDevice device) : base(device) | ||||||
| 		{ | 		{ | ||||||
|  | @ -34,15 +34,14 @@ namespace MoonWorks.Graphics | ||||||
| 			var lengthInBytes = (uint) (Marshal.SizeOf<T>() * data.Length); | 			var lengthInBytes = (uint) (Marshal.SizeOf<T>() * data.Length); | ||||||
| 			var gpuBuffer = new GpuBuffer(Device, usageFlags, lengthInBytes); | 			var gpuBuffer = new GpuBuffer(Device, usageFlags, lengthInBytes); | ||||||
| 
 | 
 | ||||||
| 			BufferUploads.Add((gpuBuffer, dataOffset, lengthInBytes)); | 			uint resourceOffset; | ||||||
| 
 |  | ||||||
| 			ResizeDataIfNeeded(lengthInBytes); |  | ||||||
| 
 |  | ||||||
| 			fixed (void* spanPtr = data) | 			fixed (void* spanPtr = data) | ||||||
| 			{ | 			{ | ||||||
| 				CopyData(spanPtr, lengthInBytes); | 				resourceOffset = CopyData(spanPtr, lengthInBytes); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | 			BufferUploads.Add((gpuBuffer, resourceOffset, lengthInBytes)); | ||||||
|  | 
 | ||||||
| 			return gpuBuffer; | 			return gpuBuffer; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -53,12 +52,11 @@ namespace MoonWorks.Graphics | ||||||
| 		{ | 		{ | ||||||
| 			var pixelData = ImageUtils.GetPixelDataFromBytes(data, out var width, out var height, out var lengthInBytes); | 			var pixelData = ImageUtils.GetPixelDataFromBytes(data, out var width, out var height, out var lengthInBytes); | ||||||
| 			var texture = Texture.CreateTexture2D(Device, width, height, TextureFormat.R8G8B8A8, TextureUsageFlags.Sampler); | 			var texture = Texture.CreateTexture2D(Device, width, height, TextureFormat.R8G8B8A8, TextureUsageFlags.Sampler); | ||||||
| 			TextureUploads.Add((texture, dataOffset, lengthInBytes)); |  | ||||||
| 
 | 
 | ||||||
| 			ResizeDataIfNeeded(lengthInBytes); | 			var resourceOffset = CopyData((void*) pixelData, texture.Size); | ||||||
| 			CopyData((void*) pixelData, lengthInBytes); |  | ||||||
| 			ImageUtils.FreePixelData(pixelData); | 			ImageUtils.FreePixelData(pixelData); | ||||||
| 
 | 
 | ||||||
|  | 			TextureUploads.Add((texture, resourceOffset)); | ||||||
| 			return texture; | 			return texture; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -88,6 +86,66 @@ namespace MoonWorks.Graphics | ||||||
| 			return CreateTexture2D(fileStream); | 			return CreateTexture2D(fileStream); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		public Texture CreateTextureFromDDS(Stream stream) | ||||||
|  | 		{ | ||||||
|  | 			using var reader = new BinaryReader(stream); | ||||||
|  | 			Texture texture; | ||||||
|  | 			int faces; | ||||||
|  | 			ImageUtils.ParseDDS(reader, out var format, out var width, out var height, out var levels, out var isCube); | ||||||
|  | 
 | ||||||
|  | 			if (isCube) | ||||||
|  | 			{ | ||||||
|  | 				texture = Texture.CreateTextureCube(Device, (uint) width, format, TextureUsageFlags.Sampler, (uint) levels); | ||||||
|  | 				faces = 6; | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				texture = Texture.CreateTexture2D(Device, (uint) width, (uint) height, format, TextureUsageFlags.Sampler, (uint) levels); | ||||||
|  | 				faces = 1; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			for (int face = 0; face < faces; face += 1) | ||||||
|  | 			{ | ||||||
|  | 				for (int level = 0; level < levels; level += 1) | ||||||
|  | 				{ | ||||||
|  | 					var levelWidth = width >> level; | ||||||
|  | 					var levelHeight = height >> level; | ||||||
|  | 
 | ||||||
|  | 					var levelSize = ImageUtils.CalculateDDSLevelSize(levelWidth, levelHeight, format); | ||||||
|  | 					var byteBuffer = NativeMemory.Alloc((nuint) levelSize); | ||||||
|  | 					var byteSpan = new Span<byte>(byteBuffer, levelSize); | ||||||
|  | 					stream.ReadExactly(byteSpan); | ||||||
|  | 
 | ||||||
|  | 					var textureSlice = new TextureSlice | ||||||
|  | 					{ | ||||||
|  | 						Texture = texture, | ||||||
|  | 						MipLevel = (uint) level, | ||||||
|  | 						BaseLayer = (uint) face, | ||||||
|  | 						LayerCount = 1, | ||||||
|  | 						X = 0, | ||||||
|  | 						Y = 0, | ||||||
|  | 						Z = 0, | ||||||
|  | 						Width = (uint) levelWidth, | ||||||
|  | 						Height = (uint) levelHeight, | ||||||
|  | 						Depth = 1 | ||||||
|  | 					}; | ||||||
|  | 
 | ||||||
|  | 					var resourceOffset = CopyDataAligned(byteBuffer, (uint) levelSize, Texture.TexelSize(format)); | ||||||
|  | 					TextureUploads.Add((textureSlice, resourceOffset)); | ||||||
|  | 
 | ||||||
|  | 					NativeMemory.Free(byteBuffer); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			return texture; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		public Texture CreateTextureFromDDS(string path) | ||||||
|  | 		{ | ||||||
|  | 			var stream = new FileStream(path, FileMode.Open, FileAccess.Read); | ||||||
|  | 			return CreateTextureFromDDS(stream); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		/// <summary> | 		/// <summary> | ||||||
| 		/// Uploads all the data corresponding to the created resources. | 		/// Uploads all the data corresponding to the created resources. | ||||||
| 		/// </summary> | 		/// </summary> | ||||||
|  | @ -119,11 +177,11 @@ namespace MoonWorks.Graphics | ||||||
| 				); | 				); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			foreach (var (texture, offset, size) in TextureUploads) | 			foreach (var (textureSlice, offset) in TextureUploads) | ||||||
| 			{ | 			{ | ||||||
| 				commandBuffer.UploadToTexture( | 				commandBuffer.UploadToTexture( | ||||||
| 					TransferBuffer, | 					TransferBuffer, | ||||||
| 					texture, | 					textureSlice, | ||||||
| 					new BufferImageCopy( | 					new BufferImageCopy( | ||||||
| 						offset, | 						offset, | ||||||
| 						0, | 						0, | ||||||
|  | @ -140,19 +198,31 @@ namespace MoonWorks.Graphics | ||||||
| 			dataOffset = 0; | 			dataOffset = 0; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		private void ResizeDataIfNeeded(uint lengthInBytes) | 		private uint CopyData(void* ptr, uint lengthInBytes) | ||||||
| 		{ | 		{ | ||||||
| 			if (dataOffset + lengthInBytes >= dataSize) | 			if (dataOffset + lengthInBytes >= dataSize) | ||||||
| 			{ | 			{ | ||||||
| 				dataSize = dataOffset + lengthInBytes; | 				dataSize = dataOffset + lengthInBytes; | ||||||
| 				data = (byte*) NativeMemory.Realloc(data, dataSize); | 				data = (byte*) NativeMemory.Realloc(data, dataSize); | ||||||
| 			} | 			} | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		private void CopyData(void* ptr, uint lengthInBytes) | 			var resourceOffset = dataOffset; | ||||||
| 		{ | 
 | ||||||
| 			NativeMemory.Copy(ptr, data + dataOffset, lengthInBytes); | 			NativeMemory.Copy(ptr, data + dataOffset, lengthInBytes); | ||||||
| 			dataOffset += lengthInBytes; | 			dataOffset += lengthInBytes; | ||||||
|  | 
 | ||||||
|  | 			return resourceOffset; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		private uint CopyDataAligned(void* ptr, uint lengthInBytes, uint alignment) | ||||||
|  | 		{ | ||||||
|  | 			dataOffset = RoundToAlignment(dataOffset, alignment); | ||||||
|  | 			return CopyData(ptr, lengthInBytes); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		private uint RoundToAlignment(uint value, uint alignment) | ||||||
|  | 		{ | ||||||
|  | 			return alignment * ((value + alignment - 1) / alignment); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		protected override void Dispose(bool disposing) | 		protected override void Dispose(bool disposing) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue