Setup entry point + integrated moonworks stuff
This commit is contained in:
		
							
								
								
									
										1948
									
								
								Nerfed.Runtime/Graphics/Color.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1948
									
								
								Nerfed.Runtime/Graphics/Color.cs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1042
									
								
								Nerfed.Runtime/Graphics/CommandBuffer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1042
									
								
								Nerfed.Runtime/Graphics/CommandBuffer.cs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										33
									
								
								Nerfed.Runtime/Graphics/CommandBufferPool.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								Nerfed.Runtime/Graphics/CommandBufferPool.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
internal class CommandBufferPool
 | 
			
		||||
{
 | 
			
		||||
	private GraphicsDevice GraphicsDevice;
 | 
			
		||||
	private ConcurrentQueue<CommandBuffer> CommandBuffers = new ConcurrentQueue<CommandBuffer>();
 | 
			
		||||
 | 
			
		||||
	public CommandBufferPool(GraphicsDevice graphicsDevice)
 | 
			
		||||
	{
 | 
			
		||||
		GraphicsDevice = graphicsDevice;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public CommandBuffer Obtain()
 | 
			
		||||
	{
 | 
			
		||||
		if (CommandBuffers.TryDequeue(out CommandBuffer commandBuffer))
 | 
			
		||||
		{
 | 
			
		||||
			return commandBuffer;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			return new CommandBuffer(GraphicsDevice);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void Return(CommandBuffer commandBuffer)
 | 
			
		||||
	{
 | 
			
		||||
		commandBuffer.Handle = IntPtr.Zero;
 | 
			
		||||
		CommandBuffers.Enqueue(commandBuffer);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										171
									
								
								Nerfed.Runtime/Graphics/ComputePass.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								Nerfed.Runtime/Graphics/ComputePass.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,171 @@
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
using RefreshCS;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
public class ComputePass
 | 
			
		||||
{
 | 
			
		||||
	public nint Handle { get; private set; }
 | 
			
		||||
 | 
			
		||||
	internal void SetHandle(nint handle)
 | 
			
		||||
	{
 | 
			
		||||
		Handle = handle;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
	internal bool active;
 | 
			
		||||
 | 
			
		||||
	ComputePipeline currentComputePipeline;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Binds a compute pipeline so that compute work may be dispatched.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="computePipeline">The compute pipeline to bind.</param>
 | 
			
		||||
	public void BindComputePipeline(
 | 
			
		||||
		ComputePipeline computePipeline
 | 
			
		||||
	) {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
		AssertComputePassActive();
 | 
			
		||||
 | 
			
		||||
		// TODO: validate formats?
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		Refresh.Refresh_BindComputePipeline(
 | 
			
		||||
			Handle,
 | 
			
		||||
			computePipeline.Handle
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
		currentComputePipeline = computePipeline;
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Binds a texture to be used in the compute shader.
 | 
			
		||||
	/// This texture must have been created with the ComputeShaderRead usage flag.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public unsafe void BindStorageTexture(
 | 
			
		||||
		in TextureSlice textureSlice,
 | 
			
		||||
		uint slot = 0
 | 
			
		||||
	) {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
		AssertComputePassActive();
 | 
			
		||||
		AssertComputePipelineBound();
 | 
			
		||||
		AssertTextureNonNull(textureSlice.Texture);
 | 
			
		||||
		AssertTextureHasComputeStorageReadFlag(textureSlice.Texture);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		Refresh.TextureSlice refreshTextureSlice = textureSlice.ToRefresh();
 | 
			
		||||
 | 
			
		||||
		Refresh.Refresh_BindComputeStorageTextures(
 | 
			
		||||
			Handle,
 | 
			
		||||
			slot,
 | 
			
		||||
			&refreshTextureSlice,
 | 
			
		||||
			1
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Binds a buffer to be used in the compute shader.
 | 
			
		||||
	/// This buffer must have been created with the ComputeShaderRead usage flag.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public unsafe void BindStorageBuffer(
 | 
			
		||||
		Buffer buffer,
 | 
			
		||||
		uint slot = 0
 | 
			
		||||
	) {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
		AssertComputePassActive();
 | 
			
		||||
		AssertComputePipelineBound();
 | 
			
		||||
		AssertBufferNonNull(buffer);
 | 
			
		||||
		AssertBufferHasComputeStorageReadFlag(buffer);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		IntPtr bufferHandle = buffer.Handle;
 | 
			
		||||
 | 
			
		||||
		Refresh.Refresh_BindComputeStorageBuffers(
 | 
			
		||||
			Handle,
 | 
			
		||||
			slot,
 | 
			
		||||
			&bufferHandle,
 | 
			
		||||
			1
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Dispatches compute work.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public void Dispatch(
 | 
			
		||||
		uint groupCountX,
 | 
			
		||||
		uint groupCountY,
 | 
			
		||||
		uint groupCountZ
 | 
			
		||||
	) {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
		AssertComputePassActive();
 | 
			
		||||
		AssertComputePipelineBound();
 | 
			
		||||
 | 
			
		||||
		if (groupCountX < 1 || groupCountY < 1 || groupCountZ < 1)
 | 
			
		||||
		{
 | 
			
		||||
			throw new System.ArgumentException("All dimensions for the compute work groups must be >= 1!");
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		Refresh.Refresh_DispatchCompute(
 | 
			
		||||
			Handle,
 | 
			
		||||
			groupCountX,
 | 
			
		||||
			groupCountY,
 | 
			
		||||
			groupCountZ
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
	private void AssertComputePassActive(string message = "Render pass is not active!")
 | 
			
		||||
	{
 | 
			
		||||
		if (!active)
 | 
			
		||||
		{
 | 
			
		||||
			throw new System.InvalidOperationException(message);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void AssertComputePipelineBound(string message = "No compute pipeline is bound!")
 | 
			
		||||
	{
 | 
			
		||||
		if (currentComputePipeline == null)
 | 
			
		||||
		{
 | 
			
		||||
			throw new System.InvalidOperationException(message);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void AssertTextureNonNull(in TextureSlice textureSlice)
 | 
			
		||||
	{
 | 
			
		||||
		if (textureSlice.Texture == null || textureSlice.Texture.Handle == nint.Zero)
 | 
			
		||||
		{
 | 
			
		||||
			throw new System.NullReferenceException("Texture must not be null!");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void AssertTextureHasComputeStorageReadFlag(Texture texture)
 | 
			
		||||
	{
 | 
			
		||||
		if ((texture.UsageFlags & TextureUsageFlags.ComputeStorageRead) == 0)
 | 
			
		||||
		{
 | 
			
		||||
			throw new System.ArgumentException("The bound Texture's UsageFlags must include TextureUsageFlags.ComputeStorageRead!");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void AssertBufferNonNull(Buffer buffer)
 | 
			
		||||
	{
 | 
			
		||||
		if (buffer == null || buffer.Handle == nint.Zero)
 | 
			
		||||
		{
 | 
			
		||||
			throw new System.NullReferenceException("Buffer must not be null!");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void AssertBufferHasComputeStorageReadFlag(Buffer buffer)
 | 
			
		||||
	{
 | 
			
		||||
		if ((buffer.UsageFlags & BufferUsageFlags.ComputeStorageRead) == 0)
 | 
			
		||||
		{
 | 
			
		||||
			throw new System.ArgumentException("The bound Buffer's UsageFlags must include BufferUsageFlag.ComputeStorageRead!");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								Nerfed.Runtime/Graphics/ComputePassPool.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								Nerfed.Runtime/Graphics/ComputePassPool.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
internal class ComputePassPool
 | 
			
		||||
{
 | 
			
		||||
	private ConcurrentQueue<ComputePass> ComputePasses = new ConcurrentQueue<ComputePass>();
 | 
			
		||||
 | 
			
		||||
	public ComputePass Obtain()
 | 
			
		||||
	{
 | 
			
		||||
		if (ComputePasses.TryDequeue(out ComputePass computePass))
 | 
			
		||||
		{
 | 
			
		||||
			return computePass;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			return new ComputePass();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void Return(ComputePass computePass)
 | 
			
		||||
	{
 | 
			
		||||
		ComputePasses.Enqueue(computePass);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										241
									
								
								Nerfed.Runtime/Graphics/CopyPass.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										241
									
								
								Nerfed.Runtime/Graphics/CopyPass.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,241 @@
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
using RefreshCS;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
public class CopyPass
 | 
			
		||||
{
 | 
			
		||||
	public nint Handle { get; private set; }
 | 
			
		||||
 | 
			
		||||
	internal void SetHandle(nint handle)
 | 
			
		||||
	{
 | 
			
		||||
		Handle = handle;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Uploads data from a TransferBuffer to a TextureSlice.
 | 
			
		||||
	/// This copy occurs on the GPU timeline.
 | 
			
		||||
	///
 | 
			
		||||
	/// Overwriting the contents of the TransferBuffer before the command buffer
 | 
			
		||||
	/// has finished execution will cause undefined behavior.
 | 
			
		||||
	///
 | 
			
		||||
	/// You MAY assume that the copy has finished for subsequent commands.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="cycle">If true, cycles the texture if the given slice is bound.</param>
 | 
			
		||||
	public void UploadToTexture(
 | 
			
		||||
		in TextureTransferInfo source,
 | 
			
		||||
		in TextureRegion destination,
 | 
			
		||||
		bool cycle
 | 
			
		||||
	) {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
		AssertTransferBufferNotMapped(source.TransferBuffer);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		Refresh.Refresh_UploadToTexture(
 | 
			
		||||
			Handle,
 | 
			
		||||
			source.ToRefresh(),
 | 
			
		||||
			destination.ToRefresh(),
 | 
			
		||||
			Conversions.BoolToInt(cycle)
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Uploads the contents of an entire buffer to a 2D texture with no mips.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public void UploadToTexture(
 | 
			
		||||
		TransferBuffer source,
 | 
			
		||||
		Texture destination,
 | 
			
		||||
		bool cycle
 | 
			
		||||
	) {
 | 
			
		||||
		UploadToTexture(
 | 
			
		||||
			new TextureTransferInfo(source),
 | 
			
		||||
			new TextureRegion(destination),
 | 
			
		||||
			cycle
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Uploads data from a TransferBuffer to a Buffer.
 | 
			
		||||
	/// This copy occurs on the GPU timeline.
 | 
			
		||||
	///
 | 
			
		||||
	/// Overwriting the contents of the TransferBuffer before the command buffer
 | 
			
		||||
	/// has finished execution will cause undefined behavior.
 | 
			
		||||
	///
 | 
			
		||||
	/// You MAY assume that the copy has finished for subsequent commands.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="cycle">If true, cycles the buffer if it is bound.</param>
 | 
			
		||||
	public void UploadToBuffer(
 | 
			
		||||
		in TransferBufferLocation source,
 | 
			
		||||
		in BufferRegion destination,
 | 
			
		||||
		bool cycle
 | 
			
		||||
	) {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
		AssertBufferBoundsCheck(source.TransferBuffer.Size, source.Offset, destination.Size);
 | 
			
		||||
		AssertBufferBoundsCheck(destination.Buffer.Size, destination.Offset, destination.Size);
 | 
			
		||||
		AssertTransferBufferNotMapped(source.TransferBuffer);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		Refresh.Refresh_UploadToBuffer(
 | 
			
		||||
			Handle,
 | 
			
		||||
			source.ToRefresh(),
 | 
			
		||||
			destination.ToRefresh(),
 | 
			
		||||
			Conversions.BoolToInt(cycle)
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Copies the entire contents of a TransferBuffer to a Buffer.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public void UploadToBuffer(
 | 
			
		||||
		TransferBuffer source,
 | 
			
		||||
		Buffer destination,
 | 
			
		||||
		bool cycle
 | 
			
		||||
	) {
 | 
			
		||||
		UploadToBuffer(
 | 
			
		||||
			new TransferBufferLocation(source),
 | 
			
		||||
			new BufferRegion(destination, 0, destination.Size),
 | 
			
		||||
			cycle
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Copies data element-wise into from a TransferBuffer to a Buffer.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public void UploadToBuffer<T>(
 | 
			
		||||
		TransferBuffer source,
 | 
			
		||||
		Buffer destination,
 | 
			
		||||
		uint sourceStartElement,
 | 
			
		||||
		uint destinationStartElement,
 | 
			
		||||
		uint numElements,
 | 
			
		||||
		bool cycle
 | 
			
		||||
	) where T : unmanaged
 | 
			
		||||
	{
 | 
			
		||||
		int elementSize = Marshal.SizeOf<T>();
 | 
			
		||||
		uint dataLengthInBytes = (uint) (elementSize * numElements);
 | 
			
		||||
		uint srcOffsetInBytes = (uint) (elementSize * sourceStartElement);
 | 
			
		||||
		uint dstOffsetInBytes = (uint) (elementSize * destinationStartElement);
 | 
			
		||||
 | 
			
		||||
		UploadToBuffer(
 | 
			
		||||
			new TransferBufferLocation(source, srcOffsetInBytes),
 | 
			
		||||
			new BufferRegion(destination, dstOffsetInBytes, dataLengthInBytes),
 | 
			
		||||
			cycle
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Copies the contents of a TextureLocation to another TextureLocation.
 | 
			
		||||
	/// This copy occurs on the GPU timeline.
 | 
			
		||||
	///
 | 
			
		||||
	/// You MAY assume that the copy has finished in subsequent commands.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public void CopyTextureToTexture(
 | 
			
		||||
		in TextureLocation source,
 | 
			
		||||
		in TextureLocation destination,
 | 
			
		||||
		uint w,
 | 
			
		||||
		uint h,
 | 
			
		||||
		uint d,
 | 
			
		||||
		bool cycle
 | 
			
		||||
	) {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
		AssertTextureBoundsCheck(source, w, h, d);
 | 
			
		||||
		AssertTextureBoundsCheck(destination, w, h, d);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		Refresh.Refresh_CopyTextureToTexture(
 | 
			
		||||
			Handle,
 | 
			
		||||
			source.ToRefresh(),
 | 
			
		||||
			destination.ToRefresh(),
 | 
			
		||||
			w,
 | 
			
		||||
			h,
 | 
			
		||||
			d,
 | 
			
		||||
			Conversions.BoolToInt(cycle)
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Copies data from a Buffer to another Buffer.
 | 
			
		||||
	/// This copy occurs on the GPU timeline.
 | 
			
		||||
	///
 | 
			
		||||
	/// You MAY assume that the copy has finished in subsequent commands.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public void CopyBufferToBuffer(
 | 
			
		||||
		in BufferLocation source,
 | 
			
		||||
		in BufferLocation destination,
 | 
			
		||||
		uint size,
 | 
			
		||||
		bool cycle
 | 
			
		||||
	) {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
		AssertBufferBoundsCheck(source.Buffer.Size, source.Offset, size);
 | 
			
		||||
		AssertBufferBoundsCheck(destination.Buffer.Size, destination.Offset, size);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		Refresh.Refresh_CopyBufferToBuffer(
 | 
			
		||||
			Handle,
 | 
			
		||||
			source.ToRefresh(),
 | 
			
		||||
			destination.ToRefresh(),
 | 
			
		||||
			size,
 | 
			
		||||
			Conversions.BoolToInt(cycle)
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void DownloadFromBuffer(
 | 
			
		||||
		in BufferRegion source,
 | 
			
		||||
		in TransferBufferLocation destination
 | 
			
		||||
	) {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
		AssertBufferBoundsCheck(source.Buffer.Size, source.Offset, source.Size);
 | 
			
		||||
		AssertBufferBoundsCheck(destination.TransferBuffer.Size, destination.Offset, source.Size);
 | 
			
		||||
		AssertTransferBufferNotMapped(destination.TransferBuffer);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		Refresh.Refresh_DownloadFromBuffer(
 | 
			
		||||
			Handle,
 | 
			
		||||
			source.ToRefresh(),
 | 
			
		||||
			destination.ToRefresh()
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void DownloadFromTexture(
 | 
			
		||||
		in TextureRegion source,
 | 
			
		||||
		in TextureTransferInfo destination
 | 
			
		||||
	) {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
		AssertTransferBufferNotMapped(destination.TransferBuffer);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		Refresh.Refresh_DownloadFromTexture(
 | 
			
		||||
			Handle,
 | 
			
		||||
			source.ToRefresh(),
 | 
			
		||||
			destination.ToRefresh()
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
	private void AssertBufferBoundsCheck(uint bufferLengthInBytes, uint offsetInBytes, uint copyLengthInBytes)
 | 
			
		||||
	{
 | 
			
		||||
		if (copyLengthInBytes > bufferLengthInBytes + offsetInBytes)
 | 
			
		||||
		{
 | 
			
		||||
			throw new System.InvalidOperationException($"SetBufferData overflow! buffer length {bufferLengthInBytes}, offset {offsetInBytes}, copy length {copyLengthInBytes}");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void AssertTextureBoundsCheck(in TextureLocation textureLocation, uint w, uint h, uint d)
 | 
			
		||||
	{
 | 
			
		||||
		if (
 | 
			
		||||
			textureLocation.X + w > textureLocation.TextureSlice.Texture.Width ||
 | 
			
		||||
			textureLocation.Y + h > textureLocation.TextureSlice.Texture.Height ||
 | 
			
		||||
			textureLocation.Z + d > textureLocation.TextureSlice.Texture.Depth
 | 
			
		||||
		) {
 | 
			
		||||
			throw new System.InvalidOperationException($"Texture data is out of bounds!");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void AssertTransferBufferNotMapped(TransferBuffer transferBuffer)
 | 
			
		||||
	{
 | 
			
		||||
		if (transferBuffer.Mapped)
 | 
			
		||||
		{
 | 
			
		||||
			throw new System.InvalidOperationException("Transfer buffer must not be mapped!");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								Nerfed.Runtime/Graphics/CopyPassPool.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								Nerfed.Runtime/Graphics/CopyPassPool.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
internal class CopyPassPool
 | 
			
		||||
{
 | 
			
		||||
	private ConcurrentQueue<CopyPass> CopyPasses = new ConcurrentQueue<CopyPass>();
 | 
			
		||||
 | 
			
		||||
	public CopyPass Obtain()
 | 
			
		||||
	{
 | 
			
		||||
		if (CopyPasses.TryDequeue(out CopyPass copyPass))
 | 
			
		||||
		{
 | 
			
		||||
			return copyPass;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			return new CopyPass();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void Return(CopyPass copyPass)
 | 
			
		||||
	{
 | 
			
		||||
		CopyPasses.Enqueue(copyPass);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										716
									
								
								Nerfed.Runtime/Graphics/EmbeddedShadersSpirV.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										716
									
								
								Nerfed.Runtime/Graphics/EmbeddedShadersSpirV.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,716 @@
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
internal class EmbeddedShadersSpirV : IEmbeddedShaders
 | 
			
		||||
{
 | 
			
		||||
    public ShaderFormat ShaderFormat => ShaderFormat.SPIRV;
 | 
			
		||||
 | 
			
		||||
    public byte[] FullscreenVert { get; } =
 | 
			
		||||
    [
 | 
			
		||||
        0x3, 0x2, 0x23, 0x7, 0x0, 0x0, 0x1, 0x0, 0xB, 0x0,
 | 
			
		||||
        0x8, 0x0, 0x2E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x11, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0xB, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x1, 0x0, 0x0, 0x0, 0x47, 0x4C, 0x53, 0x4C,
 | 
			
		||||
        0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xE, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0xF, 0x0, 0x8, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x6D, 0x61, 0x69, 0x6E,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0xC, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1D, 0x0, 0x0, 0x0, 0x3, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x2, 0x0, 0x0, 0x0, 0xC2, 0x1, 0x0, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x6D, 0x61, 0x69, 0x6E,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x5, 0x0, 0x9, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x6F, 0x75, 0x74, 0x54, 0x65, 0x78, 0x43, 0x6F,
 | 
			
		||||
        0x6F, 0x72, 0x64, 0x0, 0x5, 0x0, 0x6, 0x0, 0xC, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x67, 0x6C, 0x5F, 0x56, 0x65, 0x72, 0x74, 0x65,
 | 
			
		||||
        0x78, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x0, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x1B, 0x0, 0x0, 0x0, 0x67, 0x6C, 0x5F, 0x50,
 | 
			
		||||
        0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x6, 0x0, 0x6, 0x0, 0x1B, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x73,
 | 
			
		||||
        0x69, 0x74, 0x69, 0x6F, 0x6E, 0x0, 0x6, 0x0, 0x7, 0x0,
 | 
			
		||||
        0x1B, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x67, 0x6C,
 | 
			
		||||
        0x5F, 0x50, 0x6F, 0x69, 0x6E, 0x74, 0x53, 0x69, 0x7A, 0x65,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0x7, 0x0, 0x1B, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x67, 0x6C, 0x5F, 0x43,
 | 
			
		||||
        0x6C, 0x69, 0x70, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6E, 0x63,
 | 
			
		||||
        0x65, 0x0, 0x6, 0x0, 0x7, 0x0, 0x1B, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3, 0x0, 0x0, 0x0, 0x67, 0x6C, 0x5F, 0x43, 0x75, 0x6C,
 | 
			
		||||
        0x6C, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x0,
 | 
			
		||||
        0x5, 0x0, 0x3, 0x0, 0x1D, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x47, 0x0, 0x4, 0x0, 0x9, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x47, 0x0,
 | 
			
		||||
        0x4, 0x0, 0xC, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x2A, 0x0, 0x0, 0x0, 0x48, 0x0, 0x5, 0x0, 0x1B, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x48, 0x0, 0x5, 0x0, 0x1B, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0x48, 0x0, 0x5, 0x0, 0x1B, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3, 0x0, 0x0, 0x0, 0x48, 0x0, 0x5, 0x0, 0x1B, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x0, 0x0, 0x47, 0x0, 0x3, 0x0, 0x1B, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x13, 0x0, 0x2, 0x0,
 | 
			
		||||
        0x2, 0x0, 0x0, 0x0, 0x21, 0x0, 0x3, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x16, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x17, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x7, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x2, 0x0, 0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x8, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3B, 0x0, 0x4, 0x0, 0x8, 0x0, 0x0, 0x0, 0x9, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x15, 0x0, 0x4, 0x0,
 | 
			
		||||
        0xA, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x1, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0xB, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0xA, 0x0, 0x0, 0x0, 0x3B, 0x0,
 | 
			
		||||
        0x4, 0x0, 0xB, 0x0, 0x0, 0x0, 0xC, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0xA, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xE, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x2B, 0x0, 0x4, 0x0, 0xA, 0x0, 0x0, 0x0, 0x10, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x17, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x17, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x15, 0x0, 0x4, 0x0, 0x18, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2B, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x18, 0x0, 0x0, 0x0, 0x19, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0x1C, 0x0, 0x4, 0x0, 0x1A, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x19, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1E, 0x0, 0x6, 0x0, 0x1B, 0x0, 0x0, 0x0, 0x17, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x1A, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1A, 0x0, 0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x1C, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x1B, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3B, 0x0, 0x4, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x1D, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0,
 | 
			
		||||
        0xA, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x2B, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0xC0, 0x2C, 0x0, 0x5, 0x0, 0x7, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x21, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0xBF,
 | 
			
		||||
        0x2B, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x25, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x80, 0x3F, 0x2C, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x7, 0x0, 0x0, 0x0, 0x26, 0x0, 0x0, 0x0, 0x24, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x25, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x2C, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3, 0x0, 0x0, 0x0, 0x17, 0x0, 0x0, 0x0, 0x36, 0x0,
 | 
			
		||||
        0x5, 0x0, 0x2, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xF8, 0x0,
 | 
			
		||||
        0x2, 0x0, 0x5, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0,
 | 
			
		||||
        0xA, 0x0, 0x0, 0x0, 0xD, 0x0, 0x0, 0x0, 0xC, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xC4, 0x0, 0x5, 0x0, 0xA, 0x0, 0x0, 0x0,
 | 
			
		||||
        0xF, 0x0, 0x0, 0x0, 0xD, 0x0, 0x0, 0x0, 0xE, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xC7, 0x0, 0x5, 0x0, 0xA, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x11, 0x0, 0x0, 0x0, 0xF, 0x0, 0x0, 0x0, 0x10, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x6F, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x12, 0x0, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0, 0x3D, 0x0,
 | 
			
		||||
        0x4, 0x0, 0xA, 0x0, 0x0, 0x0, 0x13, 0x0, 0x0, 0x0,
 | 
			
		||||
        0xC, 0x0, 0x0, 0x0, 0xC7, 0x0, 0x5, 0x0, 0xA, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x13, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x10, 0x0, 0x0, 0x0, 0x6F, 0x0, 0x4, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x15, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x50, 0x0, 0x5, 0x0, 0x7, 0x0, 0x0, 0x0, 0x16, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x15, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3E, 0x0, 0x3, 0x0, 0x9, 0x0, 0x0, 0x0, 0x16, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x7, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1F, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x85, 0x0,
 | 
			
		||||
        0x5, 0x0, 0x7, 0x0, 0x0, 0x0, 0x23, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1F, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x81, 0x0,
 | 
			
		||||
        0x5, 0x0, 0x7, 0x0, 0x0, 0x0, 0x27, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x23, 0x0, 0x0, 0x0, 0x26, 0x0, 0x0, 0x0, 0x51, 0x0,
 | 
			
		||||
        0x5, 0x0, 0x6, 0x0, 0x0, 0x0, 0x29, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x27, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x51, 0x0,
 | 
			
		||||
        0x5, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2A, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x27, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x50, 0x0,
 | 
			
		||||
        0x7, 0x0, 0x17, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x29, 0x0, 0x0, 0x0, 0x2A, 0x0, 0x0, 0x0, 0x28, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x25, 0x0, 0x0, 0x0, 0x41, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x2C, 0x0, 0x0, 0x0, 0x2D, 0x0, 0x0, 0x0, 0x1D, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x2D, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x0, 0x0, 0xFD, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x38, 0x0, 0x1, 0x0,
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    public byte[] TextMsdfFrag { get; } =
 | 
			
		||||
    [
 | 
			
		||||
        0x3, 0x2, 0x23, 0x7, 0x0, 0x0, 0x1, 0x0, 0xB, 0x0,
 | 
			
		||||
        0x8, 0x0, 0x6C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x11, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x11, 0x0,
 | 
			
		||||
        0x2, 0x0, 0x32, 0x0, 0x0, 0x0, 0xB, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73,
 | 
			
		||||
        0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0xE, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xF, 0x0, 0x8, 0x0, 0x4, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x0, 0x0, 0x6D, 0x61, 0x69, 0x6E, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x36, 0x0, 0x0, 0x0, 0x64, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x67, 0x0, 0x0, 0x0, 0x10, 0x0, 0x3, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x3, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x2, 0x0, 0x0, 0x0, 0xC2, 0x1, 0x0, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x6D, 0x61, 0x69, 0x6E,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x7, 0x0, 0xC, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x6E, 0x28, 0x66,
 | 
			
		||||
        0x31, 0x3B, 0x66, 0x31, 0x3B, 0x66, 0x31, 0x3B, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x5, 0x0, 0x3, 0x0, 0x9, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x72, 0x0, 0x0, 0x0, 0x5, 0x0, 0x3, 0x0, 0xA, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x67, 0x0, 0x0, 0x0, 0x5, 0x0, 0x3, 0x0,
 | 
			
		||||
        0xB, 0x0, 0x0, 0x0, 0x62, 0x0, 0x0, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x6, 0x0, 0xF, 0x0, 0x0, 0x0, 0x73, 0x63, 0x72, 0x65,
 | 
			
		||||
        0x65, 0x6E, 0x50, 0x78, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x28,
 | 
			
		||||
        0x0, 0x0, 0x5, 0x0, 0x5, 0x0, 0x1E, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x75, 0x6E, 0x69, 0x74, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x5, 0x0, 0x3, 0x0, 0x1F, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x55, 0x42, 0x4F, 0x0, 0x6, 0x0, 0x5, 0x0, 0x1F, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x70, 0x78, 0x52, 0x61,
 | 
			
		||||
        0x6E, 0x67, 0x65, 0x0, 0x5, 0x0, 0x3, 0x0, 0x21, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x75, 0x62, 0x6F, 0x0, 0x5, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x2B, 0x0, 0x0, 0x0, 0x6D, 0x73, 0x64, 0x66, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x5, 0x0, 0x6, 0x0, 0x32, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x73, 0x63, 0x72, 0x65, 0x65, 0x6E, 0x54, 0x65, 0x78, 0x53,
 | 
			
		||||
        0x69, 0x7A, 0x65, 0x0, 0x0, 0x0, 0x5, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x36, 0x0, 0x0, 0x0, 0x69, 0x6E, 0x54, 0x65, 0x78, 0x43,
 | 
			
		||||
        0x6F, 0x6F, 0x72, 0x64, 0x0, 0x0, 0x5, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x44, 0x0, 0x0, 0x0, 0x6D, 0x73, 0x64, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x3, 0x0, 0x4A, 0x0, 0x0, 0x0, 0x73, 0x64, 0x0, 0x0,
 | 
			
		||||
        0x5, 0x0, 0x4, 0x0, 0x4B, 0x0, 0x0, 0x0, 0x70, 0x61,
 | 
			
		||||
        0x72, 0x61, 0x6D, 0x0, 0x0, 0x0, 0x5, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x50, 0x0, 0x0, 0x0, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x5, 0x0, 0x4, 0x0, 0x54, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x70, 0x61, 0x72, 0x61, 0x6D, 0x0, 0x0, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x7, 0x0, 0x59, 0x0, 0x0, 0x0, 0x73, 0x63, 0x72, 0x65,
 | 
			
		||||
        0x65, 0x6E, 0x50, 0x78, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6E,
 | 
			
		||||
        0x63, 0x65, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x5E, 0x0, 0x0, 0x0, 0x6F, 0x70, 0x61, 0x63, 0x69, 0x74,
 | 
			
		||||
        0x79, 0x0, 0x5, 0x0, 0x5, 0x0, 0x64, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x6F, 0x75, 0x74, 0x43, 0x6F, 0x6C, 0x6F, 0x72, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x5, 0x0, 0x4, 0x0, 0x67, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x69, 0x6E, 0x43, 0x6F, 0x6C, 0x6F, 0x72, 0x0, 0x48, 0x0,
 | 
			
		||||
        0x5, 0x0, 0x1F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x23, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x47, 0x0,
 | 
			
		||||
        0x3, 0x0, 0x1F, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x47, 0x0, 0x4, 0x0, 0x21, 0x0, 0x0, 0x0, 0x22, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x21, 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x47, 0x0, 0x4, 0x0, 0x2B, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x22, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x47, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x2B, 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0, 0x36, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x47, 0x0, 0x4, 0x0, 0x64, 0x0, 0x0, 0x0, 0x1E, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x67, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x1, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x13, 0x0, 0x2, 0x0, 0x2, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x21, 0x0, 0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x2, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x16, 0x0, 0x3, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x20, 0x0, 0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x7, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x21, 0x0, 0x6, 0x0, 0x8, 0x0, 0x0, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x7, 0x0, 0x0, 0x0, 0x21, 0x0, 0x3, 0x0, 0xE, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x17, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x1C, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x1D, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x7, 0x0, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x1E, 0x0,
 | 
			
		||||
        0x3, 0x0, 0x1F, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x20, 0x0, 0x4, 0x0, 0x20, 0x0, 0x0, 0x0, 0x2, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1F, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x20, 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0, 0x2, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x15, 0x0, 0x4, 0x0, 0x22, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x20, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2B, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x22, 0x0, 0x0, 0x0, 0x23, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x24, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x19, 0x0, 0x9, 0x0, 0x28, 0x0, 0x0, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1B, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x29, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x20, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x2A, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x29, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x2A, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x17, 0x0, 0x4, 0x0, 0x2E, 0x0, 0x0, 0x0, 0x22, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x0, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x80, 0x3F, 0x2C, 0x0, 0x5, 0x0, 0x1C, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x34, 0x0, 0x0, 0x0, 0x33, 0x0, 0x0, 0x0, 0x33, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x35, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x3B, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x35, 0x0, 0x0, 0x0, 0x36, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3A, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3F,
 | 
			
		||||
        0x17, 0x0, 0x4, 0x0, 0x42, 0x0, 0x0, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x20, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x43, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x42, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x17, 0x0, 0x4, 0x0, 0x47, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x15, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x4C, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x4C, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x4D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x2B, 0x0, 0x4, 0x0, 0x4C, 0x0, 0x0, 0x0, 0x51, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x4C, 0x0, 0x0, 0x0, 0x55, 0x0, 0x0, 0x0, 0x2, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x61, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x63, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x47, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x63, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x64, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x2C, 0x0, 0x7, 0x0, 0x47, 0x0, 0x0, 0x0, 0x65, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x61, 0x0, 0x0, 0x0, 0x61, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x61, 0x0, 0x0, 0x0, 0x61, 0x0, 0x0, 0x0, 0x20, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x66, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x47, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x66, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x67, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x36, 0x0, 0x5, 0x0, 0x2, 0x0, 0x0, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
 | 
			
		||||
        0xF8, 0x0, 0x2, 0x0, 0x5, 0x0, 0x0, 0x0, 0x3B, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x43, 0x0, 0x0, 0x0, 0x44, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x7, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x7, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x4A, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3B, 0x0, 0x4, 0x0, 0x7, 0x0, 0x0, 0x0, 0x4B, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x7, 0x0, 0x0, 0x0, 0x50, 0x0, 0x0, 0x0, 0x7, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x7, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x54, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x3B, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x7, 0x0, 0x0, 0x0, 0x59, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x7, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x7, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x5E, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3D, 0x0, 0x4, 0x0, 0x29, 0x0, 0x0, 0x0, 0x45, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2B, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x1C, 0x0, 0x0, 0x0, 0x46, 0x0, 0x0, 0x0, 0x36, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x57, 0x0, 0x5, 0x0, 0x47, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x48, 0x0, 0x0, 0x0, 0x45, 0x0, 0x0, 0x0, 0x46, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x4F, 0x0, 0x8, 0x0, 0x42, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x49, 0x0, 0x0, 0x0, 0x48, 0x0, 0x0, 0x0, 0x48, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x2, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x44, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x49, 0x0, 0x0, 0x0, 0x41, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x7, 0x0, 0x0, 0x0, 0x4E, 0x0, 0x0, 0x0, 0x44, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x4D, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x0, 0x0, 0x4F, 0x0, 0x0, 0x0, 0x4E, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x4B, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x4F, 0x0, 0x0, 0x0, 0x41, 0x0, 0x5, 0x0, 0x7, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x52, 0x0, 0x0, 0x0, 0x44, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x51, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x53, 0x0, 0x0, 0x0, 0x52, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3E, 0x0, 0x3, 0x0, 0x50, 0x0, 0x0, 0x0, 0x53, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x41, 0x0, 0x5, 0x0, 0x7, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x56, 0x0, 0x0, 0x0, 0x44, 0x0, 0x0, 0x0, 0x55, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x57, 0x0, 0x0, 0x0, 0x56, 0x0, 0x0, 0x0, 0x3E, 0x0,
 | 
			
		||||
        0x3, 0x0, 0x54, 0x0, 0x0, 0x0, 0x57, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x39, 0x0, 0x7, 0x0, 0x6, 0x0, 0x0, 0x0, 0x58, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xC, 0x0, 0x0, 0x0, 0x4B, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x50, 0x0, 0x0, 0x0, 0x54, 0x0, 0x0, 0x0, 0x3E, 0x0,
 | 
			
		||||
        0x3, 0x0, 0x4A, 0x0, 0x0, 0x0, 0x58, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x39, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x5A, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xF, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x0, 0x0, 0x5B, 0x0, 0x0, 0x0, 0x4A, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x83, 0x0, 0x5, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x5C, 0x0, 0x0, 0x0, 0x5B, 0x0, 0x0, 0x0, 0x3A, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x85, 0x0, 0x5, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x5D, 0x0, 0x0, 0x0, 0x5A, 0x0, 0x0, 0x0, 0x5C, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x59, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x5D, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x5F, 0x0, 0x0, 0x0, 0x59, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x81, 0x0, 0x5, 0x0, 0x6, 0x0, 0x0, 0x0, 0x60, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x5F, 0x0, 0x0, 0x0, 0x3A, 0x0, 0x0, 0x0,
 | 
			
		||||
        0xC, 0x0, 0x8, 0x0, 0x6, 0x0, 0x0, 0x0, 0x62, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x60, 0x0, 0x0, 0x0, 0x61, 0x0, 0x0, 0x0, 0x33, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x5E, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x62, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x47, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x68, 0x0, 0x0, 0x0, 0x67, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3D, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x69, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x5E, 0x0, 0x0, 0x0, 0x50, 0x0, 0x7, 0x0,
 | 
			
		||||
        0x47, 0x0, 0x0, 0x0, 0x6A, 0x0, 0x0, 0x0, 0x69, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x69, 0x0, 0x0, 0x0, 0x69, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x69, 0x0, 0x0, 0x0, 0xC, 0x0, 0x8, 0x0, 0x47, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x6B, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x2E, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0x68, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x6A, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x64, 0x0, 0x0, 0x0, 0x6B, 0x0, 0x0, 0x0, 0xFD, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x38, 0x0, 0x1, 0x0, 0x36, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x0, 0x0, 0xC, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x37, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x7, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x37, 0x0,
 | 
			
		||||
        0x3, 0x0, 0x7, 0x0, 0x0, 0x0, 0xA, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x37, 0x0, 0x3, 0x0, 0x7, 0x0, 0x0, 0x0, 0xB, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xF8, 0x0, 0x2, 0x0, 0xD, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3D, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x11, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0xA, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xC, 0x0, 0x7, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x13, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x25, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x11, 0x0, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3D, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x14, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x0, 0x0, 0x15, 0x0, 0x0, 0x0, 0xA, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xC, 0x0, 0x7, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x16, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x28, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x15, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3D, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x17, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xB, 0x0, 0x0, 0x0, 0xC, 0x0, 0x7, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x1, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x25, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x17, 0x0, 0x0, 0x0, 0xC, 0x0, 0x7, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x19, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x28, 0x0, 0x0, 0x0, 0x13, 0x0, 0x0, 0x0, 0x18, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xFE, 0x0, 0x2, 0x0, 0x19, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x38, 0x0, 0x1, 0x0, 0x36, 0x0, 0x5, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0xE, 0x0, 0x0, 0x0, 0xF8, 0x0, 0x2, 0x0, 0x10, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x1D, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1E, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x3B, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x1D, 0x0, 0x0, 0x0, 0x32, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x7, 0x0, 0x0, 0x0, 0x41, 0x0, 0x5, 0x0, 0x24, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x25, 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x23, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x26, 0x0, 0x0, 0x0, 0x25, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x50, 0x0, 0x5, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x27, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x26, 0x0, 0x0, 0x0, 0x26, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3D, 0x0, 0x4, 0x0, 0x29, 0x0, 0x0, 0x0, 0x2C, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2B, 0x0, 0x0, 0x0, 0x64, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x28, 0x0, 0x0, 0x0, 0x2D, 0x0, 0x0, 0x0, 0x2C, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x67, 0x0, 0x5, 0x0, 0x2E, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x2F, 0x0, 0x0, 0x0, 0x2D, 0x0, 0x0, 0x0, 0x23, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x6F, 0x0, 0x4, 0x0, 0x1C, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x30, 0x0, 0x0, 0x0, 0x2F, 0x0, 0x0, 0x0, 0x88, 0x0,
 | 
			
		||||
        0x5, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x31, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x27, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x3E, 0x0,
 | 
			
		||||
        0x3, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x31, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3D, 0x0, 0x4, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x37, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x36, 0x0, 0x0, 0x0, 0xD1, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x1C, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0, 0x37, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x88, 0x0, 0x5, 0x0, 0x1C, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x39, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x38, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x32, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x39, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x1C, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3B, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3D, 0x0, 0x4, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x3C, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x32, 0x0, 0x0, 0x0, 0x94, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x0, 0x0, 0x3B, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3C, 0x0, 0x0, 0x0, 0x85, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x3A, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3D, 0x0, 0x0, 0x0, 0xC, 0x0, 0x7, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x0, 0x0, 0x3F, 0x0, 0x0, 0x0, 0x1, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x33, 0x0, 0x0, 0x0, 0xFE, 0x0, 0x2, 0x0, 0x3F, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x38, 0x0, 0x1, 0x0,
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    public byte[] TextTransformVert { get; } =
 | 
			
		||||
    [
 | 
			
		||||
        0x3, 0x2, 0x23, 0x7, 0x0, 0x0, 0x1, 0x0, 0xB, 0x0,
 | 
			
		||||
        0x8, 0x0, 0x2D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x11, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0xB, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x1, 0x0, 0x0, 0x0, 0x47, 0x4C, 0x53, 0x4C,
 | 
			
		||||
        0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xE, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0xF, 0x0, 0xB, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x6D, 0x61, 0x69, 0x6E,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0xD, 0x0, 0x0, 0x0, 0x19, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x25, 0x0, 0x0, 0x0, 0x27, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x29, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x0, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x3, 0x0, 0x2, 0x0, 0x0, 0x0, 0xC2, 0x1, 0x0, 0x0,
 | 
			
		||||
        0x5, 0x0, 0x4, 0x0, 0x4, 0x0, 0x0, 0x0, 0x6D, 0x61,
 | 
			
		||||
        0x69, 0x6E, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x6, 0x0,
 | 
			
		||||
        0xB, 0x0, 0x0, 0x0, 0x67, 0x6C, 0x5F, 0x50, 0x65, 0x72,
 | 
			
		||||
        0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x6, 0x0, 0xB, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x73, 0x69, 0x74,
 | 
			
		||||
        0x69, 0x6F, 0x6E, 0x0, 0x6, 0x0, 0x7, 0x0, 0xB, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x67, 0x6C, 0x5F, 0x50,
 | 
			
		||||
        0x6F, 0x69, 0x6E, 0x74, 0x53, 0x69, 0x7A, 0x65, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x6, 0x0, 0x7, 0x0, 0xB, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x2, 0x0, 0x0, 0x0, 0x67, 0x6C, 0x5F, 0x43, 0x6C, 0x69,
 | 
			
		||||
        0x70, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x7, 0x0, 0xB, 0x0, 0x0, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x67, 0x6C, 0x5F, 0x43, 0x75, 0x6C, 0x6C, 0x44,
 | 
			
		||||
        0x69, 0x73, 0x74, 0x61, 0x6E, 0x63, 0x65, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x3, 0x0, 0xD, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x5, 0x0, 0x3, 0x0, 0x11, 0x0, 0x0, 0x0, 0x55, 0x42,
 | 
			
		||||
        0x4F, 0x0, 0x6, 0x0, 0x7, 0x0, 0x11, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72,
 | 
			
		||||
        0x6F, 0x6A, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x0, 0x0,
 | 
			
		||||
        0x5, 0x0, 0x3, 0x0, 0x13, 0x0, 0x0, 0x0, 0x75, 0x62,
 | 
			
		||||
        0x6F, 0x0, 0x5, 0x0, 0x4, 0x0, 0x19, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x69, 0x6E, 0x50, 0x6F, 0x73, 0x0, 0x0, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x5, 0x0, 0x25, 0x0, 0x0, 0x0, 0x6F, 0x75, 0x74, 0x54,
 | 
			
		||||
        0x65, 0x78, 0x43, 0x6F, 0x6F, 0x72, 0x64, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x5, 0x0, 0x27, 0x0, 0x0, 0x0, 0x69, 0x6E, 0x54, 0x65,
 | 
			
		||||
        0x78, 0x43, 0x6F, 0x6F, 0x72, 0x64, 0x0, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x5, 0x0, 0x29, 0x0, 0x0, 0x0, 0x6F, 0x75, 0x74, 0x43,
 | 
			
		||||
        0x6F, 0x6C, 0x6F, 0x72, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x2B, 0x0, 0x0, 0x0, 0x69, 0x6E, 0x43, 0x6F,
 | 
			
		||||
        0x6C, 0x6F, 0x72, 0x0, 0x48, 0x0, 0x5, 0x0, 0xB, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x48, 0x0, 0x5, 0x0, 0xB, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0x48, 0x0, 0x5, 0x0, 0xB, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3, 0x0, 0x0, 0x0, 0x48, 0x0, 0x5, 0x0, 0xB, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x0, 0x0, 0x47, 0x0, 0x3, 0x0, 0xB, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x48, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x48, 0x0, 0x5, 0x0, 0x11, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x23, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x48, 0x0, 0x5, 0x0, 0x11, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x10, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x47, 0x0, 0x3, 0x0, 0x11, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x2, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0, 0x13, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x47, 0x0, 0x4, 0x0, 0x13, 0x0, 0x0, 0x0, 0x21, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x19, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x47, 0x0, 0x4, 0x0, 0x25, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x47, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x27, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0, 0x29, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x47, 0x0, 0x4, 0x0, 0x2B, 0x0, 0x0, 0x0, 0x1E, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x13, 0x0, 0x2, 0x0,
 | 
			
		||||
        0x2, 0x0, 0x0, 0x0, 0x21, 0x0, 0x3, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x16, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x17, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x7, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x0, 0x0, 0x15, 0x0, 0x4, 0x0, 0x8, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x2B, 0x0, 0x4, 0x0, 0x8, 0x0, 0x0, 0x0, 0x9, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1C, 0x0, 0x4, 0x0,
 | 
			
		||||
        0xA, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x9, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1E, 0x0, 0x6, 0x0, 0xB, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x7, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0xA, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xA, 0x0, 0x0, 0x0, 0x20, 0x0, 0x4, 0x0,
 | 
			
		||||
        0xC, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xB, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0xC, 0x0, 0x0, 0x0,
 | 
			
		||||
        0xD, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x15, 0x0,
 | 
			
		||||
        0x4, 0x0, 0xE, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0xE, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x18, 0x0, 0x4, 0x0, 0x10, 0x0, 0x0, 0x0, 0x7, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x11, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x20, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x12, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x11, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x12, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x13, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x20, 0x0, 0x4, 0x0, 0x14, 0x0, 0x0, 0x0, 0x2, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x17, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x17, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x18, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0x17, 0x0, 0x0, 0x0, 0x3B, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x18, 0x0, 0x0, 0x0, 0x19, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3F,
 | 
			
		||||
        0x20, 0x0, 0x4, 0x0, 0x21, 0x0, 0x0, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x17, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x23, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x24, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3, 0x0, 0x0, 0x0, 0x23, 0x0, 0x0, 0x0, 0x3B, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x24, 0x0, 0x0, 0x0, 0x25, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3, 0x0, 0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x26, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x23, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3B, 0x0, 0x4, 0x0, 0x26, 0x0, 0x0, 0x0, 0x27, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x21, 0x0, 0x0, 0x0, 0x29, 0x0, 0x0, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x2A, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x3B, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x2A, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0x36, 0x0, 0x5, 0x0, 0x2, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3, 0x0, 0x0, 0x0, 0xF8, 0x0, 0x2, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x41, 0x0, 0x5, 0x0, 0x14, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x15, 0x0, 0x0, 0x0, 0x13, 0x0, 0x0, 0x0, 0xF, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x10, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x16, 0x0, 0x0, 0x0, 0x15, 0x0, 0x0, 0x0, 0x3D, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x17, 0x0, 0x0, 0x0, 0x1A, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x19, 0x0, 0x0, 0x0, 0x51, 0x0, 0x5, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x1A, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x51, 0x0, 0x5, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1D, 0x0, 0x0, 0x0, 0x1A, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0x51, 0x0, 0x5, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x1A, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x2, 0x0, 0x0, 0x0, 0x50, 0x0, 0x7, 0x0, 0x7, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1F, 0x0, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1D, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x1B, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x91, 0x0, 0x5, 0x0, 0x7, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x20, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x1F, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x41, 0x0, 0x5, 0x0, 0x21, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x22, 0x0, 0x0, 0x0, 0xD, 0x0, 0x0, 0x0, 0xF, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x22, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x20, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x23, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x27, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3E, 0x0, 0x3, 0x0, 0x25, 0x0, 0x0, 0x0, 0x28, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x7, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x2C, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x0, 0x0, 0x3E, 0x0,
 | 
			
		||||
        0x3, 0x0, 0x29, 0x0, 0x0, 0x0, 0x2C, 0x0, 0x0, 0x0,
 | 
			
		||||
        0xFD, 0x0, 0x1, 0x0, 0x38, 0x0, 0x1, 0x0,
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    public byte[] VideoYuv2RgbaFrag { get; } =
 | 
			
		||||
    [
 | 
			
		||||
        0x3, 0x2, 0x23, 0x7, 0x0, 0x0, 0x1, 0x0, 0xB, 0x0,
 | 
			
		||||
        0x8, 0x0, 0x45, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x11, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0xB, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x1, 0x0, 0x0, 0x0, 0x47, 0x4C, 0x53, 0x4C,
 | 
			
		||||
        0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xE, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0xF, 0x0, 0x7, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x6D, 0x61, 0x69, 0x6E,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0, 0x2E, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x10, 0x0, 0x3, 0x0, 0x4, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x7, 0x0, 0x0, 0x0, 0x3, 0x0, 0x3, 0x0, 0x2, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xC2, 0x1, 0x0, 0x0, 0x5, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x0, 0x0, 0x6D, 0x61, 0x69, 0x6E, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x5, 0x0, 0x3, 0x0, 0x9, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x79, 0x75, 0x76, 0x0, 0x5, 0x0, 0x5, 0x0, 0xD, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x59, 0x53, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x72,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x5, 0x0, 0x11, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x54, 0x65, 0x78, 0x43, 0x6F, 0x6F, 0x72, 0x64,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x5, 0x0, 0x1A, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x55, 0x53, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x72,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x5, 0x0, 0x21, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x56, 0x53, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x72,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x5, 0x0, 0x2E, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6F, 0x6C, 0x6F,
 | 
			
		||||
        0x72, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0, 0xD, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x47, 0x0, 0x4, 0x0, 0xD, 0x0, 0x0, 0x0, 0x21, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x11, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x47, 0x0, 0x4, 0x0, 0x1A, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x22, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x47, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x1A, 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0, 0x21, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x47, 0x0, 0x4, 0x0, 0x21, 0x0, 0x0, 0x0, 0x21, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x47, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x2E, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x13, 0x0, 0x2, 0x0, 0x2, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x21, 0x0, 0x3, 0x0, 0x3, 0x0, 0x0, 0x0, 0x2, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x16, 0x0, 0x3, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x20, 0x0, 0x0, 0x0, 0x17, 0x0, 0x4, 0x0, 0x7, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x20, 0x0, 0x4, 0x0, 0x8, 0x0, 0x0, 0x0, 0x7, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x19, 0x0, 0x9, 0x0,
 | 
			
		||||
        0xA, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x1, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1B, 0x0, 0x3, 0x0, 0xB, 0x0, 0x0, 0x0,
 | 
			
		||||
        0xA, 0x0, 0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0xC, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3B, 0x0, 0x4, 0x0, 0xC, 0x0, 0x0, 0x0, 0xD, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x17, 0x0, 0x4, 0x0,
 | 
			
		||||
        0xF, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x10, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0xF, 0x0, 0x0, 0x0, 0x3B, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x10, 0x0, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1, 0x0, 0x0, 0x0, 0x17, 0x0, 0x4, 0x0, 0x13, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x15, 0x0, 0x4, 0x0, 0x15, 0x0, 0x0, 0x0, 0x20, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x15, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x18, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x7, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x3B, 0x0,
 | 
			
		||||
        0x4, 0x0, 0xC, 0x0, 0x0, 0x0, 0x1A, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x15, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1F, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3B, 0x0, 0x4, 0x0, 0xC, 0x0, 0x0, 0x0, 0x21, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x15, 0x0, 0x0, 0x0, 0x26, 0x0, 0x0, 0x0, 0x2, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0xBD, 0x2B, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x29, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0xBF, 0x2C, 0x0, 0x6, 0x0, 0x7, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2A, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x29, 0x0, 0x0, 0x0, 0x29, 0x0, 0x0, 0x0, 0x20, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x2D, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x13, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x2D, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2E, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x2B, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x30, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xF4, 0xFD, 0x94, 0x3F, 0x2B, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x0, 0x0, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x32, 0x0, 0x0, 0x0, 0x6, 0x81, 0xE5, 0x3F, 0x2C, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x7, 0x0, 0x0, 0x0, 0x33, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x30, 0x0, 0x0, 0x0, 0x31, 0x0, 0x0, 0x0, 0x32, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x20, 0x0, 0x4, 0x0, 0x35, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2B, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x6, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0,
 | 
			
		||||
        0xAC, 0x1C, 0x5A, 0xBE, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0xB0, 0x72, 0x8, 0xBF,
 | 
			
		||||
        0x2C, 0x0, 0x6, 0x0, 0x7, 0x0, 0x0, 0x0, 0x3A, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x39, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x2, 0x2B, 0x7, 0x40,
 | 
			
		||||
        0x2C, 0x0, 0x6, 0x0, 0x7, 0x0, 0x0, 0x0, 0x3F, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x31, 0x0, 0x0, 0x0, 0x2B, 0x0, 0x4, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x42, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x3F,
 | 
			
		||||
        0x2B, 0x0, 0x4, 0x0, 0x15, 0x0, 0x0, 0x0, 0x43, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x36, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x2, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0xF8, 0x0, 0x2, 0x0,
 | 
			
		||||
        0x5, 0x0, 0x0, 0x0, 0x3B, 0x0, 0x4, 0x0, 0x8, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3D, 0x0, 0x4, 0x0, 0xB, 0x0, 0x0, 0x0, 0xE, 0x0,
 | 
			
		||||
        0x0, 0x0, 0xD, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0,
 | 
			
		||||
        0xF, 0x0, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x11, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x57, 0x0, 0x5, 0x0, 0x13, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x14, 0x0, 0x0, 0x0, 0xE, 0x0, 0x0, 0x0, 0x12, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x51, 0x0, 0x5, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x17, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x41, 0x0, 0x5, 0x0, 0x18, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x19, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x16, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x19, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x17, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0xB, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1B, 0x0, 0x0, 0x0, 0x1A, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3D, 0x0, 0x4, 0x0, 0xF, 0x0, 0x0, 0x0, 0x1C, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x11, 0x0, 0x0, 0x0, 0x57, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x13, 0x0, 0x0, 0x0, 0x1D, 0x0, 0x0, 0x0, 0x1B, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x51, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x1D, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x41, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x18, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x9, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x1F, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x20, 0x0, 0x0, 0x0, 0x1E, 0x0, 0x0, 0x0, 0x3D, 0x0,
 | 
			
		||||
        0x4, 0x0, 0xB, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x21, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0xF, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x23, 0x0, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x57, 0x0, 0x5, 0x0, 0x13, 0x0, 0x0, 0x0, 0x24, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x23, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x51, 0x0, 0x5, 0x0, 0x6, 0x0, 0x0, 0x0, 0x25, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x41, 0x0, 0x5, 0x0, 0x18, 0x0, 0x0, 0x0, 0x27, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x26, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3E, 0x0, 0x3, 0x0, 0x27, 0x0, 0x0, 0x0, 0x25, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3D, 0x0, 0x4, 0x0, 0x7, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x2B, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x81, 0x0,
 | 
			
		||||
        0x5, 0x0, 0x7, 0x0, 0x0, 0x0, 0x2C, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x2B, 0x0, 0x0, 0x0, 0x2A, 0x0, 0x0, 0x0, 0x3E, 0x0,
 | 
			
		||||
        0x3, 0x0, 0x9, 0x0, 0x0, 0x0, 0x2C, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3D, 0x0, 0x4, 0x0, 0x7, 0x0, 0x0, 0x0, 0x2F, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x94, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x6, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x2F, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x33, 0x0, 0x0, 0x0, 0x41, 0x0, 0x5, 0x0,
 | 
			
		||||
        0x35, 0x0, 0x0, 0x0, 0x36, 0x0, 0x0, 0x0, 0x2E, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x3, 0x0,
 | 
			
		||||
        0x36, 0x0, 0x0, 0x0, 0x34, 0x0, 0x0, 0x0, 0x3D, 0x0,
 | 
			
		||||
        0x4, 0x0, 0x7, 0x0, 0x0, 0x0, 0x37, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x9, 0x0, 0x0, 0x0, 0x94, 0x0, 0x5, 0x0, 0x6, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3B, 0x0, 0x0, 0x0, 0x37, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x3A, 0x0, 0x0, 0x0, 0x41, 0x0, 0x5, 0x0, 0x35, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3C, 0x0, 0x0, 0x0, 0x2E, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x1F, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x3C, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3B, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x4, 0x0,
 | 
			
		||||
        0x7, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x0, 0x0, 0x9, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x94, 0x0, 0x5, 0x0, 0x6, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x40, 0x0, 0x0, 0x0, 0x3D, 0x0, 0x0, 0x0, 0x3F, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x41, 0x0, 0x5, 0x0, 0x35, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x41, 0x0, 0x0, 0x0, 0x2E, 0x0, 0x0, 0x0, 0x26, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x41, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x40, 0x0, 0x0, 0x0, 0x41, 0x0, 0x5, 0x0, 0x35, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x44, 0x0, 0x0, 0x0, 0x2E, 0x0, 0x0, 0x0,
 | 
			
		||||
        0x43, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x3, 0x0, 0x44, 0x0,
 | 
			
		||||
        0x0, 0x0, 0x42, 0x0, 0x0, 0x0, 0xFD, 0x0, 0x1, 0x0,
 | 
			
		||||
        0x38, 0x0, 0x1, 0x0,
 | 
			
		||||
    ];
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								Nerfed.Runtime/Graphics/FencePool.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								Nerfed.Runtime/Graphics/FencePool.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
internal class FencePool
 | 
			
		||||
{
 | 
			
		||||
	private GraphicsDevice GraphicsDevice;
 | 
			
		||||
	private ConcurrentQueue<Fence> Fences = new ConcurrentQueue<Fence>();
 | 
			
		||||
 | 
			
		||||
	public FencePool(GraphicsDevice graphicsDevice)
 | 
			
		||||
	{
 | 
			
		||||
		GraphicsDevice = graphicsDevice;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Fence Obtain()
 | 
			
		||||
	{
 | 
			
		||||
		if (Fences.TryDequeue(out Fence fence))
 | 
			
		||||
		{
 | 
			
		||||
			return fence;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			return new Fence(GraphicsDevice);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void Return(Fence fence)
 | 
			
		||||
	{
 | 
			
		||||
		Fences.Enqueue(fence);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								Nerfed.Runtime/Graphics/Font/Enums.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								Nerfed.Runtime/Graphics/Font/Enums.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
public enum HorizontalAlignment
 | 
			
		||||
{
 | 
			
		||||
    Left,
 | 
			
		||||
    Center,
 | 
			
		||||
    Right
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public enum VerticalAlignment
 | 
			
		||||
{
 | 
			
		||||
    Baseline,
 | 
			
		||||
    Top,
 | 
			
		||||
    Middle,
 | 
			
		||||
    Bottom
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										123
									
								
								Nerfed.Runtime/Graphics/Font/Font.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								Nerfed.Runtime/Graphics/Font/Font.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,123 @@
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
using WellspringCS;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
public unsafe class Font : GraphicsResource
 | 
			
		||||
{
 | 
			
		||||
    public Texture Texture { get; }
 | 
			
		||||
    public float PixelsPerEm { get; }
 | 
			
		||||
    public float DistanceRange { get; }
 | 
			
		||||
 | 
			
		||||
    internal IntPtr Handle { get; }
 | 
			
		||||
 | 
			
		||||
    private byte* StringBytes;
 | 
			
		||||
    private int StringBytesLength;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Loads a TTF or OTF font from a path for use in MSDF rendering.
 | 
			
		||||
    /// Note that there must be an msdf-atlas-gen JSON and image file alongside.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public static Font Load(GraphicsDevice graphicsDevice, CommandBuffer commandBuffer, string fontPath)
 | 
			
		||||
    {
 | 
			
		||||
        FileStream fontFileStream = new FileStream(fontPath, FileMode.Open, FileAccess.Read);
 | 
			
		||||
        void* fontFileByteBuffer = NativeMemory.Alloc((nuint)fontFileStream.Length);
 | 
			
		||||
        Span<byte> fontFileByteSpan = new Span<byte>(fontFileByteBuffer, (int)fontFileStream.Length);
 | 
			
		||||
        fontFileStream.ReadExactly(fontFileByteSpan);
 | 
			
		||||
        fontFileStream.Close();
 | 
			
		||||
 | 
			
		||||
        FileStream atlasFileStream = new FileStream(Path.ChangeExtension(fontPath, ".json"), FileMode.Open, FileAccess.Read);
 | 
			
		||||
        void* atlasFileByteBuffer = NativeMemory.Alloc((nuint)atlasFileStream.Length);
 | 
			
		||||
        Span<byte> atlasFileByteSpan = new Span<byte>(atlasFileByteBuffer, (int)atlasFileStream.Length);
 | 
			
		||||
        atlasFileStream.ReadExactly(atlasFileByteSpan);
 | 
			
		||||
        atlasFileStream.Close();
 | 
			
		||||
 | 
			
		||||
        IntPtr handle = Wellspring.Wellspring_CreateFont(
 | 
			
		||||
            (IntPtr)fontFileByteBuffer,
 | 
			
		||||
            (uint)fontFileByteSpan.Length,
 | 
			
		||||
            (IntPtr)atlasFileByteBuffer,
 | 
			
		||||
            (uint)atlasFileByteSpan.Length,
 | 
			
		||||
            out float pixelsPerEm,
 | 
			
		||||
            out float distanceRange
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        string imagePath = Path.ChangeExtension(fontPath, ".png");
 | 
			
		||||
        ImageUtils.ImageInfoFromFile(imagePath, out uint width, out uint height, out uint sizeInBytes);
 | 
			
		||||
 | 
			
		||||
        ResourceUploader uploader = new ResourceUploader(graphicsDevice);
 | 
			
		||||
        Texture texture = uploader.CreateTexture2DFromCompressed(imagePath);
 | 
			
		||||
        uploader.Upload();
 | 
			
		||||
        uploader.Dispose();
 | 
			
		||||
 | 
			
		||||
        NativeMemory.Free(fontFileByteBuffer);
 | 
			
		||||
        NativeMemory.Free(atlasFileByteBuffer);
 | 
			
		||||
 | 
			
		||||
        return new Font(graphicsDevice, handle, texture, pixelsPerEm, distanceRange);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Font(GraphicsDevice device, IntPtr handle, Texture texture, float pixelsPerEm, float distanceRange) : base(device)
 | 
			
		||||
    {
 | 
			
		||||
        Handle = handle;
 | 
			
		||||
        Texture = texture;
 | 
			
		||||
        PixelsPerEm = pixelsPerEm;
 | 
			
		||||
        DistanceRange = distanceRange;
 | 
			
		||||
 | 
			
		||||
        StringBytesLength = 32;
 | 
			
		||||
        StringBytes = (byte*)NativeMemory.Alloc((nuint)StringBytesLength);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public unsafe bool TextBounds(
 | 
			
		||||
        string text,
 | 
			
		||||
        int pixelSize,
 | 
			
		||||
        HorizontalAlignment horizontalAlignment,
 | 
			
		||||
        VerticalAlignment verticalAlignment,
 | 
			
		||||
        out Wellspring.Rectangle rectangle
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
        int byteCount = System.Text.Encoding.UTF8.GetByteCount(text);
 | 
			
		||||
 | 
			
		||||
        if (StringBytesLength < byteCount)
 | 
			
		||||
        {
 | 
			
		||||
            StringBytes = (byte*)NativeMemory.Realloc(StringBytes, (nuint)byteCount);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fixed (char* chars = text)
 | 
			
		||||
        {
 | 
			
		||||
            System.Text.Encoding.UTF8.GetBytes(chars, text.Length, StringBytes, byteCount);
 | 
			
		||||
 | 
			
		||||
            byte result = Wellspring.Wellspring_TextBounds(
 | 
			
		||||
                Handle,
 | 
			
		||||
                pixelSize,
 | 
			
		||||
                (Wellspring.HorizontalAlignment)horizontalAlignment,
 | 
			
		||||
                (Wellspring.VerticalAlignment)verticalAlignment,
 | 
			
		||||
                (IntPtr)StringBytes,
 | 
			
		||||
                (uint)byteCount,
 | 
			
		||||
                out rectangle
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            if (result == 0)
 | 
			
		||||
            {
 | 
			
		||||
                Log.Warning("Could not decode string: " + text);
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected override void Dispose(bool disposing)
 | 
			
		||||
    {
 | 
			
		||||
        if (!IsDisposed)
 | 
			
		||||
        {
 | 
			
		||||
            if (disposing)
 | 
			
		||||
            {
 | 
			
		||||
                Texture.Dispose();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Wellspring.Wellspring_DestroyFont(Handle);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        base.Dispose(disposing);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								Nerfed.Runtime/Graphics/Font/Structs.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								Nerfed.Runtime/Graphics/Font/Structs.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
[StructLayout(LayoutKind.Sequential)]
 | 
			
		||||
public struct FontVertex : IVertexType
 | 
			
		||||
{
 | 
			
		||||
	public Vector3 Position;
 | 
			
		||||
	public Vector2 TexCoord;
 | 
			
		||||
	public Color Color;
 | 
			
		||||
 | 
			
		||||
	public static VertexElementFormat[] Formats { get; } =
 | 
			
		||||
	[
 | 
			
		||||
		VertexElementFormat.Vector3,
 | 
			
		||||
		VertexElementFormat.Vector2,
 | 
			
		||||
		VertexElementFormat.Color
 | 
			
		||||
	];
 | 
			
		||||
 | 
			
		||||
	public static uint[] Offsets { get; } =
 | 
			
		||||
	[
 | 
			
		||||
		0,
 | 
			
		||||
		12,
 | 
			
		||||
		20
 | 
			
		||||
	];
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										191
									
								
								Nerfed.Runtime/Graphics/Font/TextBatch.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								Nerfed.Runtime/Graphics/Font/TextBatch.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,191 @@
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
using WellspringCS;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
public unsafe class TextBatch : GraphicsResource
 | 
			
		||||
{
 | 
			
		||||
    public const int INITIAL_CHAR_COUNT = 64;
 | 
			
		||||
    public const int INITIAL_VERTEX_COUNT = INITIAL_CHAR_COUNT * 4;
 | 
			
		||||
    public const int INITIAL_INDEX_COUNT = INITIAL_CHAR_COUNT * 6;
 | 
			
		||||
 | 
			
		||||
    public IntPtr Handle { get; }
 | 
			
		||||
    public Buffer VertexBuffer { get; protected set; } = null;
 | 
			
		||||
    public Buffer IndexBuffer { get; protected set; } = null;
 | 
			
		||||
    public uint PrimitiveCount { get; protected set; }
 | 
			
		||||
    public Font CurrentFont { get; private set; }
 | 
			
		||||
 | 
			
		||||
    private readonly GraphicsDevice graphicsDevice;
 | 
			
		||||
    private readonly int stringBytesLength;
 | 
			
		||||
    private TransferBuffer TransferBuffer;
 | 
			
		||||
    private byte* stringBytes;
 | 
			
		||||
 | 
			
		||||
    public TextBatch(GraphicsDevice device) : base(device)
 | 
			
		||||
    {
 | 
			
		||||
        graphicsDevice = device;
 | 
			
		||||
        Handle = Wellspring.Wellspring_CreateTextBatch();
 | 
			
		||||
 | 
			
		||||
        stringBytesLength = 128;
 | 
			
		||||
        stringBytes = (byte*)NativeMemory.Alloc((nuint)stringBytesLength);
 | 
			
		||||
 | 
			
		||||
        VertexBuffer = Buffer.Create<FontVertex>(graphicsDevice, BufferUsageFlags.Vertex, INITIAL_VERTEX_COUNT);
 | 
			
		||||
        IndexBuffer = Buffer.Create<uint>(graphicsDevice, BufferUsageFlags.Index, INITIAL_INDEX_COUNT);
 | 
			
		||||
 | 
			
		||||
        TransferBuffer = TransferBuffer.Create<byte>(
 | 
			
		||||
            graphicsDevice,
 | 
			
		||||
            TransferBufferUsage.Upload,
 | 
			
		||||
            VertexBuffer.Size + IndexBuffer.Size
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Call this to initialize or reset the batch.
 | 
			
		||||
    public void Start(Font font)
 | 
			
		||||
    {
 | 
			
		||||
        Wellspring.Wellspring_StartTextBatch(Handle, font.Handle);
 | 
			
		||||
        CurrentFont = font;
 | 
			
		||||
        PrimitiveCount = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Add text with size and color to the batch
 | 
			
		||||
    public unsafe bool Add(
 | 
			
		||||
        string text,
 | 
			
		||||
        int pixelSize,
 | 
			
		||||
        Color color,
 | 
			
		||||
        HorizontalAlignment horizontalAlignment = HorizontalAlignment.Left,
 | 
			
		||||
        VerticalAlignment verticalAlignment = VerticalAlignment.Baseline
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
        int byteCount = System.Text.Encoding.UTF8.GetByteCount(text);
 | 
			
		||||
 | 
			
		||||
        if (stringBytesLength < byteCount)
 | 
			
		||||
        {
 | 
			
		||||
            stringBytes = (byte*)NativeMemory.Realloc(stringBytes, (nuint)byteCount);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fixed (char* chars = text)
 | 
			
		||||
        {
 | 
			
		||||
            System.Text.Encoding.UTF8.GetBytes(chars, text.Length, stringBytes, byteCount);
 | 
			
		||||
 | 
			
		||||
            byte result = Wellspring.Wellspring_AddToTextBatch(
 | 
			
		||||
                Handle,
 | 
			
		||||
                pixelSize,
 | 
			
		||||
                new Wellspring.Color { R = color.R, G = color.G, B = color.B, A = color.A },
 | 
			
		||||
                (Wellspring.HorizontalAlignment)horizontalAlignment,
 | 
			
		||||
                (Wellspring.VerticalAlignment)verticalAlignment,
 | 
			
		||||
                (IntPtr)stringBytes,
 | 
			
		||||
                (uint)byteCount
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            if (result == 0)
 | 
			
		||||
            {
 | 
			
		||||
                Log.Warning("Could not decode string: " + text);
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Call this after you have made all the Add calls you want, but before beginning a render pass.
 | 
			
		||||
    public unsafe void UploadBufferData(CommandBuffer commandBuffer)
 | 
			
		||||
    {
 | 
			
		||||
        Wellspring.Wellspring_GetBufferData(
 | 
			
		||||
            Handle,
 | 
			
		||||
            out uint vertexCount,
 | 
			
		||||
            out IntPtr vertexDataPointer,
 | 
			
		||||
            out uint vertexDataLengthInBytes,
 | 
			
		||||
            out IntPtr indexDataPointer,
 | 
			
		||||
            out uint indexDataLengthInBytes
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        Span<byte> vertexSpan = new Span<byte>((void*)vertexDataPointer, (int)vertexDataLengthInBytes);
 | 
			
		||||
        Span<byte> indexSpan = new Span<byte>((void*)indexDataPointer, (int)indexDataLengthInBytes);
 | 
			
		||||
 | 
			
		||||
        bool newTransferBufferNeeded = false;
 | 
			
		||||
 | 
			
		||||
        if (VertexBuffer.Size < vertexDataLengthInBytes)
 | 
			
		||||
        {
 | 
			
		||||
            VertexBuffer.Dispose();
 | 
			
		||||
            VertexBuffer = new Buffer(graphicsDevice, BufferUsageFlags.Vertex, vertexDataLengthInBytes);
 | 
			
		||||
            newTransferBufferNeeded = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (IndexBuffer.Size < indexDataLengthInBytes)
 | 
			
		||||
        {
 | 
			
		||||
            IndexBuffer.Dispose();
 | 
			
		||||
            IndexBuffer = new Buffer(graphicsDevice, BufferUsageFlags.Index, vertexDataLengthInBytes);
 | 
			
		||||
            newTransferBufferNeeded = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (newTransferBufferNeeded)
 | 
			
		||||
        {
 | 
			
		||||
            TransferBuffer.Dispose();
 | 
			
		||||
            TransferBuffer = new TransferBuffer(
 | 
			
		||||
                graphicsDevice,
 | 
			
		||||
                TransferBufferUsage.Upload,
 | 
			
		||||
                VertexBuffer.Size + IndexBuffer.Size
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (vertexDataLengthInBytes > 0 && indexDataLengthInBytes > 0)
 | 
			
		||||
        {
 | 
			
		||||
            TransferBuffer.SetData(vertexSpan, true);
 | 
			
		||||
            TransferBuffer.SetData(indexSpan, (uint)vertexSpan.Length, false);
 | 
			
		||||
 | 
			
		||||
            CopyPass copyPass = commandBuffer.BeginCopyPass();
 | 
			
		||||
            copyPass.UploadToBuffer(
 | 
			
		||||
                new TransferBufferLocation(TransferBuffer),
 | 
			
		||||
                new BufferRegion(VertexBuffer, 0, (uint)vertexSpan.Length),
 | 
			
		||||
                true
 | 
			
		||||
            );
 | 
			
		||||
            copyPass.UploadToBuffer(
 | 
			
		||||
                new TransferBufferLocation(TransferBuffer, (uint)vertexSpan.Length),
 | 
			
		||||
                new BufferRegion(IndexBuffer, 0, (uint)indexSpan.Length),
 | 
			
		||||
                true
 | 
			
		||||
            );
 | 
			
		||||
            commandBuffer.EndCopyPass(copyPass);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        PrimitiveCount = vertexCount / 2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Call this AFTER binding your text pipeline!
 | 
			
		||||
    public void Render(CommandBuffer commandBuffer, RenderPass renderPass, Matrix4x4 transformMatrix)
 | 
			
		||||
    {
 | 
			
		||||
        commandBuffer.PushVertexUniformData(transformMatrix);
 | 
			
		||||
        commandBuffer.PushFragmentUniformData(CurrentFont.DistanceRange);
 | 
			
		||||
 | 
			
		||||
        renderPass.BindFragmentSampler(
 | 
			
		||||
            new TextureSamplerBinding(
 | 
			
		||||
                CurrentFont.Texture,
 | 
			
		||||
                graphicsDevice.LinearSampler
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
        renderPass.BindVertexBuffer(VertexBuffer);
 | 
			
		||||
        renderPass.BindIndexBuffer(IndexBuffer, IndexElementSize.ThirtyTwo);
 | 
			
		||||
 | 
			
		||||
        renderPass.DrawIndexedPrimitives(
 | 
			
		||||
            0,
 | 
			
		||||
            0,
 | 
			
		||||
            PrimitiveCount
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected override void Dispose(bool disposing)
 | 
			
		||||
    {
 | 
			
		||||
        if (!IsDisposed)
 | 
			
		||||
        {
 | 
			
		||||
            if (disposing)
 | 
			
		||||
            {
 | 
			
		||||
                VertexBuffer.Dispose();
 | 
			
		||||
                IndexBuffer.Dispose();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            NativeMemory.Free(stringBytes);
 | 
			
		||||
            Wellspring.Wellspring_DestroyTextBatch(Handle);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        base.Dispose(disposing);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										466
									
								
								Nerfed.Runtime/Graphics/GraphicsDevice.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										466
									
								
								Nerfed.Runtime/Graphics/GraphicsDevice.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,466 @@
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
using Nerfed.Runtime.Video;
 | 
			
		||||
using RefreshCS;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Manages all graphics-related concerns.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public class GraphicsDevice : IDisposable
 | 
			
		||||
{
 | 
			
		||||
    public IntPtr Handle { get; }
 | 
			
		||||
    public BackendFlags Backend { get; }
 | 
			
		||||
    public bool DebugMode { get; }
 | 
			
		||||
 | 
			
		||||
    // Built-in video pipeline
 | 
			
		||||
    internal GraphicsPipeline VideoPipeline { get; }
 | 
			
		||||
 | 
			
		||||
    // Built-in text shader info
 | 
			
		||||
    public Shader TextVertexShader;
 | 
			
		||||
    public Shader TextFragmentShader;
 | 
			
		||||
    public VertexInputState TextVertexInputState { get; }
 | 
			
		||||
 | 
			
		||||
    // Built-in samplers
 | 
			
		||||
    public Sampler PointSampler { get; }
 | 
			
		||||
    public Sampler LinearSampler { get; }
 | 
			
		||||
 | 
			
		||||
    public bool IsDisposed { get; private set; }
 | 
			
		||||
 | 
			
		||||
    internal readonly RenderPassPool RenderPassPool = new RenderPassPool();
 | 
			
		||||
    internal readonly ComputePassPool ComputePassPool = new ComputePassPool();
 | 
			
		||||
    internal readonly CopyPassPool CopyPassPool = new CopyPassPool();
 | 
			
		||||
    private readonly HashSet<GCHandle> resources = new HashSet<GCHandle>();
 | 
			
		||||
    private readonly CommandBufferPool commandBufferPool;
 | 
			
		||||
    private readonly FencePool fencePool;
 | 
			
		||||
 | 
			
		||||
    internal GraphicsDevice(BackendFlags preferredBackends)
 | 
			
		||||
    {
 | 
			
		||||
        if (preferredBackends == BackendFlags.Invalid)
 | 
			
		||||
        {
 | 
			
		||||
            throw new System.Exception("Could not set graphics backend!");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        bool debugMode = false;
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        debugMode = true;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        Handle = Refresh.Refresh_CreateDevice((Refresh.BackendFlags)preferredBackends, Conversions.BoolToInt(debugMode));
 | 
			
		||||
 | 
			
		||||
        DebugMode = debugMode;
 | 
			
		||||
        // TODO: check for CreateDevice fail
 | 
			
		||||
 | 
			
		||||
        Backend = (BackendFlags)Refresh.Refresh_GetBackend(Handle);
 | 
			
		||||
 | 
			
		||||
        IEmbeddedShaders embeddedShaders;
 | 
			
		||||
        switch (Backend)
 | 
			
		||||
        {
 | 
			
		||||
            case BackendFlags.Vulkan:
 | 
			
		||||
                embeddedShaders = new EmbeddedShadersSpirV();
 | 
			
		||||
                break;
 | 
			
		||||
            case BackendFlags.D3D11:
 | 
			
		||||
                throw new NotImplementedException("D3D11 embedded shaders");
 | 
			
		||||
                break;
 | 
			
		||||
            case BackendFlags.Metal:
 | 
			
		||||
                throw new NotImplementedException("Metal embedded shaders");
 | 
			
		||||
                break;
 | 
			
		||||
            default: throw new ArgumentOutOfRangeException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Shader fullscreenVertShader;
 | 
			
		||||
        Shader textVertShader;
 | 
			
		||||
        Shader textFragShader;
 | 
			
		||||
        Shader videoFragShader;
 | 
			
		||||
 | 
			
		||||
        using (MemoryStream fullscreenVertStream = new MemoryStream(embeddedShaders.FullscreenVert))
 | 
			
		||||
        {
 | 
			
		||||
            fullscreenVertShader = new Shader(
 | 
			
		||||
                this,
 | 
			
		||||
                fullscreenVertStream,
 | 
			
		||||
                "main",
 | 
			
		||||
                new ShaderCreateInfo
 | 
			
		||||
                {
 | 
			
		||||
                    ShaderStage = ShaderStage.Vertex,
 | 
			
		||||
                    ShaderFormat = embeddedShaders.ShaderFormat
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        using (MemoryStream videoYuv2RgbaFragStream = new MemoryStream(embeddedShaders.VideoYuv2RgbaFrag))
 | 
			
		||||
        {
 | 
			
		||||
            videoFragShader = new Shader(
 | 
			
		||||
                this,
 | 
			
		||||
                videoYuv2RgbaFragStream,
 | 
			
		||||
                "main",
 | 
			
		||||
                new ShaderCreateInfo
 | 
			
		||||
                {
 | 
			
		||||
                    ShaderStage = ShaderStage.Fragment,
 | 
			
		||||
                    ShaderFormat = embeddedShaders.ShaderFormat,
 | 
			
		||||
                    SamplerCount = 3
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        using (MemoryStream textTransformVertStream = new MemoryStream(embeddedShaders.TextTransformVert))
 | 
			
		||||
        {
 | 
			
		||||
            textVertShader = new Shader(
 | 
			
		||||
                this,
 | 
			
		||||
                textTransformVertStream,
 | 
			
		||||
                "main",
 | 
			
		||||
                new ShaderCreateInfo
 | 
			
		||||
                {
 | 
			
		||||
                    ShaderStage = ShaderStage.Vertex,
 | 
			
		||||
                    ShaderFormat = embeddedShaders.ShaderFormat,
 | 
			
		||||
                    UniformBufferCount = 1
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        using (MemoryStream textMsdfFragStream = new MemoryStream(embeddedShaders.TextMsdfFrag))
 | 
			
		||||
        {
 | 
			
		||||
            textFragShader = new Shader(
 | 
			
		||||
                this,
 | 
			
		||||
                textMsdfFragStream,
 | 
			
		||||
                "main",
 | 
			
		||||
                new ShaderCreateInfo
 | 
			
		||||
                {
 | 
			
		||||
                    ShaderStage = ShaderStage.Fragment,
 | 
			
		||||
                    ShaderFormat = embeddedShaders.ShaderFormat,
 | 
			
		||||
                    SamplerCount = 1,
 | 
			
		||||
                    UniformBufferCount = 1
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        VideoPipeline = new GraphicsPipeline(
 | 
			
		||||
            this,
 | 
			
		||||
            new GraphicsPipelineCreateInfo
 | 
			
		||||
            {
 | 
			
		||||
                AttachmentInfo = new GraphicsPipelineAttachmentInfo(
 | 
			
		||||
                    new ColorAttachmentDescription(
 | 
			
		||||
                        TextureFormat.R8G8B8A8,
 | 
			
		||||
                        ColorAttachmentBlendState.None
 | 
			
		||||
                    )
 | 
			
		||||
                ),
 | 
			
		||||
                DepthStencilState = DepthStencilState.Disable,
 | 
			
		||||
                VertexShader = fullscreenVertShader,
 | 
			
		||||
                FragmentShader = videoFragShader,
 | 
			
		||||
                VertexInputState = VertexInputState.Empty,
 | 
			
		||||
                RasterizerState = RasterizerState.CCW_CullNone,
 | 
			
		||||
                PrimitiveType = PrimitiveType.TriangleList,
 | 
			
		||||
                MultisampleState = MultisampleState.None
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        TextVertexShader = textVertShader;
 | 
			
		||||
        TextFragmentShader = textFragShader;
 | 
			
		||||
 | 
			
		||||
        TextVertexInputState = VertexInputState.CreateSingleBinding<FontVertex>();
 | 
			
		||||
 | 
			
		||||
        PointSampler = new Sampler(this, SamplerCreateInfo.PointClamp);
 | 
			
		||||
        LinearSampler = new Sampler(this, SamplerCreateInfo.LinearClamp);
 | 
			
		||||
 | 
			
		||||
        fencePool = new FencePool(this);
 | 
			
		||||
        commandBufferPool = new CommandBufferPool(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Prepares a window so that frames can be presented to it.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="swapchainComposition">The desired composition of the swapchain. Ignore this unless you are using HDR or tonemapping.</param>
 | 
			
		||||
    /// <param name="presentMode">The desired presentation mode for the window. Roughly equivalent to V-Sync.</param>
 | 
			
		||||
    /// <returns>True if successfully claimed.</returns>
 | 
			
		||||
    public bool ClaimWindow(
 | 
			
		||||
        Window window,
 | 
			
		||||
        SwapchainComposition swapchainComposition,
 | 
			
		||||
        PresentMode presentMode
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
        if (window.Claimed)
 | 
			
		||||
        {
 | 
			
		||||
            Log.Error("Window already claimed!");
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        bool success = Conversions.IntToBool(
 | 
			
		||||
            Refresh.Refresh_ClaimWindow(
 | 
			
		||||
                Handle,
 | 
			
		||||
                window.Handle,
 | 
			
		||||
                (Refresh.SwapchainComposition)swapchainComposition,
 | 
			
		||||
                (Refresh.PresentMode)presentMode
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        if (success)
 | 
			
		||||
        {
 | 
			
		||||
            window.Claimed = true;
 | 
			
		||||
            window.SwapchainComposition = swapchainComposition;
 | 
			
		||||
            window.SwapchainFormat = GetSwapchainFormat(window);
 | 
			
		||||
 | 
			
		||||
            if (window.SwapchainTexture == null)
 | 
			
		||||
            {
 | 
			
		||||
                window.SwapchainTexture = new Texture(this, window.SwapchainFormat);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return success;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Unclaims a window, making it unavailable for presenting and freeing associated resources.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public void UnclaimWindow(Window window)
 | 
			
		||||
    {
 | 
			
		||||
        if (window.Claimed)
 | 
			
		||||
        {
 | 
			
		||||
            Refresh.Refresh_UnclaimWindow(
 | 
			
		||||
                Handle,
 | 
			
		||||
                window.Handle
 | 
			
		||||
            );
 | 
			
		||||
            window.Claimed = false;
 | 
			
		||||
 | 
			
		||||
            // The swapchain texture doesn't actually have a permanent texture reference, so we zero the handle before disposing.
 | 
			
		||||
            window.SwapchainTexture.Handle = IntPtr.Zero;
 | 
			
		||||
            window.SwapchainTexture.Dispose();
 | 
			
		||||
            window.SwapchainTexture = null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Changes the present mode of a claimed window. Does nothing if the window is not claimed.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public bool SetSwapchainParameters(
 | 
			
		||||
        Window window,
 | 
			
		||||
        SwapchainComposition swapchainComposition,
 | 
			
		||||
        PresentMode presentMode
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
        if (!window.Claimed)
 | 
			
		||||
        {
 | 
			
		||||
            Log.Error("Cannot set present mode on unclaimed window!");
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        bool success = Conversions.IntToBool(
 | 
			
		||||
            Refresh.Refresh_SetSwapchainParameters(
 | 
			
		||||
                Handle,
 | 
			
		||||
                window.Handle,
 | 
			
		||||
                (Refresh.SwapchainComposition)swapchainComposition,
 | 
			
		||||
                (Refresh.PresentMode)presentMode
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        if (success)
 | 
			
		||||
        {
 | 
			
		||||
            window.SwapchainComposition = swapchainComposition;
 | 
			
		||||
            window.SwapchainFormat = GetSwapchainFormat(window);
 | 
			
		||||
 | 
			
		||||
            if (window.SwapchainTexture != null)
 | 
			
		||||
            {
 | 
			
		||||
                window.SwapchainTexture.Format = window.SwapchainFormat;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return success;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Acquires a command buffer.
 | 
			
		||||
    /// This is the start of your rendering process.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public CommandBuffer AcquireCommandBuffer()
 | 
			
		||||
    {
 | 
			
		||||
        CommandBuffer commandBuffer = commandBufferPool.Obtain();
 | 
			
		||||
        commandBuffer.SetHandle(Refresh.Refresh_AcquireCommandBuffer(Handle));
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        commandBuffer.ResetStateTracking();
 | 
			
		||||
#endif
 | 
			
		||||
        return commandBuffer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Submits a command buffer to the GPU for processing.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public void Submit(CommandBuffer commandBuffer)
 | 
			
		||||
    {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        if (commandBuffer.Submitted)
 | 
			
		||||
        {
 | 
			
		||||
            throw new System.InvalidOperationException("Command buffer already submitted!");
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        Refresh.Refresh_Submit(
 | 
			
		||||
            commandBuffer.Handle
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        commandBufferPool.Return(commandBuffer);
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        commandBuffer.Submitted = true;
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Submits a command buffer to the GPU for processing and acquires a fence associated with the submission.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public Fence SubmitAndAcquireFence(CommandBuffer commandBuffer)
 | 
			
		||||
    {
 | 
			
		||||
        IntPtr fenceHandle = Refresh.Refresh_SubmitAndAcquireFence(
 | 
			
		||||
            commandBuffer.Handle
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        Fence fence = fencePool.Obtain();
 | 
			
		||||
        fence.SetHandle(fenceHandle);
 | 
			
		||||
 | 
			
		||||
        return fence;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Wait for the graphics device to become idle.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public void Wait()
 | 
			
		||||
    {
 | 
			
		||||
        Refresh.Refresh_Wait(Handle);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Waits for the given fence to become signaled.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public unsafe void WaitForFence(Fence fence)
 | 
			
		||||
    {
 | 
			
		||||
        IntPtr fenceHandle = fence.Handle;
 | 
			
		||||
 | 
			
		||||
        Refresh.Refresh_WaitForFences(
 | 
			
		||||
            Handle,
 | 
			
		||||
            1,
 | 
			
		||||
            &fenceHandle,
 | 
			
		||||
            1
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Wait for one or more fences to become signaled.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="waitAll">If true, will wait for all given fences to be signaled.</param>
 | 
			
		||||
    public unsafe void WaitForFences(Span<Fence> fences, bool waitAll)
 | 
			
		||||
    {
 | 
			
		||||
        IntPtr* handlePtr = stackalloc nint[fences.Length];
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < fences.Length; i += 1)
 | 
			
		||||
        {
 | 
			
		||||
            handlePtr[i] = fences[i].Handle;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Refresh.Refresh_WaitForFences(
 | 
			
		||||
            Handle,
 | 
			
		||||
            Conversions.BoolToInt(waitAll),
 | 
			
		||||
            handlePtr,
 | 
			
		||||
            (uint)fences.Length
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Returns true if the fence is signaled, indicating that the associated command buffer has finished processing.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <exception cref="InvalidOperationException">Throws if the fence query indicates that the graphics device has been lost.</exception>
 | 
			
		||||
    public bool QueryFence(Fence fence)
 | 
			
		||||
    {
 | 
			
		||||
        int result = Refresh.Refresh_QueryFence(Handle, fence.Handle);
 | 
			
		||||
 | 
			
		||||
        if (result < 0)
 | 
			
		||||
        {
 | 
			
		||||
            throw new InvalidOperationException("The graphics device has been lost.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return result != 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Release reference to an acquired fence, enabling it to be reused.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public void ReleaseFence(Fence fence)
 | 
			
		||||
    {
 | 
			
		||||
        Refresh.Refresh_ReleaseFence(Handle, fence.Handle);
 | 
			
		||||
        fence.Handle = IntPtr.Zero;
 | 
			
		||||
        fencePool.Return(fence);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private TextureFormat GetSwapchainFormat(Window window)
 | 
			
		||||
    {
 | 
			
		||||
        if (!window.Claimed)
 | 
			
		||||
        {
 | 
			
		||||
            throw new System.ArgumentException("Cannot get swapchain format of unclaimed window!");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return (TextureFormat)Refresh.Refresh_GetSwapchainTextureFormat(Handle, window.Handle);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    internal void AddResourceReference(GCHandle resourceReference)
 | 
			
		||||
    {
 | 
			
		||||
        lock (resources)
 | 
			
		||||
        {
 | 
			
		||||
            resources.Add(resourceReference);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    internal void RemoveResourceReference(GCHandle resourceReference)
 | 
			
		||||
    {
 | 
			
		||||
        lock (resources)
 | 
			
		||||
        {
 | 
			
		||||
            resources.Remove(resourceReference);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void Dispose(bool disposing)
 | 
			
		||||
    {
 | 
			
		||||
        if (!IsDisposed)
 | 
			
		||||
        {
 | 
			
		||||
            if (disposing)
 | 
			
		||||
            {
 | 
			
		||||
                lock (resources)
 | 
			
		||||
                {
 | 
			
		||||
                    // Dispose video players first to avoid race condition on threaded decoding
 | 
			
		||||
                    foreach (GCHandle resource in resources)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (resource.Target is VideoPlayer player)
 | 
			
		||||
                        {
 | 
			
		||||
                            player.Dispose();
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // Dispose everything else
 | 
			
		||||
                    foreach (GCHandle resource in resources)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (resource.Target is IDisposable disposable)
 | 
			
		||||
                        {
 | 
			
		||||
                            disposable.Dispose();
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    resources.Clear();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Refresh.Refresh_DestroyDevice(Handle);
 | 
			
		||||
 | 
			
		||||
            IsDisposed = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~GraphicsDevice()
 | 
			
		||||
    {
 | 
			
		||||
        // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
 | 
			
		||||
        Dispose(disposing: false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void Dispose()
 | 
			
		||||
    {
 | 
			
		||||
        // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
 | 
			
		||||
        Dispose(disposing: true);
 | 
			
		||||
        GC.SuppressFinalize(this);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										53
									
								
								Nerfed.Runtime/Graphics/GraphicsResource.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								Nerfed.Runtime/Graphics/GraphicsResource.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
public abstract class GraphicsResource : IDisposable
 | 
			
		||||
{
 | 
			
		||||
    public GraphicsDevice Device { get; }
 | 
			
		||||
 | 
			
		||||
    private GCHandle SelfReference;
 | 
			
		||||
 | 
			
		||||
    public bool IsDisposed { get; private set; }
 | 
			
		||||
 | 
			
		||||
    protected GraphicsResource(GraphicsDevice device)
 | 
			
		||||
    {
 | 
			
		||||
        Device = device;
 | 
			
		||||
 | 
			
		||||
        SelfReference = GCHandle.Alloc(this, GCHandleType.Weak);
 | 
			
		||||
        Device.AddResourceReference(SelfReference);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected virtual void Dispose(bool disposing)
 | 
			
		||||
    {
 | 
			
		||||
        if (!IsDisposed)
 | 
			
		||||
        {
 | 
			
		||||
            if (disposing)
 | 
			
		||||
            {
 | 
			
		||||
                Device.RemoveResourceReference(SelfReference);
 | 
			
		||||
                SelfReference.Free();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            IsDisposed = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~GraphicsResource()
 | 
			
		||||
    {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        // If you see this log message, you leaked a graphics resource without disposing it!
 | 
			
		||||
        // We'll try to clean it up for you but you really should fix this.
 | 
			
		||||
        Log.Warning($"A resource of type {GetType().Name} was not Disposed.");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        Dispose(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void Dispose()
 | 
			
		||||
    {
 | 
			
		||||
        // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
 | 
			
		||||
        Dispose(disposing: true);
 | 
			
		||||
        GC.SuppressFinalize(this);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								Nerfed.Runtime/Graphics/IEmbeddedShaders.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								Nerfed.Runtime/Graphics/IEmbeddedShaders.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
internal interface IEmbeddedShaders
 | 
			
		||||
{
 | 
			
		||||
    ShaderFormat ShaderFormat { get; }
 | 
			
		||||
    byte[] FullscreenVert { get; }
 | 
			
		||||
    byte[] TextMsdfFrag { get; }
 | 
			
		||||
    byte[] TextTransformVert { get; }
 | 
			
		||||
    byte[] VideoYuv2RgbaFrag { get; }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								Nerfed.Runtime/Graphics/IVertexType.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								Nerfed.Runtime/Graphics/IVertexType.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Can be defined on your struct type to enable simplified vertex input state definition.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public interface IVertexType
 | 
			
		||||
{
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// An ordered list of the types in your vertex struct.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	static abstract VertexElementFormat[] Formats { get; }
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// An ordered list of the offsets in your vertex struct.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	static abstract uint[] Offsets { get; }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										455
									
								
								Nerfed.Runtime/Graphics/ImageUtils.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										455
									
								
								Nerfed.Runtime/Graphics/ImageUtils.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,455 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
using RefreshCS;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
public static class ImageUtils
 | 
			
		||||
{
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets pointer to pixel data from compressed image byte data.
 | 
			
		||||
	///
 | 
			
		||||
	/// The returned pointer must be freed by calling FreePixelData.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public static unsafe byte* GetPixelDataFromBytes(
 | 
			
		||||
		Span<byte> data,
 | 
			
		||||
		out uint width,
 | 
			
		||||
		out uint height,
 | 
			
		||||
		out uint sizeInBytes
 | 
			
		||||
	) {
 | 
			
		||||
		fixed (byte* ptr = data)
 | 
			
		||||
		{
 | 
			
		||||
			byte* pixelData =
 | 
			
		||||
				Refresh.Refresh_Image_Load(
 | 
			
		||||
				ptr,
 | 
			
		||||
				data.Length,
 | 
			
		||||
				out int w,
 | 
			
		||||
				out int h,
 | 
			
		||||
				out int len
 | 
			
		||||
			);
 | 
			
		||||
 | 
			
		||||
			width = (uint) w;
 | 
			
		||||
			height = (uint) h;
 | 
			
		||||
			sizeInBytes = (uint) len;
 | 
			
		||||
 | 
			
		||||
			return pixelData;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets pointer to pixel data from a compressed image stream.
 | 
			
		||||
	///
 | 
			
		||||
	/// The returned pointer must be freed by calling FreePixelData.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public static unsafe byte* GetPixelDataFromStream(
 | 
			
		||||
		Stream stream,
 | 
			
		||||
		out uint width,
 | 
			
		||||
		out uint height,
 | 
			
		||||
		out uint sizeInBytes
 | 
			
		||||
	) {
 | 
			
		||||
		long length = stream.Length;
 | 
			
		||||
		void* buffer = NativeMemory.Alloc((nuint) length);
 | 
			
		||||
		Span<byte> span = new Span<byte>(buffer, (int) length);
 | 
			
		||||
		stream.ReadExactly(span);
 | 
			
		||||
 | 
			
		||||
		byte* pixelData = GetPixelDataFromBytes(span, out width, out height, out sizeInBytes);
 | 
			
		||||
 | 
			
		||||
		NativeMemory.Free(buffer);
 | 
			
		||||
 | 
			
		||||
		return pixelData;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets pointer to pixel data from a compressed image file.
 | 
			
		||||
	///
 | 
			
		||||
	/// The returned pointer must be freed by calling FreePixelData.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public static unsafe byte* GetPixelDataFromFile(
 | 
			
		||||
		string path,
 | 
			
		||||
		out uint width,
 | 
			
		||||
		out uint height,
 | 
			
		||||
		out uint sizeInBytes
 | 
			
		||||
	) {
 | 
			
		||||
		FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
 | 
			
		||||
		return GetPixelDataFromStream(fileStream, out width, out height, out sizeInBytes);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Get metadata from compressed image bytes.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public static unsafe bool ImageInfoFromBytes(
 | 
			
		||||
		Span<byte> data,
 | 
			
		||||
		out uint width,
 | 
			
		||||
		out uint height,
 | 
			
		||||
		out uint sizeInBytes
 | 
			
		||||
	) {
 | 
			
		||||
		fixed (byte* ptr = data)
 | 
			
		||||
		{
 | 
			
		||||
			int result =
 | 
			
		||||
				Refresh.Refresh_Image_Info(
 | 
			
		||||
				ptr,
 | 
			
		||||
				data.Length,
 | 
			
		||||
				out int w,
 | 
			
		||||
				out int h,
 | 
			
		||||
				out int len
 | 
			
		||||
			);
 | 
			
		||||
 | 
			
		||||
			width = (uint) w;
 | 
			
		||||
			height = (uint) h;
 | 
			
		||||
			sizeInBytes = (uint) len;
 | 
			
		||||
 | 
			
		||||
			return Conversions.IntToBool(result);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Get metadata from a compressed image stream.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public static unsafe bool ImageInfoFromStream(
 | 
			
		||||
		Stream stream,
 | 
			
		||||
		out uint width,
 | 
			
		||||
		out uint height,
 | 
			
		||||
		out uint sizeInBytes
 | 
			
		||||
	) {
 | 
			
		||||
		long length = stream.Length;
 | 
			
		||||
		void* buffer = NativeMemory.Alloc((nuint) length);
 | 
			
		||||
		Span<byte> span = new Span<byte>(buffer, (int) length);
 | 
			
		||||
		stream.ReadExactly(span);
 | 
			
		||||
 | 
			
		||||
		bool result = ImageInfoFromBytes(span, out width, out height, out sizeInBytes);
 | 
			
		||||
 | 
			
		||||
		NativeMemory.Free(buffer);
 | 
			
		||||
 | 
			
		||||
		return result;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Get metadata from a compressed image file.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public static bool ImageInfoFromFile(
 | 
			
		||||
		string path,
 | 
			
		||||
		out uint width,
 | 
			
		||||
		out uint height,
 | 
			
		||||
		out uint sizeInBytes
 | 
			
		||||
	) {
 | 
			
		||||
		FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
 | 
			
		||||
		return ImageInfoFromStream(fileStream, out width, out height, out sizeInBytes);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Frees pixel data obtained from GetPixelData methods.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public unsafe static void FreePixelData(byte* pixels)
 | 
			
		||||
	{
 | 
			
		||||
		Refresh.Refresh_Image_Free(pixels);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Saves pixel data contained in a TransferBuffer to a PNG file.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public static unsafe void SavePNG(
 | 
			
		||||
		string path,
 | 
			
		||||
		TransferBuffer transferBuffer,
 | 
			
		||||
		uint bufferOffsetInBytes,
 | 
			
		||||
		int width,
 | 
			
		||||
		int height,
 | 
			
		||||
		bool bgra
 | 
			
		||||
	) {
 | 
			
		||||
		int sizeInBytes = width * height * 4;
 | 
			
		||||
 | 
			
		||||
		byte* pixelsPtr = (byte*) NativeMemory.Alloc((nuint) sizeInBytes);
 | 
			
		||||
		Span<byte> pixelsSpan = new Span<byte>(pixelsPtr, sizeInBytes);
 | 
			
		||||
 | 
			
		||||
		transferBuffer.GetData(pixelsSpan, bufferOffsetInBytes);
 | 
			
		||||
 | 
			
		||||
		if (bgra)
 | 
			
		||||
		{
 | 
			
		||||
			// if data is bgra, we have to swap the R and B channels
 | 
			
		||||
			byte* rgbaPtr = (byte*) NativeMemory.Alloc((nuint) sizeInBytes);
 | 
			
		||||
			Span<byte> rgbaSpan = new Span<byte>(rgbaPtr, sizeInBytes);
 | 
			
		||||
 | 
			
		||||
			for (int i = 0; i < sizeInBytes; i += 4)
 | 
			
		||||
			{
 | 
			
		||||
				rgbaSpan[i] = pixelsSpan[i + 2];
 | 
			
		||||
				rgbaSpan[i + 1] = pixelsSpan[i + 1];
 | 
			
		||||
				rgbaSpan[i + 2] = pixelsSpan[i];
 | 
			
		||||
				rgbaSpan[i + 3] = pixelsSpan[i + 3];
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			NativeMemory.Free(pixelsPtr);
 | 
			
		||||
			pixelsPtr = rgbaPtr;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		Refresh.Refresh_Image_SavePNG(path, pixelsPtr, width, height);
 | 
			
		||||
		NativeMemory.Free(pixelsPtr);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// DDS loading extension, based on MojoDDS
 | 
			
		||||
	// Taken from https://github.com/FNA-XNA/FNA/blob/1e49f868f595f62bc6385db45949a03186a7cd7f/src/Graphics/Texture.cs#L194
 | 
			
		||||
	public static void ParseDDS(
 | 
			
		||||
		BinaryReader reader,
 | 
			
		||||
		out TextureFormat format,
 | 
			
		||||
		out int width,
 | 
			
		||||
		out int height,
 | 
			
		||||
		out int levels,
 | 
			
		||||
		out bool isCube
 | 
			
		||||
	) {
 | 
			
		||||
		// A whole bunch of magic numbers, yay DDS!
 | 
			
		||||
		const uint DDS_MAGIC = 0x20534444;
 | 
			
		||||
		const uint DDS_HEADERSIZE = 124;
 | 
			
		||||
		const uint DDS_PIXFMTSIZE = 32;
 | 
			
		||||
		const uint DDSD_HEIGHT = 0x2;
 | 
			
		||||
		const uint DDSD_WIDTH = 0x4;
 | 
			
		||||
		const uint DDSD_PITCH = 0x8;
 | 
			
		||||
		const uint DDSD_LINEARSIZE = 0x80000;
 | 
			
		||||
		const uint DDSD_REQ = (
 | 
			
		||||
			DDSD_HEIGHT | DDSD_WIDTH
 | 
			
		||||
		);
 | 
			
		||||
		const uint DDSCAPS_MIPMAP = 0x400000;
 | 
			
		||||
		const uint DDSCAPS_TEXTURE = 0x1000;
 | 
			
		||||
		const uint DDSCAPS2_CUBEMAP = 0x200;
 | 
			
		||||
		const uint DDPF_FOURCC = 0x4;
 | 
			
		||||
		const uint DDPF_RGB = 0x40;
 | 
			
		||||
		const uint FOURCC_DXT1 = 0x31545844;
 | 
			
		||||
		const uint FOURCC_DXT3 = 0x33545844;
 | 
			
		||||
		const uint FOURCC_DXT5 = 0x35545844;
 | 
			
		||||
		const uint FOURCC_DX10 = 0x30315844;
 | 
			
		||||
		const uint pitchAndLinear = (
 | 
			
		||||
			DDSD_PITCH | DDSD_LINEARSIZE
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		// File should start with 'DDS '
 | 
			
		||||
		if (reader.ReadUInt32() != DDS_MAGIC)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotSupportedException("Not a DDS!");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Texture info
 | 
			
		||||
		uint size = reader.ReadUInt32();
 | 
			
		||||
		if (size != DDS_HEADERSIZE)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotSupportedException("Invalid DDS header!");
 | 
			
		||||
		}
 | 
			
		||||
		uint flags = reader.ReadUInt32();
 | 
			
		||||
		if ((flags & DDSD_REQ) != DDSD_REQ)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotSupportedException("Invalid DDS flags!");
 | 
			
		||||
		}
 | 
			
		||||
		if ((flags & pitchAndLinear) == pitchAndLinear)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotSupportedException("Invalid DDS flags!");
 | 
			
		||||
		}
 | 
			
		||||
		height = reader.ReadInt32();
 | 
			
		||||
		width = reader.ReadInt32();
 | 
			
		||||
		reader.ReadUInt32(); // dwPitchOrLinearSize, unused
 | 
			
		||||
		reader.ReadUInt32(); // dwDepth, unused
 | 
			
		||||
		levels = reader.ReadInt32();
 | 
			
		||||
 | 
			
		||||
		// "Reserved"
 | 
			
		||||
		reader.ReadBytes(4 * 11);
 | 
			
		||||
 | 
			
		||||
		// Format info
 | 
			
		||||
		uint formatSize = reader.ReadUInt32();
 | 
			
		||||
		if (formatSize != DDS_PIXFMTSIZE)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotSupportedException("Bogus PIXFMTSIZE!");
 | 
			
		||||
		}
 | 
			
		||||
		uint formatFlags = reader.ReadUInt32();
 | 
			
		||||
		uint formatFourCC = reader.ReadUInt32();
 | 
			
		||||
		uint formatRGBBitCount = reader.ReadUInt32();
 | 
			
		||||
		uint formatRBitMask = reader.ReadUInt32();
 | 
			
		||||
		uint formatGBitMask = reader.ReadUInt32();
 | 
			
		||||
		uint formatBBitMask = reader.ReadUInt32();
 | 
			
		||||
		uint formatABitMask = reader.ReadUInt32();
 | 
			
		||||
 | 
			
		||||
		// dwCaps "stuff"
 | 
			
		||||
		uint caps = reader.ReadUInt32();
 | 
			
		||||
		if ((caps & DDSCAPS_TEXTURE) == 0)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotSupportedException("Not a texture!");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		isCube = false;
 | 
			
		||||
 | 
			
		||||
		uint caps2 = reader.ReadUInt32();
 | 
			
		||||
		if (caps2 != 0)
 | 
			
		||||
		{
 | 
			
		||||
			if ((caps2 & DDSCAPS2_CUBEMAP) == DDSCAPS2_CUBEMAP)
 | 
			
		||||
			{
 | 
			
		||||
				isCube = true;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				throw new NotSupportedException("Invalid caps2!");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		reader.ReadUInt32(); // dwCaps3, unused
 | 
			
		||||
		reader.ReadUInt32(); // dwCaps4, unused
 | 
			
		||||
 | 
			
		||||
		// "Reserved"
 | 
			
		||||
		reader.ReadUInt32();
 | 
			
		||||
 | 
			
		||||
		// Mipmap sanity check
 | 
			
		||||
		if ((caps & DDSCAPS_MIPMAP) != DDSCAPS_MIPMAP)
 | 
			
		||||
		{
 | 
			
		||||
			levels = 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Determine texture format
 | 
			
		||||
		if ((formatFlags & DDPF_FOURCC) == DDPF_FOURCC)
 | 
			
		||||
		{
 | 
			
		||||
			switch (formatFourCC)
 | 
			
		||||
			{
 | 
			
		||||
				case 0x71: // D3DFMT_A16B16G16R16F
 | 
			
		||||
					format = TextureFormat.R16G16B16A16_SFLOAT;
 | 
			
		||||
					break;
 | 
			
		||||
				case 0x74: // D3DFMT_A32B32G32R32F
 | 
			
		||||
					format = TextureFormat.R32G32B32A32_SFLOAT;
 | 
			
		||||
					break;
 | 
			
		||||
				case FOURCC_DXT1:
 | 
			
		||||
					format = TextureFormat.BC1;
 | 
			
		||||
					break;
 | 
			
		||||
				case FOURCC_DXT3:
 | 
			
		||||
					format = TextureFormat.BC2;
 | 
			
		||||
					break;
 | 
			
		||||
				case FOURCC_DXT5:
 | 
			
		||||
					format = TextureFormat.BC3;
 | 
			
		||||
					break;
 | 
			
		||||
				case FOURCC_DX10:
 | 
			
		||||
					// If the fourCC is DX10, there is an extra header with additional format information.
 | 
			
		||||
					uint dxgiFormat = reader.ReadUInt32();
 | 
			
		||||
 | 
			
		||||
					// These values are taken from the DXGI_FORMAT enum.
 | 
			
		||||
					switch (dxgiFormat)
 | 
			
		||||
					{
 | 
			
		||||
						case 2:
 | 
			
		||||
							format = TextureFormat.R32G32B32A32_SFLOAT;
 | 
			
		||||
							break;
 | 
			
		||||
 | 
			
		||||
						case 10:
 | 
			
		||||
							format = TextureFormat.R16G16B16A16_SFLOAT;
 | 
			
		||||
							break;
 | 
			
		||||
 | 
			
		||||
						case 71:
 | 
			
		||||
							format = TextureFormat.BC1;
 | 
			
		||||
							break;
 | 
			
		||||
 | 
			
		||||
						case 74:
 | 
			
		||||
							format = TextureFormat.BC2;
 | 
			
		||||
							break;
 | 
			
		||||
 | 
			
		||||
						case 77:
 | 
			
		||||
							format = TextureFormat.BC3;
 | 
			
		||||
							break;
 | 
			
		||||
 | 
			
		||||
						case 98:
 | 
			
		||||
							format = TextureFormat.BC7;
 | 
			
		||||
							break;
 | 
			
		||||
 | 
			
		||||
						default:
 | 
			
		||||
							throw new NotSupportedException(
 | 
			
		||||
								"Unsupported DDS texture format"
 | 
			
		||||
							);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					uint resourceDimension = reader.ReadUInt32();
 | 
			
		||||
 | 
			
		||||
					// These values are taken from the D3D10_RESOURCE_DIMENSION enum.
 | 
			
		||||
					switch (resourceDimension)
 | 
			
		||||
					{
 | 
			
		||||
						case 0: // Unknown
 | 
			
		||||
						case 1: // Buffer
 | 
			
		||||
							throw new NotSupportedException(
 | 
			
		||||
								"Unsupported DDS texture format"
 | 
			
		||||
							);
 | 
			
		||||
						default:
 | 
			
		||||
							break;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					/*
 | 
			
		||||
					 * This flag seemingly only indicates if the texture is a cube map.
 | 
			
		||||
					 * This is already determined above. Cool!
 | 
			
		||||
					 */
 | 
			
		||||
					uint miscFlag = reader.ReadUInt32();
 | 
			
		||||
 | 
			
		||||
					/*
 | 
			
		||||
					 * Indicates the number of elements in the texture array.
 | 
			
		||||
					 * We don't support texture arrays so just throw if it's greater than 1.
 | 
			
		||||
					 */
 | 
			
		||||
					uint arraySize = reader.ReadUInt32();
 | 
			
		||||
 | 
			
		||||
					if (arraySize > 1)
 | 
			
		||||
					{
 | 
			
		||||
						throw new NotSupportedException(
 | 
			
		||||
							"Unsupported DDS texture format"
 | 
			
		||||
						);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					reader.ReadUInt32(); // reserved
 | 
			
		||||
 | 
			
		||||
					break;
 | 
			
		||||
				default:
 | 
			
		||||
					throw new NotSupportedException(
 | 
			
		||||
						"Unsupported DDS texture format"
 | 
			
		||||
					);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else if ((formatFlags & DDPF_RGB) == DDPF_RGB)
 | 
			
		||||
		{
 | 
			
		||||
			if (	formatRGBBitCount != 32 ||
 | 
			
		||||
				formatRBitMask != 0x00FF0000 ||
 | 
			
		||||
				formatGBitMask != 0x0000FF00 ||
 | 
			
		||||
				formatBBitMask != 0x000000FF ||
 | 
			
		||||
				formatABitMask != 0xFF000000	)
 | 
			
		||||
			{
 | 
			
		||||
				throw new NotSupportedException(
 | 
			
		||||
					"Unsupported DDS texture format"
 | 
			
		||||
				);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			format = TextureFormat.B8G8R8A8;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotSupportedException(
 | 
			
		||||
				"Unsupported DDS texture format"
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static int CalculateDDSLevelSize(
 | 
			
		||||
		int width,
 | 
			
		||||
		int height,
 | 
			
		||||
		TextureFormat format
 | 
			
		||||
	) {
 | 
			
		||||
		if (format == TextureFormat.R8G8B8A8)
 | 
			
		||||
		{
 | 
			
		||||
			return (((width * 32) + 7) / 8) * height;
 | 
			
		||||
		}
 | 
			
		||||
		else if (format == TextureFormat.R16G16B16A16_SFLOAT)
 | 
			
		||||
		{
 | 
			
		||||
			return (((width * 64) + 7) / 8) * height;
 | 
			
		||||
		}
 | 
			
		||||
		else if (format == TextureFormat.R32G32B32A32_SFLOAT)
 | 
			
		||||
		{
 | 
			
		||||
			return (((width * 128) + 7) / 8) * height;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			int blockSize = 16;
 | 
			
		||||
			if (format == TextureFormat.BC1)
 | 
			
		||||
			{
 | 
			
		||||
				blockSize = 8;
 | 
			
		||||
			}
 | 
			
		||||
			width = System.Math.Max(width, 1);
 | 
			
		||||
			height = System.Math.Max(height, 1);
 | 
			
		||||
			return (
 | 
			
		||||
				((width + 3) / 4) *
 | 
			
		||||
				((height + 3) / 4) *
 | 
			
		||||
				blockSize
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										161
									
								
								Nerfed.Runtime/Graphics/PackedVector/Alpha8.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								Nerfed.Runtime/Graphics/PackedVector/Alpha8.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,161 @@
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Packed vector type containing unsigned normalized values ranging from 0 to 1.
 | 
			
		||||
/// The x and z components use 5 bits, and the y component uses 6 bits.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public struct Alpha8 : IPackedVector<byte>, IEquatable<Alpha8>, IPackedVector
 | 
			
		||||
{
 | 
			
		||||
	#region Public Properties
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets and sets the packed value.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public byte PackedValue
 | 
			
		||||
	{
 | 
			
		||||
		get
 | 
			
		||||
		{
 | 
			
		||||
			return packedValue;
 | 
			
		||||
		}
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
			packedValue = value;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Variables
 | 
			
		||||
 | 
			
		||||
	private byte packedValue;
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Constructor
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a new instance of Alpha8.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="alpha">The alpha component</param>
 | 
			
		||||
	public Alpha8(float alpha)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(alpha);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets the packed vector in float format.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The packed vector in Vector3 format</returns>
 | 
			
		||||
	public float ToAlpha()
 | 
			
		||||
	{
 | 
			
		||||
		return (float) (packedValue / 255.0f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region IPackedVector Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Sets the packed vector from a Vector4.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">Vector containing the components.</param>
 | 
			
		||||
	void IPackedVector.PackFromVector4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.W);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets the packed vector in Vector4 format.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The packed vector in Vector4 format</returns>
 | 
			
		||||
	Vector4 IPackedVector.ToVector4()
 | 
			
		||||
	{
 | 
			
		||||
		return new Vector4(
 | 
			
		||||
			0.0f,
 | 
			
		||||
			0.0f,
 | 
			
		||||
			0.0f,
 | 
			
		||||
			(float) (packedValue / 255.0f)
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Static Operators and Override Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares an object with the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="obj">The object to compare.</param>
 | 
			
		||||
	/// <returns>True if the object is equal to the packed vector.</returns>
 | 
			
		||||
	public override bool Equals(object obj)
 | 
			
		||||
	{
 | 
			
		||||
		return (obj is Alpha8) && Equals((Alpha8) obj);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares another Bgra5551 packed vector with the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="other">The Bgra5551 packed vector to compare.</param>
 | 
			
		||||
	/// <returns>True if the packed vectors are equal.</returns>
 | 
			
		||||
	public bool Equals(Alpha8 other)
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue == other.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets a string representation of the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>A string representation of the packed vector.</returns>
 | 
			
		||||
	public override string ToString()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.ToString("X");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets a hash code of the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The hash code for the packed vector.</returns>
 | 
			
		||||
	public override int GetHashCode()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.GetHashCode();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator ==(Alpha8 lhs, Alpha8 rhs)
 | 
			
		||||
	{
 | 
			
		||||
		return lhs.packedValue == rhs.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator !=(Alpha8 lhs, Alpha8 rhs)
 | 
			
		||||
	{
 | 
			
		||||
		return lhs.packedValue != rhs.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Static Pack Method
 | 
			
		||||
 | 
			
		||||
	private static byte Pack(float alpha)
 | 
			
		||||
	{
 | 
			
		||||
		return (byte) System.Math.Round(Math.Clamp(alpha, 0, 1) * 255.0f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										184
									
								
								Nerfed.Runtime/Graphics/PackedVector/Bgr565.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								Nerfed.Runtime/Graphics/PackedVector/Bgr565.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,184 @@
 | 
			
		||||
#region License
 | 
			
		||||
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
#region Using Statements
 | 
			
		||||
using System;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Packed vector type containing unsigned normalized values ranging from 0 to 1.
 | 
			
		||||
/// The x and z components use 5 bits, and the y component uses 6 bits.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public struct Bgr565 : IPackedVector<ushort>, IEquatable<Bgr565>, IPackedVector
 | 
			
		||||
{
 | 
			
		||||
	#region Public Properties
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets and sets the packed value.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public ushort PackedValue
 | 
			
		||||
	{
 | 
			
		||||
		get
 | 
			
		||||
		{
 | 
			
		||||
			return packedValue;
 | 
			
		||||
		}
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
			packedValue = value;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Variables
 | 
			
		||||
 | 
			
		||||
	private ushort packedValue;
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Constructors
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a new instance of Bgr565.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="x">The x component</param>
 | 
			
		||||
	/// <param name="y">The y component</param>
 | 
			
		||||
	/// <param name="z">The z component</param>
 | 
			
		||||
	public Bgr565(float x, float y, float z)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(x, y, z);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a new instance of Bgr565.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">
 | 
			
		||||
	/// Vector containing the components for the packed vector.
 | 
			
		||||
	/// </param>
 | 
			
		||||
	public Bgr565(Vector3 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y, vector.Z);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets the packed vector in Vector3 format.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The packed vector in Vector3 format</returns>
 | 
			
		||||
	public Vector3 ToVector3()
 | 
			
		||||
	{
 | 
			
		||||
		return new Vector3(
 | 
			
		||||
			(packedValue >> 11) / 31.0f,
 | 
			
		||||
			((packedValue >> 5) & 0x3F) / 63.0f,
 | 
			
		||||
			(packedValue & 0x1F) / 31.0f
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region IPackedVector Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Sets the packed vector from a Vector4.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">Vector containing the components.</param>
 | 
			
		||||
	void IPackedVector.PackFromVector4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		Pack(vector.X, vector.Y, vector.Z);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets the packed vector in Vector4 format.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The packed vector in Vector4 format</returns>
 | 
			
		||||
	Vector4 IPackedVector.ToVector4()
 | 
			
		||||
	{
 | 
			
		||||
		return new Vector4(ToVector3(), 1.0f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Static Operators and Override Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares an object with the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="obj">The object to compare.</param>
 | 
			
		||||
	/// <returns>True if the object is equal to the packed vector.</returns>
 | 
			
		||||
	public override bool Equals(object obj)
 | 
			
		||||
	{
 | 
			
		||||
		return (obj is Bgr565) && Equals((Bgr565) obj);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares another Bgr565 packed vector with the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="other">The Bgr565 packed vector to compare.</param>
 | 
			
		||||
	/// <returns>True if the packed vectors are equal.</returns>
 | 
			
		||||
	public bool Equals(Bgr565 other)
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue == other.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets a string representation of the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>A string representation of the packed vector.</returns>
 | 
			
		||||
	public override string ToString()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.ToString("X");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets a hash code of the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The hash code for the packed vector.</returns>
 | 
			
		||||
	public override int GetHashCode()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.GetHashCode();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator ==(Bgr565 lhs, Bgr565 rhs)
 | 
			
		||||
	{
 | 
			
		||||
		return lhs.packedValue == rhs.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator !=(Bgr565 lhs, Bgr565 rhs)
 | 
			
		||||
	{
 | 
			
		||||
		return lhs.packedValue != rhs.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Static Pack Method
 | 
			
		||||
 | 
			
		||||
	private static ushort Pack(float x, float y, float z)
 | 
			
		||||
	{
 | 
			
		||||
		return (ushort) (
 | 
			
		||||
			(((ushort) System.Math.Round(Math.Clamp(x, 0, 1) * 31.0f)) << 11) |
 | 
			
		||||
			(((ushort) System.Math.Round(Math.Clamp(y, 0, 1) * 63.0f)) << 5) |
 | 
			
		||||
			((ushort) System.Math.Round(Math.Clamp(z, 0, 1) * 31.0f))
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										178
									
								
								Nerfed.Runtime/Graphics/PackedVector/Bgra4444.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								Nerfed.Runtime/Graphics/PackedVector/Bgra4444.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,178 @@
 | 
			
		||||
#region License
 | 
			
		||||
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
#region Using Statements
 | 
			
		||||
using System;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Packed vector type containing unsigned normalized values, ranging from 0 to 1, using
 | 
			
		||||
/// 4 bits each for x, y, z, and w.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public struct Bgra4444 : IPackedVector<ushort>, IEquatable<Bgra4444>
 | 
			
		||||
{
 | 
			
		||||
	#region Public Properties
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets and sets the packed value.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public ushort PackedValue
 | 
			
		||||
	{
 | 
			
		||||
		get
 | 
			
		||||
		{
 | 
			
		||||
			return packedValue;
 | 
			
		||||
		}
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
			packedValue = value;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Variables
 | 
			
		||||
 | 
			
		||||
	private ushort packedValue;
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Constructors
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a new instance of Bgra4444.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="x">The x component</param>
 | 
			
		||||
	/// <param name="y">The y component</param>
 | 
			
		||||
	/// <param name="z">The z component</param>
 | 
			
		||||
	/// <param name="w">The w component</param>
 | 
			
		||||
	public Bgra4444(float x, float y, float z, float w)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(x, y, z, w);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a new instance of Bgra4444.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">
 | 
			
		||||
	/// Vector containing the components for the packed vector.
 | 
			
		||||
	/// </param>
 | 
			
		||||
	public Bgra4444(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets the packed vector in Vector4 format.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The packed vector in Vector4 format</returns>
 | 
			
		||||
	public Vector4 ToVector4()
 | 
			
		||||
	{
 | 
			
		||||
		return new Vector4(
 | 
			
		||||
			((packedValue >> 8) & 0x0F) / 15.0f,
 | 
			
		||||
			((packedValue >> 4) & 0x0F) / 15.0f,
 | 
			
		||||
			(packedValue & 0x0F) / 15.0f,
 | 
			
		||||
			(packedValue >> 12) / 15.0f
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region IPackedVector Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Sets the packed vector from a Vector4.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">Vector containing the components.</param>
 | 
			
		||||
	void IPackedVector.PackFromVector4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Static Operators and Override Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares an object with the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="obj">The object to compare.</param>
 | 
			
		||||
	/// <returns>True if the object is equal to the packed vector.</returns>
 | 
			
		||||
	public override bool Equals(object obj)
 | 
			
		||||
	{
 | 
			
		||||
		return (obj is Bgra4444) && Equals((Bgra4444) obj);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares another Bgra4444 packed vector with the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="other">The Bgra4444 packed vector to compare.</param>
 | 
			
		||||
	/// <returns>True if the packed vectors are equal.</returns>
 | 
			
		||||
	public bool Equals(Bgra4444 other)
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue == other.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets a string representation of the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>A string representation of the packed vector.</returns>
 | 
			
		||||
	public override string ToString()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.ToString("X");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets a hash code of the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The hash code for the packed vector.</returns>
 | 
			
		||||
	public override int GetHashCode()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.GetHashCode();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator ==(Bgra4444 lhs, Bgra4444 rhs)
 | 
			
		||||
	{
 | 
			
		||||
		return lhs.packedValue == rhs.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator !=(Bgra4444 lhs, Bgra4444 rhs)
 | 
			
		||||
	{
 | 
			
		||||
		return lhs.packedValue != rhs.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Static Pack Method
 | 
			
		||||
 | 
			
		||||
	private static ushort Pack(float x, float y, float z, float w)
 | 
			
		||||
	{
 | 
			
		||||
		return (ushort) (
 | 
			
		||||
			(((ushort) System.Math.Round(Math.Clamp(x, 0, 1) * 15.0f)) << 8) |
 | 
			
		||||
			(((ushort) System.Math.Round(Math.Clamp(y, 0, 1) * 15.0f)) << 4) |
 | 
			
		||||
			((ushort) System.Math.Round(Math.Clamp(z, 0, 1) * 15.0f)) |
 | 
			
		||||
			(((ushort) System.Math.Round(Math.Clamp(w, 0, 1) * 15.0f)) << 12)
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										178
									
								
								Nerfed.Runtime/Graphics/PackedVector/Bgra5551.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								Nerfed.Runtime/Graphics/PackedVector/Bgra5551.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,178 @@
 | 
			
		||||
#region License
 | 
			
		||||
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
#region Using Statements
 | 
			
		||||
using System;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Packed vector type containing unsigned normalized values ranging from 0 to 1.
 | 
			
		||||
/// The x and z components use 5 bits, and the y component uses 6 bits.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public struct Bgra5551 : IPackedVector<ushort>, IEquatable<Bgra5551>, IPackedVector
 | 
			
		||||
{
 | 
			
		||||
	#region Public Properties
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets and sets the packed value.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public ushort PackedValue
 | 
			
		||||
	{
 | 
			
		||||
		get
 | 
			
		||||
		{
 | 
			
		||||
			return packedValue;
 | 
			
		||||
		}
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
			packedValue = value;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Variables
 | 
			
		||||
 | 
			
		||||
	private ushort packedValue;
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Constructors
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a new instance of Bgra5551.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="x">The x component</param>
 | 
			
		||||
	/// <param name="y">The y component</param>
 | 
			
		||||
	/// <param name="z">The z component</param>
 | 
			
		||||
	/// <param name="w">The w component</param>
 | 
			
		||||
	public Bgra5551(float x, float y, float z, float w)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(x, y, z, w);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a new instance of Bgra5551.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">
 | 
			
		||||
	/// Vector containing the components for the packed vector.
 | 
			
		||||
	/// </param>
 | 
			
		||||
	public Bgra5551(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets the packed vector in Vector4 format.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The packed vector in Vector4 format</returns>
 | 
			
		||||
	public Vector4 ToVector4()
 | 
			
		||||
	{
 | 
			
		||||
		return new Vector4(
 | 
			
		||||
			((packedValue >> 10) & 0x1F) / 31.0f,
 | 
			
		||||
			((packedValue >> 5) & 0x1F) / 31.0f,
 | 
			
		||||
			(packedValue & 0x1F) / 31.0f,
 | 
			
		||||
			(float) (packedValue >> 15)
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region IPackedVector Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Sets the packed vector from a Vector4.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">Vector containing the components.</param>
 | 
			
		||||
	void IPackedVector.PackFromVector4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Static Operators and Override Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares an object with the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="obj">The object to compare.</param>
 | 
			
		||||
	/// <returns>True if the object is equal to the packed vector.</returns>
 | 
			
		||||
	public override bool Equals(object obj)
 | 
			
		||||
	{
 | 
			
		||||
		return (obj is Bgra5551) && Equals((Bgra5551) obj);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares another Bgra5551 packed vector with the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="other">The Bgra5551 packed vector to compare.</param>
 | 
			
		||||
	/// <returns>True if the packed vectors are equal.</returns>
 | 
			
		||||
	public bool Equals(Bgra5551 other)
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue == other.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets a string representation of the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>A string representation of the packed vector.</returns>
 | 
			
		||||
	public override string ToString()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.ToString("X");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets a hash code of the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The hash code for the packed vector.</returns>
 | 
			
		||||
	public override int GetHashCode()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.GetHashCode();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator ==(Bgra5551 lhs, Bgra5551 rhs)
 | 
			
		||||
	{
 | 
			
		||||
		return lhs.packedValue == rhs.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator !=(Bgra5551 lhs, Bgra5551 rhs)
 | 
			
		||||
	{
 | 
			
		||||
		return lhs.packedValue != rhs.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Static Pack Method
 | 
			
		||||
 | 
			
		||||
	private static ushort Pack(float x, float y, float z, float w)
 | 
			
		||||
	{
 | 
			
		||||
		return (ushort) (
 | 
			
		||||
			(((ushort) System.Math.Round(Math.Clamp(x, 0, 1) * 31.0f)) << 10) |
 | 
			
		||||
			(((ushort) System.Math.Round(Math.Clamp(y, 0, 1) * 31.0f)) << 5) |
 | 
			
		||||
			((ushort) System.Math.Round(Math.Clamp(z, 0, 1) * 31.0f)) |
 | 
			
		||||
			((ushort) System.Math.Round(Math.Clamp(w, 0, 1)) << 15)
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										204
									
								
								Nerfed.Runtime/Graphics/PackedVector/Byte4.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										204
									
								
								Nerfed.Runtime/Graphics/PackedVector/Byte4.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,204 @@
 | 
			
		||||
#region License
 | 
			
		||||
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
#region Using Statements
 | 
			
		||||
using System;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Packed vector type containing four 8-bit unsigned integer values, ranging from 0 to 255.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public struct Byte4 : IPackedVector<uint>, IEquatable<Byte4>, IPackedVector
 | 
			
		||||
{
 | 
			
		||||
	#region Public Properties
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Directly gets or sets the packed representation of the value.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <value>The packed representation of the value.</value>
 | 
			
		||||
	public uint PackedValue
 | 
			
		||||
	{
 | 
			
		||||
		get
 | 
			
		||||
		{
 | 
			
		||||
			return packedValue;
 | 
			
		||||
		}
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
			packedValue = value;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Variables
 | 
			
		||||
 | 
			
		||||
	private uint packedValue;
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Constructors
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Initializes a new instance of the Byte4 class.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">
 | 
			
		||||
	/// A vector containing the initial values for the components of the Byte4 structure.
 | 
			
		||||
	/// </param>
 | 
			
		||||
	public Byte4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Initializes a new instance of the Byte4 class.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="x">Initial value for the x component.</param>
 | 
			
		||||
	/// <param name="y">Initial value for the y component.</param>
 | 
			
		||||
	/// <param name="z">Initial value for the z component.</param>
 | 
			
		||||
	/// <param name="w">Initial value for the w component.</param>
 | 
			
		||||
	public Byte4(float x, float y, float z, float w)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(x, y, z, w);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Expands the packed representation into a Vector4.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The expanded vector.</returns>
 | 
			
		||||
	public Vector4 ToVector4()
 | 
			
		||||
	{
 | 
			
		||||
		return new Vector4(
 | 
			
		||||
			(packedValue & 0xFF),
 | 
			
		||||
			((packedValue >> 8) & 0xFF),
 | 
			
		||||
			((packedValue >> 16) & 0xFF),
 | 
			
		||||
			(packedValue >> 24)
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region IPackedVector Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Sets the packed representation from a Vector4.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">The vector to create the packed representation from.</param>
 | 
			
		||||
	void IPackedVector.PackFromVector4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Static Operators and Override Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares the current instance of a class to another instance to determine
 | 
			
		||||
	/// whether they are different.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="a">The object to the left of the equality operator.</param>
 | 
			
		||||
	/// <param name="b">The object to the right of the equality operator.</param>
 | 
			
		||||
	/// <returns>True if the objects are different; false otherwise.</returns>
 | 
			
		||||
	public static bool operator !=(Byte4 a, Byte4 b)
 | 
			
		||||
	{
 | 
			
		||||
		return a.packedValue != b.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares the current instance of a class to another instance to determine
 | 
			
		||||
	/// whether they are the same.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="a">The object to the left of the equality operator.</param>
 | 
			
		||||
	/// <param name="b">The object to the right of the equality operator.</param>
 | 
			
		||||
	/// <returns>True if the objects are the same; false otherwise.</returns>
 | 
			
		||||
	public static bool operator ==(Byte4 a, Byte4 b)
 | 
			
		||||
	{
 | 
			
		||||
		return a.packedValue == b.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Returns a value that indicates whether the current instance is equal to a
 | 
			
		||||
	/// specified object.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="obj">The object with which to make the comparison.</param>
 | 
			
		||||
	/// <returns>
 | 
			
		||||
	/// True if the current instance is equal to the specified object; false otherwise.
 | 
			
		||||
	/// </returns>
 | 
			
		||||
	public override bool Equals(object obj)
 | 
			
		||||
	{
 | 
			
		||||
		return (obj is Byte4) && Equals((Byte4) obj);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Returns a value that indicates whether the current instance is equal to a
 | 
			
		||||
	/// specified object.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="other">The object with which to make the comparison.</param>
 | 
			
		||||
	/// <returns>
 | 
			
		||||
	/// True if the current instance is equal to the specified object; false otherwise.
 | 
			
		||||
	/// </returns>
 | 
			
		||||
	public bool Equals(Byte4 other)
 | 
			
		||||
	{
 | 
			
		||||
		return this == other;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets the hash code for the current instance.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>Hash code for the instance.</returns>
 | 
			
		||||
	public override int GetHashCode()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.GetHashCode();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Returns a string representation of the current instance.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>String that represents the object.</returns>
 | 
			
		||||
	public override string ToString()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.ToString("X");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Static Pack Method
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Packs a vector into a uint.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">The vector containing the values to pack.</param>
 | 
			
		||||
	/// <returns>The ulong containing the packed values.</returns>
 | 
			
		||||
	static uint Pack(float x, float y, float z, float w)
 | 
			
		||||
	{
 | 
			
		||||
		return (uint) (
 | 
			
		||||
			((uint) System.Math.Round(Math.Clamp(x, 0, 255))) |
 | 
			
		||||
			((uint) System.Math.Round(Math.Clamp(y, 0, 255)) << 8) |
 | 
			
		||||
			((uint) System.Math.Round(Math.Clamp(z, 0, 255)) << 16) |
 | 
			
		||||
			((uint) System.Math.Round(Math.Clamp(w, 0, 255)) << 24)
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										113
									
								
								Nerfed.Runtime/Graphics/PackedVector/HalfSingle.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								Nerfed.Runtime/Graphics/PackedVector/HalfSingle.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,113 @@
 | 
			
		||||
#region License
 | 
			
		||||
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
#region Using Statements
 | 
			
		||||
using System;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
public struct HalfSingle : IPackedVector<ushort>, IEquatable<HalfSingle>, IPackedVector
 | 
			
		||||
{
 | 
			
		||||
	#region Public Properties
 | 
			
		||||
 | 
			
		||||
	public ushort PackedValue
 | 
			
		||||
	{
 | 
			
		||||
		get
 | 
			
		||||
		{
 | 
			
		||||
			return packedValue;
 | 
			
		||||
		}
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
			packedValue = value;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Variables
 | 
			
		||||
 | 
			
		||||
	private ushort packedValue;
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Constructors
 | 
			
		||||
 | 
			
		||||
	public HalfSingle(float single)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = HalfTypeHelper.Convert(single);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Methods
 | 
			
		||||
 | 
			
		||||
	public float ToSingle()
 | 
			
		||||
	{
 | 
			
		||||
		return HalfTypeHelper.Convert(packedValue);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region IPackedVector Methods
 | 
			
		||||
 | 
			
		||||
	void IPackedVector.PackFromVector4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = HalfTypeHelper.Convert(vector.X);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Vector4 IPackedVector.ToVector4()
 | 
			
		||||
	{
 | 
			
		||||
		return new Vector4(ToSingle(), 0.0f, 0.0f, 1.0f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Static Operators and Override Methods
 | 
			
		||||
 | 
			
		||||
	public override bool Equals(object obj)
 | 
			
		||||
	{
 | 
			
		||||
		return (obj is HalfSingle) && Equals((HalfSingle) obj);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public bool Equals(HalfSingle other)
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue == other.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override string ToString()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.ToString("X");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override int GetHashCode()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.GetHashCode();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator ==(HalfSingle lhs, HalfSingle rhs)
 | 
			
		||||
	{
 | 
			
		||||
		return lhs.packedValue == rhs.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator !=(HalfSingle lhs, HalfSingle rhs)
 | 
			
		||||
	{
 | 
			
		||||
		return lhs.packedValue != rhs.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										138
									
								
								Nerfed.Runtime/Graphics/PackedVector/HalfTypeHelper.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								Nerfed.Runtime/Graphics/PackedVector/HalfTypeHelper.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,138 @@
 | 
			
		||||
#region License
 | 
			
		||||
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
#region Using Statements
 | 
			
		||||
using System;
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
internal static class HalfTypeHelper
 | 
			
		||||
{
 | 
			
		||||
	#region Private Struct uif
 | 
			
		||||
 | 
			
		||||
	[StructLayout(LayoutKind.Explicit)]
 | 
			
		||||
	private struct uif
 | 
			
		||||
	{
 | 
			
		||||
		[FieldOffset(0)]
 | 
			
		||||
		public float f;
 | 
			
		||||
		[FieldOffset(0)]
 | 
			
		||||
		public int i;
 | 
			
		||||
		[FieldOffset(0)]
 | 
			
		||||
		public uint u;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Internal Static Methods
 | 
			
		||||
 | 
			
		||||
	internal static ushort Convert(float f)
 | 
			
		||||
	{
 | 
			
		||||
		uif uif = new uif();
 | 
			
		||||
		uif.f = f;
 | 
			
		||||
		return Convert(uif.i);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	internal static ushort Convert(int i)
 | 
			
		||||
	{
 | 
			
		||||
		int s = (i >> 16) & 0x00008000;
 | 
			
		||||
		int e = ((i >> 23) & 0x000000ff) - (127 - 15);
 | 
			
		||||
		int m = i & 0x007fffff;
 | 
			
		||||
 | 
			
		||||
		if (e <= 0)
 | 
			
		||||
		{
 | 
			
		||||
			if (e < -10)
 | 
			
		||||
			{
 | 
			
		||||
				return (ushort) s;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			m = m | 0x00800000;
 | 
			
		||||
 | 
			
		||||
			int t = 14 - e;
 | 
			
		||||
			int a = (1 << (t - 1)) - 1;
 | 
			
		||||
			int b = (m >> t) & 1;
 | 
			
		||||
 | 
			
		||||
			m = (m + a + b) >> t;
 | 
			
		||||
 | 
			
		||||
			return (ushort) (s | m);
 | 
			
		||||
		}
 | 
			
		||||
		else if (e == 0xff - (127 - 15))
 | 
			
		||||
		{
 | 
			
		||||
			if (m == 0)
 | 
			
		||||
			{
 | 
			
		||||
				return (ushort) (s | 0x7c00);
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				m >>= 13;
 | 
			
		||||
				return (ushort) (s | 0x7c00 | m | ((m == 0) ? 1 : 0));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			m = m + 0x00000fff + ((m >> 13) & 1);
 | 
			
		||||
 | 
			
		||||
			if ((m & 0x00800000) != 0)
 | 
			
		||||
			{
 | 
			
		||||
				m = 0;
 | 
			
		||||
				e += 1;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (e > 30)
 | 
			
		||||
			{
 | 
			
		||||
				return (ushort) (s | 0x7c00);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return (ushort) (s | (e << 10) | (m >> 13));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	internal static float Convert(ushort value)
 | 
			
		||||
	{
 | 
			
		||||
		uint rst;
 | 
			
		||||
		uint mantissa = (uint) (value & 1023);
 | 
			
		||||
		uint exp = 0xfffffff2;
 | 
			
		||||
 | 
			
		||||
		if ((value & -33792) == 0)
 | 
			
		||||
		{
 | 
			
		||||
			if (mantissa != 0)
 | 
			
		||||
			{
 | 
			
		||||
				while ((mantissa & 1024) == 0)
 | 
			
		||||
				{
 | 
			
		||||
					exp--;
 | 
			
		||||
					mantissa = mantissa << 1;
 | 
			
		||||
				}
 | 
			
		||||
				mantissa &= 0xfffffbff;
 | 
			
		||||
				rst = ((uint) ((((uint) value & 0x8000) << 16) | ((exp + 127) << 23))) | (mantissa << 13);
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				rst = (uint) ((value & 0x8000) << 16);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			rst = (uint) (((((uint) value & 0x8000) << 16) | ((((((uint) value >> 10) & 0x1f) - 15) + 127) << 23)) | (mantissa << 13));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		uif uif = new uif();
 | 
			
		||||
		uif.u = rst;
 | 
			
		||||
		return uif.f;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										133
									
								
								Nerfed.Runtime/Graphics/PackedVector/HalfVector2.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								Nerfed.Runtime/Graphics/PackedVector/HalfVector2.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,133 @@
 | 
			
		||||
#region License
 | 
			
		||||
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
#region Using Statements
 | 
			
		||||
using System;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
public struct HalfVector2 : IPackedVector<uint>, IPackedVector, IEquatable<HalfVector2>
 | 
			
		||||
{
 | 
			
		||||
	#region Public Properties
 | 
			
		||||
 | 
			
		||||
	public uint PackedValue
 | 
			
		||||
	{
 | 
			
		||||
		get
 | 
			
		||||
		{
 | 
			
		||||
			return packedValue;
 | 
			
		||||
		}
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
			packedValue = value;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Variables
 | 
			
		||||
 | 
			
		||||
	private uint packedValue;
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Constructors
 | 
			
		||||
 | 
			
		||||
	public HalfVector2(float x, float y)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = PackHelper(x, y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public HalfVector2(Vector2 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = PackHelper(vector.X, vector.Y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Methods
 | 
			
		||||
 | 
			
		||||
	public Vector2 ToVector2()
 | 
			
		||||
	{
 | 
			
		||||
		Vector2 vector;
 | 
			
		||||
		vector.X = HalfTypeHelper.Convert((ushort) packedValue);
 | 
			
		||||
		vector.Y = HalfTypeHelper.Convert((ushort) (packedValue >> 0x10));
 | 
			
		||||
		return vector;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region IPackedVector Methods
 | 
			
		||||
 | 
			
		||||
	void IPackedVector.PackFromVector4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = PackHelper(vector.X, vector.Y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Vector4 IPackedVector.ToVector4()
 | 
			
		||||
	{
 | 
			
		||||
		return new Vector4(ToVector2(), 0.0f, 1.0f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Static Operators and Override Methods
 | 
			
		||||
 | 
			
		||||
	public override string ToString()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.ToString("X");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override int GetHashCode()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.GetHashCode();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override bool Equals(object obj)
 | 
			
		||||
	{
 | 
			
		||||
		return ((obj is HalfVector2) && Equals((HalfVector2) obj));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public bool Equals(HalfVector2 other)
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.Equals(other.packedValue);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator ==(HalfVector2 a, HalfVector2 b)
 | 
			
		||||
	{
 | 
			
		||||
		return a.Equals(b);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator !=(HalfVector2 a, HalfVector2 b)
 | 
			
		||||
	{
 | 
			
		||||
		return !a.Equals(b);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Static Pack Method
 | 
			
		||||
 | 
			
		||||
	private static uint PackHelper(float vectorX, float vectorY)
 | 
			
		||||
	{
 | 
			
		||||
		return (uint) (
 | 
			
		||||
			HalfTypeHelper.Convert(vectorX) |
 | 
			
		||||
			((uint) (HalfTypeHelper.Convert(vectorY) << 0x10))
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										204
									
								
								Nerfed.Runtime/Graphics/PackedVector/HalfVector4.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										204
									
								
								Nerfed.Runtime/Graphics/PackedVector/HalfVector4.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,204 @@
 | 
			
		||||
#region License
 | 
			
		||||
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
#region Using Statements
 | 
			
		||||
using System;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Packed vector type containing four 16-bit floating-point values.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public struct HalfVector4 : IPackedVector<ulong>, IPackedVector, IEquatable<HalfVector4>
 | 
			
		||||
{
 | 
			
		||||
	#region Public Properties
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Directly gets or sets the packed representation of the value.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <value>The packed representation of the value.</value>
 | 
			
		||||
	public ulong PackedValue
 | 
			
		||||
	{
 | 
			
		||||
		get
 | 
			
		||||
		{
 | 
			
		||||
			return packedValue;
 | 
			
		||||
		}
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
			packedValue = value;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Variables
 | 
			
		||||
 | 
			
		||||
	private ulong packedValue;
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Constructors
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Initializes a new instance of the HalfVector4 structure.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="x">Initial value for the x component.</param>
 | 
			
		||||
	/// <param name="y">Initial value for the y component.</param>
 | 
			
		||||
	/// <param name="z">Initial value for the z component.</param>
 | 
			
		||||
	/// <param name="w">Initial value for the q component.</param>
 | 
			
		||||
	public HalfVector4(float x, float y, float z, float w)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(x, y, z, w);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Initializes a new instance of the HalfVector4 structure.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">
 | 
			
		||||
	/// A vector containing the initial values for the components of the HalfVector4
 | 
			
		||||
	/// structure.
 | 
			
		||||
	/// </param>
 | 
			
		||||
	public HalfVector4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Expands the packed representation into a Vector4.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The expanded vector.</returns>
 | 
			
		||||
	public Vector4 ToVector4()
 | 
			
		||||
	{
 | 
			
		||||
		return new Vector4(
 | 
			
		||||
			HalfTypeHelper.Convert((ushort) packedValue),
 | 
			
		||||
			HalfTypeHelper.Convert((ushort) (packedValue >> 0x10)),
 | 
			
		||||
			HalfTypeHelper.Convert((ushort) (packedValue >> 0x20)),
 | 
			
		||||
			HalfTypeHelper.Convert((ushort) (packedValue >> 0x30))
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region IPackedVector Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Sets the packed representation from a Vector4.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">The vector to create the packed representation from.</param>
 | 
			
		||||
	void IPackedVector.PackFromVector4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Static Operators and Override Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Returns a string representation of the current instance.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>String that represents the object.</returns>
 | 
			
		||||
	public override string ToString()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.ToString("X");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets the hash code for the current instance.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>Hash code for the instance.</returns>
 | 
			
		||||
	public override int GetHashCode()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.GetHashCode();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Returns a value that indicates whether the current instance is equal to a
 | 
			
		||||
	/// specified object.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="obj">The object with which to make the comparison.</param>
 | 
			
		||||
	/// <returns>
 | 
			
		||||
	/// True if the current instance is equal to the specified object; false otherwise.
 | 
			
		||||
	/// </returns>
 | 
			
		||||
	public override bool Equals(object obj)
 | 
			
		||||
	{
 | 
			
		||||
		return ((obj is HalfVector4) && Equals((HalfVector4) obj));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Returns a value that indicates whether the current instance is equal to a
 | 
			
		||||
	/// specified object.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="other">The object with which to make the comparison.</param>
 | 
			
		||||
	/// <returns>
 | 
			
		||||
	/// True if the current instance is equal to the specified object; false otherwise.
 | 
			
		||||
	/// </returns>
 | 
			
		||||
	public bool Equals(HalfVector4 other)
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.Equals(other.packedValue);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares the current instance of a class to another instance to determine
 | 
			
		||||
	/// whether they are the same.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="a">The object to the left of the equality operator.</param>
 | 
			
		||||
	/// <param name="b">The object to the right of the equality operator.</param>
 | 
			
		||||
	/// <returns>True if the objects are the same; false otherwise.</returns>
 | 
			
		||||
	public static bool operator ==(HalfVector4 a, HalfVector4 b)
 | 
			
		||||
	{
 | 
			
		||||
		return a.Equals(b);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares the current instance of a class to another instance to determine
 | 
			
		||||
	/// whether they are different.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="a">The object to the left of the equality operator.</param>
 | 
			
		||||
	/// <param name="b">The object to the right of the equality operator.</param>
 | 
			
		||||
	/// <returns>True if the objects are different; false otherwise.</returns>
 | 
			
		||||
	public static bool operator !=(HalfVector4 a, HalfVector4 b)
 | 
			
		||||
	{
 | 
			
		||||
		return !a.Equals(b);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Static Pack Method
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Packs a vector into a ulong.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">The vector containing the values to pack.</param>
 | 
			
		||||
	/// <returns>The ulong containing the packed values.</returns>
 | 
			
		||||
	private static ulong Pack(float x, float y, float z, float w)
 | 
			
		||||
	{
 | 
			
		||||
		return (ulong) (
 | 
			
		||||
			((ulong) HalfTypeHelper.Convert(x)) |
 | 
			
		||||
			(((ulong) HalfTypeHelper.Convert(y) << 0x10)) |
 | 
			
		||||
			(((ulong) HalfTypeHelper.Convert(z) << 0x20)) |
 | 
			
		||||
			(((ulong) HalfTypeHelper.Convert(w) << 0x30))
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								Nerfed.Runtime/Graphics/PackedVector/IPackedVector.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								Nerfed.Runtime/Graphics/PackedVector/IPackedVector.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
#region License
 | 
			
		||||
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
// http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.packedvector.ipackedvector.aspx
 | 
			
		||||
public interface IPackedVector
 | 
			
		||||
{
 | 
			
		||||
	void PackFromVector4(Vector4 vector);
 | 
			
		||||
 | 
			
		||||
	Vector4 ToVector4();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PackedVector Generic interface
 | 
			
		||||
// http://msdn.microsoft.com/en-us/library/bb197661.aspx
 | 
			
		||||
public interface IPackedVector<TPacked> : IPackedVector
 | 
			
		||||
{
 | 
			
		||||
	TPacked PackedValue
 | 
			
		||||
	{
 | 
			
		||||
		get;
 | 
			
		||||
		set;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										141
									
								
								Nerfed.Runtime/Graphics/PackedVector/NormalizedByte2.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								Nerfed.Runtime/Graphics/PackedVector/NormalizedByte2.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,141 @@
 | 
			
		||||
#region License
 | 
			
		||||
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
#region Using Statements
 | 
			
		||||
using System;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
public struct NormalizedByte2 : IPackedVector<ushort>, IEquatable<NormalizedByte2>
 | 
			
		||||
{
 | 
			
		||||
	#region Public Properties
 | 
			
		||||
 | 
			
		||||
	public ushort PackedValue
 | 
			
		||||
	{
 | 
			
		||||
		get
 | 
			
		||||
		{
 | 
			
		||||
			return packedValue;
 | 
			
		||||
		}
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
			packedValue = value;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Variables
 | 
			
		||||
 | 
			
		||||
	private ushort packedValue;
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Constructors
 | 
			
		||||
 | 
			
		||||
	public NormalizedByte2(Vector2 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public NormalizedByte2(float x, float y)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(x, y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Methods
 | 
			
		||||
 | 
			
		||||
	public Vector2 ToVector2()
 | 
			
		||||
	{
 | 
			
		||||
		return new Vector2(
 | 
			
		||||
			((sbyte) (packedValue & 0xFF)) / 127.0f,
 | 
			
		||||
			((sbyte) ((packedValue >> 8) & 0xFF)) / 127.0f
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region IPackedVector Methods
 | 
			
		||||
 | 
			
		||||
	void IPackedVector.PackFromVector4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Vector4 IPackedVector.ToVector4()
 | 
			
		||||
	{
 | 
			
		||||
		return new Vector4(ToVector2(), 0.0f, 1.0f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Static Operators and Override Methods
 | 
			
		||||
 | 
			
		||||
	public static bool operator !=(NormalizedByte2 a, NormalizedByte2 b)
 | 
			
		||||
	{
 | 
			
		||||
		return a.packedValue != b.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator ==(NormalizedByte2 a, NormalizedByte2 b)
 | 
			
		||||
	{
 | 
			
		||||
		return a.packedValue == b.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override bool Equals(object obj)
 | 
			
		||||
	{
 | 
			
		||||
		return (obj is NormalizedByte2) && Equals((NormalizedByte2) obj);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public bool Equals(NormalizedByte2 other)
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue == other.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override int GetHashCode()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.GetHashCode();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override string ToString()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.ToString("X");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Static Pack Method
 | 
			
		||||
 | 
			
		||||
	private static ushort Pack(float x, float y)
 | 
			
		||||
	{
 | 
			
		||||
		int byte2 = (
 | 
			
		||||
			((ushort)
 | 
			
		||||
				System.Math.Round(Math.Clamp(x, -1.0f, 1.0f) * 127.0f)
 | 
			
		||||
			)
 | 
			
		||||
		) & 0x00FF;
 | 
			
		||||
		int byte1 = (
 | 
			
		||||
			((ushort)
 | 
			
		||||
				System.Math.Round(Math.Clamp(y, -1.0f, 1.0f) * 127.0f)
 | 
			
		||||
			) << 8
 | 
			
		||||
		) & 0xFF00;
 | 
			
		||||
 | 
			
		||||
		return (ushort) (byte2 | byte1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										146
									
								
								Nerfed.Runtime/Graphics/PackedVector/NormalizedByte4.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								Nerfed.Runtime/Graphics/PackedVector/NormalizedByte4.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,146 @@
 | 
			
		||||
#region License
 | 
			
		||||
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
#region Using Statements
 | 
			
		||||
using System;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
public struct NormalizedByte4 : IPackedVector<uint>, IEquatable<NormalizedByte4>
 | 
			
		||||
{
 | 
			
		||||
	#region Public Properties
 | 
			
		||||
 | 
			
		||||
	public uint PackedValue
 | 
			
		||||
	{
 | 
			
		||||
		get
 | 
			
		||||
		{
 | 
			
		||||
			return packedValue;
 | 
			
		||||
		}
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
			packedValue = value;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Variables
 | 
			
		||||
 | 
			
		||||
	private uint packedValue;
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Constructors
 | 
			
		||||
 | 
			
		||||
	public NormalizedByte4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public NormalizedByte4(float x, float y, float z, float w)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(x, y, z, w);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Methods
 | 
			
		||||
 | 
			
		||||
	public Vector4 ToVector4()
 | 
			
		||||
	{
 | 
			
		||||
		return new Vector4(
 | 
			
		||||
			((sbyte) (packedValue & 0xFF)) / 127.0f,
 | 
			
		||||
			((sbyte) ((packedValue >> 8) & 0xFF)) / 127.0f,
 | 
			
		||||
			((sbyte) ((packedValue >> 16) & 0xFF)) / 127.0f,
 | 
			
		||||
			((sbyte) ((packedValue >> 24) & 0xFF)) / 127.0f
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region IPackedVector Methods
 | 
			
		||||
 | 
			
		||||
	void IPackedVector.PackFromVector4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Static Operators and Override Methods
 | 
			
		||||
 | 
			
		||||
	public static bool operator !=(NormalizedByte4 a, NormalizedByte4 b)
 | 
			
		||||
	{
 | 
			
		||||
		return a.packedValue != b.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator ==(NormalizedByte4 a, NormalizedByte4 b)
 | 
			
		||||
	{
 | 
			
		||||
		return a.packedValue == b.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override bool Equals(object obj)
 | 
			
		||||
	{
 | 
			
		||||
		return (obj is NormalizedByte4) && Equals((NormalizedByte4) obj);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public bool Equals(NormalizedByte4 other)
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue == other.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override int GetHashCode()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.GetHashCode();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override string ToString()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.ToString("X");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Static Pack Method
 | 
			
		||||
 | 
			
		||||
	private static uint Pack(float x, float y, float z, float w)
 | 
			
		||||
	{
 | 
			
		||||
		uint byte4 = (
 | 
			
		||||
			(uint) System.Math.Round(Math.Clamp(x, -1.0f, 1.0f) * 127.0f)
 | 
			
		||||
		) & 0x000000FF;
 | 
			
		||||
		uint byte3 = (
 | 
			
		||||
			(
 | 
			
		||||
				(uint) System.Math.Round(Math.Clamp(y, -1.0f, 1.0f) * 127.0f)
 | 
			
		||||
			) << 8
 | 
			
		||||
		) & 0x0000FF00;
 | 
			
		||||
		uint byte2 = (
 | 
			
		||||
			(
 | 
			
		||||
				(uint) System.Math.Round(Math.Clamp(z, -1.0f, 1.0f) * 127.0f)
 | 
			
		||||
			) << 16
 | 
			
		||||
		) & 0x00FF0000;
 | 
			
		||||
		uint byte1 = (
 | 
			
		||||
			(
 | 
			
		||||
				(uint) System.Math.Round(Math.Clamp(w, -1.0f, 1.0f) * 127.0f)
 | 
			
		||||
			) << 24
 | 
			
		||||
		) & 0xFF000000;
 | 
			
		||||
 | 
			
		||||
		return byte4 | byte3 | byte2 | byte1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										150
									
								
								Nerfed.Runtime/Graphics/PackedVector/NormalizedShort2.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								Nerfed.Runtime/Graphics/PackedVector/NormalizedShort2.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,150 @@
 | 
			
		||||
#region License
 | 
			
		||||
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
#region Using Statements
 | 
			
		||||
using System;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
public struct NormalizedShort2 : IPackedVector<uint>, IEquatable<NormalizedShort2>
 | 
			
		||||
{
 | 
			
		||||
	#region Public Properties
 | 
			
		||||
 | 
			
		||||
	public uint PackedValue
 | 
			
		||||
	{
 | 
			
		||||
		get
 | 
			
		||||
		{
 | 
			
		||||
			return packedValue;
 | 
			
		||||
		}
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
			packedValue = value;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Variables
 | 
			
		||||
 | 
			
		||||
	private uint packedValue;
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Constructors
 | 
			
		||||
 | 
			
		||||
	public NormalizedShort2(Vector2 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public NormalizedShort2(float x, float y)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(x, y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Methods
 | 
			
		||||
 | 
			
		||||
	public Vector2 ToVector2()
 | 
			
		||||
	{
 | 
			
		||||
		const float maxVal = 0x7FFF;
 | 
			
		||||
 | 
			
		||||
		return new Vector2(
 | 
			
		||||
			(short) (packedValue & 0xFFFF) / maxVal,
 | 
			
		||||
			(short) (packedValue >> 0x10) / maxVal
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region IPackedVector Methods
 | 
			
		||||
 | 
			
		||||
	void IPackedVector.PackFromVector4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Vector4 IPackedVector.ToVector4()
 | 
			
		||||
	{
 | 
			
		||||
		return new Vector4(ToVector2(), 0.0f, 1.0f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Static Operators and Override Methods
 | 
			
		||||
 | 
			
		||||
	public static bool operator !=(NormalizedShort2 a, NormalizedShort2 b)
 | 
			
		||||
	{
 | 
			
		||||
		return !a.Equals(b);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator ==(NormalizedShort2 a, NormalizedShort2 b)
 | 
			
		||||
	{
 | 
			
		||||
		return a.Equals(b);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override bool Equals(object obj)
 | 
			
		||||
	{
 | 
			
		||||
		return (obj is NormalizedShort2) && Equals((NormalizedShort2) obj);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public bool Equals(NormalizedShort2 other)
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.Equals(other.packedValue);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override int GetHashCode()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.GetHashCode();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override string ToString()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.ToString("X");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Static Pack Method
 | 
			
		||||
 | 
			
		||||
	private static uint Pack(float x, float y)
 | 
			
		||||
	{
 | 
			
		||||
		const float max = 0x7FFF;
 | 
			
		||||
		const float min = -max;
 | 
			
		||||
 | 
			
		||||
		uint word2 = (uint) (
 | 
			
		||||
			(int) Math.Clamp(
 | 
			
		||||
				(float) System.Math.Round(x * max),
 | 
			
		||||
				min,
 | 
			
		||||
				max
 | 
			
		||||
			) & 0xFFFF
 | 
			
		||||
		);
 | 
			
		||||
		uint word1 = (uint) ((
 | 
			
		||||
			(int) Math.Clamp(
 | 
			
		||||
				(float) System.Math.Round(y * max),
 | 
			
		||||
				min,
 | 
			
		||||
				max
 | 
			
		||||
			) & 0xFFFF
 | 
			
		||||
		) << 0x10);
 | 
			
		||||
 | 
			
		||||
		return (word2 | word1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										161
									
								
								Nerfed.Runtime/Graphics/PackedVector/NormalizedShort4.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								Nerfed.Runtime/Graphics/PackedVector/NormalizedShort4.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,161 @@
 | 
			
		||||
#region License
 | 
			
		||||
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
#region Using Statements
 | 
			
		||||
using System;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
public struct NormalizedShort4 : IPackedVector<ulong>, IEquatable<NormalizedShort4>
 | 
			
		||||
{
 | 
			
		||||
	#region Public Properties
 | 
			
		||||
 | 
			
		||||
	public ulong PackedValue
 | 
			
		||||
	{
 | 
			
		||||
		get
 | 
			
		||||
		{
 | 
			
		||||
			return packedValue;
 | 
			
		||||
		}
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
			packedValue = value;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Variables
 | 
			
		||||
 | 
			
		||||
	private ulong packedValue;
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Constructors
 | 
			
		||||
 | 
			
		||||
	public NormalizedShort4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public NormalizedShort4(float x, float y, float z, float w)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(x, y, z, w);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Methods
 | 
			
		||||
 | 
			
		||||
	public Vector4 ToVector4()
 | 
			
		||||
	{
 | 
			
		||||
		const float maxVal = 0x7FFF;
 | 
			
		||||
 | 
			
		||||
		return new Vector4(
 | 
			
		||||
			((short) (packedValue & 0xFFFF)) / maxVal,
 | 
			
		||||
			((short) ((packedValue >> 0x10) & 0xFFFF)) / maxVal,
 | 
			
		||||
			((short) ((packedValue >> 0x20) & 0xFFFF)) / maxVal,
 | 
			
		||||
			((short) ((packedValue >> 0x30) & 0xFFFF)) / maxVal
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region IPackedVector Methods
 | 
			
		||||
 | 
			
		||||
	void IPackedVector.PackFromVector4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Static Operators and Override Methods
 | 
			
		||||
 | 
			
		||||
	public static bool operator !=(NormalizedShort4 a, NormalizedShort4 b)
 | 
			
		||||
	{
 | 
			
		||||
		return !a.Equals(b);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator ==(NormalizedShort4 a, NormalizedShort4 b)
 | 
			
		||||
	{
 | 
			
		||||
		return a.Equals(b);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override bool Equals(object obj)
 | 
			
		||||
	{
 | 
			
		||||
		return (obj is NormalizedShort4) && Equals((NormalizedShort4) obj);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public bool Equals(NormalizedShort4 other)
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.Equals(other.packedValue);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override int GetHashCode()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.GetHashCode();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override string ToString()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.ToString("X");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Static Pack Method
 | 
			
		||||
 | 
			
		||||
	private static ulong Pack(float x, float y, float z, float w)
 | 
			
		||||
	{
 | 
			
		||||
		const float max = 0x7FFF;
 | 
			
		||||
		const float min = -max;
 | 
			
		||||
 | 
			
		||||
		ulong word4 = (
 | 
			
		||||
			(ulong) Math.Clamp(
 | 
			
		||||
				(float) System.Math.Round(x * max),
 | 
			
		||||
				min,
 | 
			
		||||
				max
 | 
			
		||||
			) & 0xFFFF
 | 
			
		||||
		);
 | 
			
		||||
		ulong word3 = (
 | 
			
		||||
			(ulong) Math.Clamp(
 | 
			
		||||
				(float) System.Math.Round(y * max),
 | 
			
		||||
				min,
 | 
			
		||||
				max
 | 
			
		||||
			) & 0xFFFF
 | 
			
		||||
		) << 0x10;
 | 
			
		||||
		ulong word2 = (
 | 
			
		||||
			(ulong) Math.Clamp(
 | 
			
		||||
				(float) System.Math.Round(z * max),
 | 
			
		||||
				min,
 | 
			
		||||
				max
 | 
			
		||||
			) & 0xFFFF
 | 
			
		||||
		) << 0x20;
 | 
			
		||||
		ulong word1 = (
 | 
			
		||||
			(ulong) Math.Clamp(
 | 
			
		||||
				(float) System.Math.Round(w * max),
 | 
			
		||||
				min,
 | 
			
		||||
				max
 | 
			
		||||
			) & 0xFFFF
 | 
			
		||||
		) << 0x30;
 | 
			
		||||
 | 
			
		||||
		return (word4 | word3 | word2 | word1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										182
									
								
								Nerfed.Runtime/Graphics/PackedVector/Rg32.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								Nerfed.Runtime/Graphics/PackedVector/Rg32.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,182 @@
 | 
			
		||||
#region License
 | 
			
		||||
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
#region Using Statements
 | 
			
		||||
using System;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Packed vector type containing unsigned normalized values ranging from 0 to 1.
 | 
			
		||||
/// The x and z components use 5 bits, and the y component uses 6 bits.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public struct Rg32 : IPackedVector<uint>, IEquatable<Rg32>, IPackedVector
 | 
			
		||||
{
 | 
			
		||||
	#region Public Properties
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets and sets the packed value.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public uint PackedValue
 | 
			
		||||
	{
 | 
			
		||||
		get
 | 
			
		||||
		{
 | 
			
		||||
			return packedValue;
 | 
			
		||||
		}
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
			packedValue = value;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Variables
 | 
			
		||||
 | 
			
		||||
	private uint packedValue;
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Constructors
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a new instance of Rg32.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="x">The x component</param>
 | 
			
		||||
	/// <param name="y">The y component</param>
 | 
			
		||||
	public Rg32(float x, float y)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(x, y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a new instance of Rg32.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">
 | 
			
		||||
	/// Vector containing the components for the packed vector.
 | 
			
		||||
	/// </param>
 | 
			
		||||
	public Rg32(Vector2 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets the packed vector in Vector2 format.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The packed vector in Vector2 format</returns>
 | 
			
		||||
	public Vector2 ToVector2()
 | 
			
		||||
	{
 | 
			
		||||
		return new Vector2(
 | 
			
		||||
			(packedValue & 0xFFFF) / 65535.0f,
 | 
			
		||||
			(packedValue >> 16) / 65535.0f
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region IPackedVector Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Sets the packed vector from a Vector4.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">Vector containing the components.</param>
 | 
			
		||||
	void IPackedVector.PackFromVector4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets the packed vector in Vector4 format.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The packed vector in Vector4 format</returns>
 | 
			
		||||
	Vector4 IPackedVector.ToVector4()
 | 
			
		||||
	{
 | 
			
		||||
		return new Vector4(ToVector2(), 0.0f, 1.0f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Static Operators and Override Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares an object with the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="obj">The object to compare.</param>
 | 
			
		||||
	/// <returns>True if the object is equal to the packed vector.</returns>
 | 
			
		||||
	public override bool Equals(object obj)
 | 
			
		||||
	{
 | 
			
		||||
		return (obj is Rg32) && Equals((Rg32) obj);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares another Rg32 packed vector with the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="other">The Rg32 packed vector to compare.</param>
 | 
			
		||||
	/// <returns>True if the packed vectors are equal.</returns>
 | 
			
		||||
	public bool Equals(Rg32 other)
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue == other.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets a string representation of the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>A string representation of the packed vector.</returns>
 | 
			
		||||
	public override string ToString()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.ToString("X");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets a hash code of the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The hash code for the packed vector.</returns>
 | 
			
		||||
	public override int GetHashCode()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.GetHashCode();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator ==(Rg32 lhs, Rg32 rhs)
 | 
			
		||||
	{
 | 
			
		||||
		return lhs.packedValue == rhs.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator !=(Rg32 lhs, Rg32 rhs)
 | 
			
		||||
	{
 | 
			
		||||
		return lhs.packedValue != rhs.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Static Pack Method
 | 
			
		||||
 | 
			
		||||
	private static uint Pack(float x, float y)
 | 
			
		||||
	{
 | 
			
		||||
		return (uint) (
 | 
			
		||||
			((uint) System.Math.Round(Math.Clamp(x, 0, 1) * 65535.0f)) |
 | 
			
		||||
			(((uint) System.Math.Round(Math.Clamp(y, 0, 1) * 65535.0f)) << 16)
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										178
									
								
								Nerfed.Runtime/Graphics/PackedVector/Rgba1010102.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								Nerfed.Runtime/Graphics/PackedVector/Rgba1010102.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,178 @@
 | 
			
		||||
#region License
 | 
			
		||||
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
#region Using Statements
 | 
			
		||||
using System;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Packed vector type containing unsigned normalized values ranging from 0 to 1.
 | 
			
		||||
/// The x and z components use 5 bits, and the y component uses 6 bits.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public struct Rgba1010102 : IPackedVector<uint>, IEquatable<Rgba1010102>, IPackedVector
 | 
			
		||||
{
 | 
			
		||||
	#region Public Properties
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets and sets the packed value.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public uint PackedValue
 | 
			
		||||
	{
 | 
			
		||||
		get
 | 
			
		||||
		{
 | 
			
		||||
				return packedValue;
 | 
			
		||||
			}
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
				packedValue = value;
 | 
			
		||||
			}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Variables
 | 
			
		||||
 | 
			
		||||
	private uint packedValue;
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Constructors
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a new instance of Rgba1010102.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="x">The x component</param>
 | 
			
		||||
	/// <param name="y">The y component</param>
 | 
			
		||||
	/// <param name="z">The z component</param>
 | 
			
		||||
	/// <param name="w">The w component</param>
 | 
			
		||||
	public Rgba1010102(float x, float y, float z, float w)
 | 
			
		||||
	{
 | 
			
		||||
			packedValue = Pack(x, y, z, w);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a new instance of Rgba1010102.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">
 | 
			
		||||
	/// Vector containing the components for the packed vector.
 | 
			
		||||
	/// </param>
 | 
			
		||||
	public Rgba1010102(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
			packedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets the packed vector in Vector4 format.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The packed vector in Vector4 format</returns>
 | 
			
		||||
	public Vector4 ToVector4()
 | 
			
		||||
	{
 | 
			
		||||
			return new Vector4(
 | 
			
		||||
				(packedValue & 0x03FF) / 1023.0f,
 | 
			
		||||
				((packedValue >> 10) & 0x03FF) / 1023.0f,
 | 
			
		||||
				((packedValue >> 20) & 0x03FF) / 1023.0f,
 | 
			
		||||
				(packedValue >> 30) / 3.0f
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region IPackedVector Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Sets the packed vector from a Vector4.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">Vector containing the components.</param>
 | 
			
		||||
	void IPackedVector.PackFromVector4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
			packedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Static Operators and Override Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares an object with the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="obj">The object to compare.</param>
 | 
			
		||||
	/// <returns>True if the object is equal to the packed vector.</returns>
 | 
			
		||||
	public override bool Equals(object obj)
 | 
			
		||||
	{
 | 
			
		||||
			return (obj is Rgba1010102) && Equals((Rgba1010102) obj);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares another Rgba1010102 packed vector with the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="other">The Rgba1010102 packed vector to compare.</param>
 | 
			
		||||
	/// <returns>True if the packed vectors are equal.</returns>
 | 
			
		||||
	public bool Equals(Rgba1010102 other)
 | 
			
		||||
	{
 | 
			
		||||
			return packedValue == other.packedValue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets a string representation of the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>A string representation of the packed vector.</returns>
 | 
			
		||||
	public override string ToString()
 | 
			
		||||
	{
 | 
			
		||||
			return packedValue.ToString("X");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets a hash code of the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The hash code for the packed vector.</returns>
 | 
			
		||||
	public override int GetHashCode()
 | 
			
		||||
	{
 | 
			
		||||
			return packedValue.GetHashCode();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	public static bool operator ==(Rgba1010102 lhs, Rgba1010102 rhs)
 | 
			
		||||
	{
 | 
			
		||||
			return lhs.packedValue == rhs.packedValue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	public static bool operator !=(Rgba1010102 lhs, Rgba1010102 rhs)
 | 
			
		||||
	{
 | 
			
		||||
			return lhs.packedValue != rhs.packedValue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Static Pack Method
 | 
			
		||||
 | 
			
		||||
	private static uint Pack(float x, float y, float z, float w)
 | 
			
		||||
	{
 | 
			
		||||
			return (uint) (
 | 
			
		||||
				((uint) System.Math.Round(Math.Clamp(x, 0, 1) * 1023.0f)) |
 | 
			
		||||
				((uint) System.Math.Round(Math.Clamp(y, 0, 1) * 1023.0f) << 10) |
 | 
			
		||||
				((uint) System.Math.Round(Math.Clamp(z, 0, 1) * 1023.0f) << 20) |
 | 
			
		||||
				((uint) System.Math.Round(Math.Clamp(w, 0, 1) * 3.0f) << 30)
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										178
									
								
								Nerfed.Runtime/Graphics/PackedVector/Rgba64.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								Nerfed.Runtime/Graphics/PackedVector/Rgba64.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,178 @@
 | 
			
		||||
#region License
 | 
			
		||||
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
#region Using Statements
 | 
			
		||||
using System;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Packed vector type containing unsigned normalized values ranging from 0 to 1.
 | 
			
		||||
/// The x and z components use 5 bits, and the y component uses 6 bits.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public struct Rgba64 : IPackedVector<ulong>, IEquatable<Rgba64>, IPackedVector
 | 
			
		||||
{
 | 
			
		||||
	#region Public Properties
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets and sets the packed value.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public ulong PackedValue
 | 
			
		||||
	{
 | 
			
		||||
		get
 | 
			
		||||
		{
 | 
			
		||||
			return packedValue;
 | 
			
		||||
		}
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
			packedValue = value;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Variables
 | 
			
		||||
 | 
			
		||||
	private ulong packedValue;
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Constructors
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a new instance of Rgba64.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="x">The x component</param>
 | 
			
		||||
	/// <param name="y">The y component</param>
 | 
			
		||||
	/// <param name="z">The z component</param>
 | 
			
		||||
	/// <param name="w">The w component</param>
 | 
			
		||||
	public Rgba64(float x, float y, float z, float w)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(x, y, z, w);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a new instance of Rgba64.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">
 | 
			
		||||
	/// Vector containing the components for the packed vector.
 | 
			
		||||
	/// </param>
 | 
			
		||||
	public Rgba64(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets the packed vector in Vector4 format.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The packed vector in Vector4 format</returns>
 | 
			
		||||
	public Vector4 ToVector4()
 | 
			
		||||
	{
 | 
			
		||||
		return new Vector4(
 | 
			
		||||
			(packedValue & 0xFFFF) / 65535.0f,
 | 
			
		||||
			((packedValue >> 16) & 0xFFFF) / 65535.0f,
 | 
			
		||||
			((packedValue >> 32) & 0xFFFF) / 65535.0f,
 | 
			
		||||
			(packedValue >> 48) / 65535.0f
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region IPackedVector Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Sets the packed vector from a Vector4.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">Vector containing the components.</param>
 | 
			
		||||
	void IPackedVector.PackFromVector4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Static Operators and Override Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares an object with the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="obj">The object to compare.</param>
 | 
			
		||||
	/// <returns>True if the object is equal to the packed vector.</returns>
 | 
			
		||||
	public override bool Equals(object obj)
 | 
			
		||||
	{
 | 
			
		||||
		return (obj is Rgba64) && Equals((Rgba64) obj);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares another Rgba64 packed vector with the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="other">The Rgba64 packed vector to compare.</param>
 | 
			
		||||
	/// <returns>True if the packed vectors are equal.</returns>
 | 
			
		||||
	public bool Equals(Rgba64 other)
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue == other.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets a string representation of the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>A string representation of the packed vector.</returns>
 | 
			
		||||
	public override string ToString()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.ToString("X");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets a hash code of the packed vector.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The hash code for the packed vector.</returns>
 | 
			
		||||
	public override int GetHashCode()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.GetHashCode();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator ==(Rgba64 lhs, Rgba64 rhs)
 | 
			
		||||
	{
 | 
			
		||||
		return lhs.packedValue == rhs.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator !=(Rgba64 lhs, Rgba64 rhs)
 | 
			
		||||
	{
 | 
			
		||||
		return lhs.packedValue != rhs.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Static Pack Method
 | 
			
		||||
 | 
			
		||||
	private static ulong Pack(float x, float y, float z, float w)
 | 
			
		||||
	{
 | 
			
		||||
		return (ulong) (
 | 
			
		||||
			((ulong) System.Math.Round(Math.Clamp(x, 0, 1) * 65535.0f)) |
 | 
			
		||||
			(((ulong) System.Math.Round(Math.Clamp(y, 0, 1) * 65535.0f)) << 16) |
 | 
			
		||||
			(((ulong) System.Math.Round(Math.Clamp(z, 0, 1) * 65535.0f)) << 32) |
 | 
			
		||||
			(((ulong) System.Math.Round(Math.Clamp(w, 0, 1) * 65535.0f)) << 48)
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										134
									
								
								Nerfed.Runtime/Graphics/PackedVector/Short2.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								Nerfed.Runtime/Graphics/PackedVector/Short2.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,134 @@
 | 
			
		||||
#region License
 | 
			
		||||
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
#region Using Statements
 | 
			
		||||
using System;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
public struct Short2 : IPackedVector<uint>, IEquatable<Short2>
 | 
			
		||||
{
 | 
			
		||||
	#region Public Properties
 | 
			
		||||
 | 
			
		||||
	public uint PackedValue
 | 
			
		||||
	{
 | 
			
		||||
		get
 | 
			
		||||
		{
 | 
			
		||||
			return packedValue;
 | 
			
		||||
		}
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
			packedValue = value;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Variables
 | 
			
		||||
 | 
			
		||||
	private uint packedValue;
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Constructors
 | 
			
		||||
 | 
			
		||||
	public Short2(Vector2 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Short2(float x, float y)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(x, y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Methods
 | 
			
		||||
 | 
			
		||||
	public Vector2 ToVector2()
 | 
			
		||||
	{
 | 
			
		||||
		return new Vector2(
 | 
			
		||||
			(short) (packedValue & 0xFFFF),
 | 
			
		||||
			(short) (packedValue >> 16)
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region IPackedVector Methods
 | 
			
		||||
 | 
			
		||||
	void IPackedVector.PackFromVector4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
		packedValue = Pack(vector.X, vector.Y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Vector4 IPackedVector.ToVector4()
 | 
			
		||||
	{
 | 
			
		||||
		return new Vector4(ToVector2(), 0.0f, 1.0f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Static Operators and Override Methods
 | 
			
		||||
 | 
			
		||||
	public static bool operator !=(Short2 a, Short2 b)
 | 
			
		||||
	{
 | 
			
		||||
		return a.packedValue != b.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static bool operator ==(Short2 a, Short2 b)
 | 
			
		||||
	{
 | 
			
		||||
		return a.packedValue == b.packedValue;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override bool Equals(object obj)
 | 
			
		||||
	{
 | 
			
		||||
		return (obj is Short2) && Equals((Short2) obj);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public bool Equals(Short2 other)
 | 
			
		||||
	{
 | 
			
		||||
		return this == other;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override int GetHashCode()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.GetHashCode();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override string ToString()
 | 
			
		||||
	{
 | 
			
		||||
		return packedValue.ToString("X");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Static Pack Method
 | 
			
		||||
 | 
			
		||||
	private static uint Pack(float x, float y)
 | 
			
		||||
	{
 | 
			
		||||
		return (uint) (
 | 
			
		||||
			((int) System.Math.Round(Math.Clamp(x, -32768, 32767)) & 0x0000FFFF) |
 | 
			
		||||
			(((int) System.Math.Round(Math.Clamp(y, -32768, 32767))) << 16)
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										204
									
								
								Nerfed.Runtime/Graphics/PackedVector/Short4.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										204
									
								
								Nerfed.Runtime/Graphics/PackedVector/Short4.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,204 @@
 | 
			
		||||
#region License
 | 
			
		||||
 | 
			
		||||
/* MoonWorks - Game Development Framework
 | 
			
		||||
 * Copyright 2021 Evan Hemsley
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Derived from code by Ethan Lee (Copyright 2009-2021).
 | 
			
		||||
 * Released under the Microsoft Public License.
 | 
			
		||||
 * See fna.LICENSE for details.
 | 
			
		||||
 | 
			
		||||
 * Derived from code by the Mono.Xna Team (Copyright 2006).
 | 
			
		||||
 * Released under the MIT License. See monoxna.LICENSE for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
#region Using Statements
 | 
			
		||||
using System;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics.PackedVector;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Packed vector type containing four 16-bit signed integer values.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public struct Short4 : IPackedVector<ulong>, IEquatable<Short4>
 | 
			
		||||
{
 | 
			
		||||
	#region Public Properties
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Directly gets or sets the packed representation of the value.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <value>The packed representation of the value.</value>
 | 
			
		||||
	public ulong PackedValue
 | 
			
		||||
	{
 | 
			
		||||
		get
 | 
			
		||||
		{
 | 
			
		||||
				return packedValue;
 | 
			
		||||
			}
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
				packedValue = value;
 | 
			
		||||
			}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Variables
 | 
			
		||||
 | 
			
		||||
	private ulong packedValue;
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Constructors
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Initializes a new instance of the Short4 class.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">
 | 
			
		||||
	/// A vector containing the initial values for the components of the Short4 structure.
 | 
			
		||||
	/// </param>
 | 
			
		||||
	public Short4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
			packedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Initializes a new instance of the Short4 class.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="x">Initial value for the x component.</param>
 | 
			
		||||
	/// <param name="y">Initial value for the y component.</param>
 | 
			
		||||
	/// <param name="z">Initial value for the z component.</param>
 | 
			
		||||
	/// <param name="w">Initial value for the w component.</param>
 | 
			
		||||
	public Short4(float x, float y, float z, float w)
 | 
			
		||||
	{
 | 
			
		||||
			packedValue = Pack(x, y, z, w);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Expands the packed representation into a Vector4.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>The expanded vector.</returns>
 | 
			
		||||
	public Vector4 ToVector4()
 | 
			
		||||
	{
 | 
			
		||||
			return new Vector4(
 | 
			
		||||
				(short) (packedValue & 0xFFFF),
 | 
			
		||||
				(short) ((packedValue >> 16) & 0xFFFF),
 | 
			
		||||
				(short) ((packedValue >> 32) & 0xFFFF),
 | 
			
		||||
				(short) (packedValue >> 48)
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region IPackedVector Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Sets the packed representation from a Vector4.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">The vector to create the packed representation from.</param>
 | 
			
		||||
	void IPackedVector.PackFromVector4(Vector4 vector)
 | 
			
		||||
	{
 | 
			
		||||
			packedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Public Static Operators and Override Methods
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares the current instance of a class to another instance to determine
 | 
			
		||||
	/// whether they are different.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="a">The object to the left of the equality operator.</param>
 | 
			
		||||
	/// <param name="b">The object to the right of the equality operator.</param>
 | 
			
		||||
	/// <returns>True if the objects are different; false otherwise.</returns>
 | 
			
		||||
	public static bool operator !=(Short4 a, Short4 b)
 | 
			
		||||
	{
 | 
			
		||||
			return a.PackedValue != b.PackedValue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Compares the current instance of a class to another instance to determine
 | 
			
		||||
	/// whether they are the same.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="a">The object to the left of the equality operator.</param>
 | 
			
		||||
	/// <param name="b">The object to the right of the equality operator.</param>
 | 
			
		||||
	/// <returns>True if the objects are the same; false otherwise.</returns>
 | 
			
		||||
	public static bool operator ==(Short4 a, Short4 b)
 | 
			
		||||
	{
 | 
			
		||||
			return a.PackedValue == b.PackedValue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Returns a value that indicates whether the current instance is equal to a
 | 
			
		||||
	/// specified object.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="obj">The object with which to make the comparison.</param>
 | 
			
		||||
	/// <returns>
 | 
			
		||||
	/// True if the current instance is equal to the specified object; false otherwise.
 | 
			
		||||
	/// </returns>
 | 
			
		||||
	public override bool Equals(object obj)
 | 
			
		||||
	{
 | 
			
		||||
			return (obj is Short4) && Equals((Short4) obj);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Returns a value that indicates whether the current instance is equal to a
 | 
			
		||||
	/// specified object.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="other">The object with which to make the comparison.</param>
 | 
			
		||||
	/// <returns>
 | 
			
		||||
	/// True if the current instance is equal to the specified object; false otherwise.
 | 
			
		||||
	/// </returns>
 | 
			
		||||
	public bool Equals(Short4 other)
 | 
			
		||||
	{
 | 
			
		||||
			return this == other;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets the hash code for the current instance.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>Hash code for the instance.</returns>
 | 
			
		||||
	public override int GetHashCode()
 | 
			
		||||
	{
 | 
			
		||||
			return packedValue.GetHashCode();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Returns a string representation of the current instance.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>String that represents the object.</returns>
 | 
			
		||||
	public override string ToString()
 | 
			
		||||
	{
 | 
			
		||||
			return packedValue.ToString("X");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
 | 
			
		||||
	#region Private Static Pack Method
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Packs a vector into a ulong.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="vector">The vector containing the values to pack.</param>
 | 
			
		||||
	/// <returns>The ulong containing the packed values.</returns>
 | 
			
		||||
	static ulong Pack(float x, float y, float z, float w)
 | 
			
		||||
	{
 | 
			
		||||
			return (ulong) (
 | 
			
		||||
				((long) System.Math.Round(Math.Clamp(x, -32768, 32767)) & 0xFFFF) |
 | 
			
		||||
				(((long) System.Math.Round(Math.Clamp(y, -32768, 32767)) << 16) & 0xFFFF0000) |
 | 
			
		||||
				(((long) System.Math.Round(Math.Clamp(z, -32768, 32767)) << 32) & 0xFFFF00000000) |
 | 
			
		||||
				((long) System.Math.Round(Math.Clamp(w, -32768, 32767)) << 48)
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	#endregion
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								Nerfed.Runtime/Graphics/RefreshResource.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								Nerfed.Runtime/Graphics/RefreshResource.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
public abstract class RefreshResource : GraphicsResource
 | 
			
		||||
{
 | 
			
		||||
	public IntPtr Handle { get => handle; internal set => handle = value; }
 | 
			
		||||
	private IntPtr handle;
 | 
			
		||||
 | 
			
		||||
	protected abstract Action<IntPtr, IntPtr> ReleaseFunction { get; }
 | 
			
		||||
 | 
			
		||||
	protected RefreshResource(GraphicsDevice device) : base(device)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected override void Dispose(bool disposing)
 | 
			
		||||
	{
 | 
			
		||||
		if (!IsDisposed)
 | 
			
		||||
		{
 | 
			
		||||
			// Atomically call release function in case this is called from the finalizer thread
 | 
			
		||||
			IntPtr toDispose = Interlocked.Exchange(ref handle, IntPtr.Zero);
 | 
			
		||||
			if (toDispose != IntPtr.Zero)
 | 
			
		||||
			{
 | 
			
		||||
				ReleaseFunction(Device.Handle, toDispose);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		base.Dispose(disposing);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1723
									
								
								Nerfed.Runtime/Graphics/RefreshTypes.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1723
									
								
								Nerfed.Runtime/Graphics/RefreshTypes.cs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										495
									
								
								Nerfed.Runtime/Graphics/RenderPass.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										495
									
								
								Nerfed.Runtime/Graphics/RenderPass.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,495 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
using RefreshCS;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Render passes are begun in command buffers and are used to apply render state and issue draw calls.
 | 
			
		||||
/// Render passes are pooled and should not be referenced after calling EndRenderPass.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public class RenderPass
 | 
			
		||||
{
 | 
			
		||||
    public nint Handle { get; private set; }
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
    internal uint colorAttachmentCount;
 | 
			
		||||
    internal SampleCount colorAttachmentSampleCount;
 | 
			
		||||
    internal TextureFormat colorFormatOne;
 | 
			
		||||
    internal TextureFormat colorFormatTwo;
 | 
			
		||||
    internal TextureFormat colorFormatThree;
 | 
			
		||||
    internal TextureFormat colorFormatFour;
 | 
			
		||||
    internal bool hasDepthStencilAttachment;
 | 
			
		||||
    internal SampleCount depthStencilAttachmentSampleCount;
 | 
			
		||||
    internal TextureFormat depthStencilFormat;
 | 
			
		||||
 | 
			
		||||
    GraphicsPipeline currentGraphicsPipeline;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    internal void SetHandle(nint handle)
 | 
			
		||||
    {
 | 
			
		||||
        Handle = handle;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Binds a graphics pipeline so that rendering work may be performed.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="graphicsPipeline">The graphics pipeline to bind.</param>
 | 
			
		||||
    public void BindGraphicsPipeline(GraphicsPipeline graphicsPipeline)
 | 
			
		||||
    {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        AssertRenderPassPipelineFormatMatch(graphicsPipeline);
 | 
			
		||||
 | 
			
		||||
        if (colorAttachmentCount > 0)
 | 
			
		||||
        {
 | 
			
		||||
            if (graphicsPipeline.SampleCount != colorAttachmentSampleCount)
 | 
			
		||||
            {
 | 
			
		||||
                throw new System.InvalidOperationException(
 | 
			
		||||
                    $"Sample count mismatch! Graphics pipeline sample count: {graphicsPipeline.SampleCount}, Color attachment sample count: {colorAttachmentSampleCount}"
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (hasDepthStencilAttachment)
 | 
			
		||||
        {
 | 
			
		||||
            if (graphicsPipeline.SampleCount != depthStencilAttachmentSampleCount)
 | 
			
		||||
            {
 | 
			
		||||
                throw new System.InvalidOperationException(
 | 
			
		||||
                    $"Sample count mismatch! Graphics pipeline sample count: {graphicsPipeline.SampleCount}, Depth stencil attachment sample count: {depthStencilAttachmentSampleCount}"
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        Refresh.Refresh_BindGraphicsPipeline(
 | 
			
		||||
            Handle,
 | 
			
		||||
            graphicsPipeline.Handle
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        currentGraphicsPipeline = graphicsPipeline;
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Sets the viewport.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public void SetViewport(in Viewport viewport)
 | 
			
		||||
    {
 | 
			
		||||
        Refresh.Refresh_SetViewport(
 | 
			
		||||
            Handle,
 | 
			
		||||
            viewport.ToRefresh()
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Sets the scissor area.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public void SetScissor(in Rect scissor)
 | 
			
		||||
    {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        if (scissor.X < 0 || scissor.Y < 0 || scissor.W <= 0 || scissor.H <= 0)
 | 
			
		||||
        {
 | 
			
		||||
            throw new System.ArgumentOutOfRangeException("Scissor position cannot be negative and dimensions must be positive!");
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        Refresh.Refresh_SetScissor(
 | 
			
		||||
            Handle,
 | 
			
		||||
            scissor.ToRefresh()
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Binds vertex buffers to be used by subsequent draw calls.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="bufferBinding">Buffer to bind and associated offset.</param>
 | 
			
		||||
    /// <param name="firstBinding">The index of the first vertex input binding whose state is updated by the command.</param>
 | 
			
		||||
    public unsafe void BindVertexBuffer(
 | 
			
		||||
        in BufferBinding bufferBinding,
 | 
			
		||||
        uint firstBinding = 0
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        AssertGraphicsPipelineBound();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        Refresh.BufferBinding refreshBufferBinding = bufferBinding.ToRefresh();
 | 
			
		||||
 | 
			
		||||
        Refresh.Refresh_BindVertexBuffers(
 | 
			
		||||
            Handle,
 | 
			
		||||
            firstBinding,
 | 
			
		||||
            &refreshBufferBinding,
 | 
			
		||||
            1
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Binds an index buffer to be used by subsequent draw calls.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="indexBuffer">The index buffer to bind.</param>
 | 
			
		||||
    /// <param name="indexElementSize">The size in bytes of the index buffer elements.</param>
 | 
			
		||||
    /// <param name="offset">The offset index for the buffer.</param>
 | 
			
		||||
    public void BindIndexBuffer(
 | 
			
		||||
        BufferBinding bufferBinding,
 | 
			
		||||
        IndexElementSize indexElementSize
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        AssertGraphicsPipelineBound();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        Refresh.Refresh_BindIndexBuffer(
 | 
			
		||||
            Handle,
 | 
			
		||||
            bufferBinding.ToRefresh(),
 | 
			
		||||
            (Refresh.IndexElementSize)indexElementSize
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Binds samplers to be used by the vertex shader.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="textureSamplerBindings">The texture-sampler to bind.</param>
 | 
			
		||||
    public unsafe void BindVertexSampler(
 | 
			
		||||
        in TextureSamplerBinding textureSamplerBinding,
 | 
			
		||||
        uint slot = 0
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        AssertGraphicsPipelineBound();
 | 
			
		||||
        AssertTextureSamplerBindingNonNull(textureSamplerBinding);
 | 
			
		||||
        AssertTextureHasSamplerFlag(textureSamplerBinding.Texture);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        Refresh.TextureSamplerBinding refreshTextureSamplerBinding = textureSamplerBinding.ToRefresh();
 | 
			
		||||
 | 
			
		||||
        Refresh.Refresh_BindVertexSamplers(
 | 
			
		||||
            Handle,
 | 
			
		||||
            slot,
 | 
			
		||||
            &refreshTextureSamplerBinding,
 | 
			
		||||
            1
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public unsafe void BindVertexStorageTexture(
 | 
			
		||||
        in TextureSlice textureSlice,
 | 
			
		||||
        uint slot = 0
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        AssertGraphicsPipelineBound();
 | 
			
		||||
        AssertTextureNonNull(textureSlice.Texture);
 | 
			
		||||
        AssertTextureHasGraphicsStorageFlag(textureSlice.Texture);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        Refresh.TextureSlice refreshTextureSlice = textureSlice.ToRefresh();
 | 
			
		||||
 | 
			
		||||
        Refresh.Refresh_BindVertexStorageTextures(
 | 
			
		||||
            Handle,
 | 
			
		||||
            slot,
 | 
			
		||||
            &refreshTextureSlice,
 | 
			
		||||
            1
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public unsafe void BindVertexStorageBuffer(
 | 
			
		||||
        Buffer buffer,
 | 
			
		||||
        uint slot = 0
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        AssertGraphicsPipelineBound();
 | 
			
		||||
        AssertBufferNonNull(buffer);
 | 
			
		||||
        AssertBufferHasGraphicsStorageFlag(buffer);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        IntPtr bufferHandle = buffer.Handle;
 | 
			
		||||
 | 
			
		||||
        Refresh.Refresh_BindVertexStorageBuffers(
 | 
			
		||||
            Handle,
 | 
			
		||||
            slot,
 | 
			
		||||
            &bufferHandle,
 | 
			
		||||
            1
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public unsafe void BindFragmentSampler(
 | 
			
		||||
        in TextureSamplerBinding textureSamplerBinding,
 | 
			
		||||
        uint slot = 0
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        AssertGraphicsPipelineBound();
 | 
			
		||||
        AssertTextureSamplerBindingNonNull(textureSamplerBinding);
 | 
			
		||||
        AssertTextureHasSamplerFlag(textureSamplerBinding.Texture);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        Refresh.TextureSamplerBinding refreshTextureSamplerBinding = textureSamplerBinding.ToRefresh();
 | 
			
		||||
 | 
			
		||||
        Refresh.Refresh_BindFragmentSamplers(
 | 
			
		||||
            Handle,
 | 
			
		||||
            slot,
 | 
			
		||||
            &refreshTextureSamplerBinding,
 | 
			
		||||
            1
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public unsafe void BindFragmentStorageTexture(
 | 
			
		||||
        in TextureSlice textureSlice,
 | 
			
		||||
        uint slot = 0
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        AssertGraphicsPipelineBound();
 | 
			
		||||
        AssertTextureNonNull(textureSlice.Texture);
 | 
			
		||||
        AssertTextureHasGraphicsStorageFlag(textureSlice.Texture);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        Refresh.TextureSlice refreshTextureSlice = textureSlice.ToRefresh();
 | 
			
		||||
 | 
			
		||||
        Refresh.Refresh_BindFragmentStorageTextures(
 | 
			
		||||
            Handle,
 | 
			
		||||
            slot,
 | 
			
		||||
            &refreshTextureSlice,
 | 
			
		||||
            1
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public unsafe void BindFragmentStorageBuffer(
 | 
			
		||||
        Buffer buffer,
 | 
			
		||||
        uint slot = 0
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        AssertGraphicsPipelineBound();
 | 
			
		||||
        AssertBufferNonNull(buffer);
 | 
			
		||||
        AssertBufferHasGraphicsStorageFlag(buffer);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        IntPtr bufferHandle = buffer.Handle;
 | 
			
		||||
 | 
			
		||||
        Refresh.Refresh_BindFragmentStorageBuffers(
 | 
			
		||||
            Handle,
 | 
			
		||||
            slot,
 | 
			
		||||
            &bufferHandle,
 | 
			
		||||
            1
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Draws using a vertex buffer and an index buffer, and an optional instance count.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="baseVertex">The starting index offset for the vertex buffer.</param>
 | 
			
		||||
    /// <param name="startIndex">The starting index offset for the index buffer.</param>
 | 
			
		||||
    /// <param name="primitiveCount">The number of primitives to draw.</param>
 | 
			
		||||
    /// <param name="instanceCount">The number of instances to draw.</param>
 | 
			
		||||
    public void DrawIndexedPrimitives(
 | 
			
		||||
        uint baseVertex,
 | 
			
		||||
        uint startIndex,
 | 
			
		||||
        uint primitiveCount,
 | 
			
		||||
        uint instanceCount = 1
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        AssertGraphicsPipelineBound();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        Refresh.Refresh_DrawIndexedPrimitives(
 | 
			
		||||
            Handle,
 | 
			
		||||
            baseVertex,
 | 
			
		||||
            startIndex,
 | 
			
		||||
            primitiveCount,
 | 
			
		||||
            instanceCount
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Draws using a vertex buffer and an index buffer.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="baseVertex">The starting index offset for the vertex buffer.</param>
 | 
			
		||||
    /// <param name="startIndex">The starting index offset for the index buffer.</param>
 | 
			
		||||
    /// <param name="primitiveCount">The number of primitives to draw.</param>
 | 
			
		||||
    public void DrawPrimitives(
 | 
			
		||||
        uint vertexStart,
 | 
			
		||||
        uint primitiveCount
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        AssertGraphicsPipelineBound();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        Refresh.Refresh_DrawPrimitives(
 | 
			
		||||
            Handle,
 | 
			
		||||
            vertexStart,
 | 
			
		||||
            primitiveCount
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Similar to DrawPrimitives, but parameters are set from a buffer.
 | 
			
		||||
    /// The buffer must have the Indirect usage flag set.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="buffer">The draw parameters buffer.</param>
 | 
			
		||||
    /// <param name="offsetInBytes">The offset to start reading from the draw parameters buffer.</param>
 | 
			
		||||
    /// <param name="drawCount">The number of draw parameter sets that should be read from the buffer.</param>
 | 
			
		||||
    /// <param name="stride">The byte stride between sets of draw parameters.</param>
 | 
			
		||||
    public void DrawPrimitivesIndirect(
 | 
			
		||||
        Buffer buffer,
 | 
			
		||||
        uint offsetInBytes,
 | 
			
		||||
        uint drawCount,
 | 
			
		||||
        uint stride
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        AssertGraphicsPipelineBound();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        Refresh.Refresh_DrawPrimitivesIndirect(
 | 
			
		||||
            Handle,
 | 
			
		||||
            buffer.Handle,
 | 
			
		||||
            offsetInBytes,
 | 
			
		||||
            drawCount,
 | 
			
		||||
            stride
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Similar to DrawIndexedPrimitives, but parameters are set from a buffer.
 | 
			
		||||
    /// The buffer must have the Indirect usage flag set.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="buffer">The draw parameters buffer.</param>
 | 
			
		||||
    /// <param name="offsetInBytes">The offset to start reading from the draw parameters buffer.</param>
 | 
			
		||||
    /// <param name="drawCount">The number of draw parameter sets that should be read from the buffer.</param>
 | 
			
		||||
    /// <param name="stride">The byte stride between sets of draw parameters.</param>
 | 
			
		||||
    public void DrawIndexedPrimitivesIndirect(
 | 
			
		||||
        Buffer buffer,
 | 
			
		||||
        uint offsetInBytes,
 | 
			
		||||
        uint drawCount,
 | 
			
		||||
        uint stride
 | 
			
		||||
    )
 | 
			
		||||
    {
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        AssertGraphicsPipelineBound();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        Refresh.Refresh_DrawIndexedPrimitivesIndirect(
 | 
			
		||||
            Handle,
 | 
			
		||||
            buffer.Handle,
 | 
			
		||||
            offsetInBytes,
 | 
			
		||||
            drawCount,
 | 
			
		||||
            stride
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
    private void AssertRenderPassPipelineFormatMatch(GraphicsPipeline graphicsPipeline)
 | 
			
		||||
    {
 | 
			
		||||
        for (int i = 0; i < graphicsPipeline.AttachmentInfo.ColorAttachmentDescriptions.Length; i += 1)
 | 
			
		||||
        {
 | 
			
		||||
            TextureFormat format;
 | 
			
		||||
            if (i == 0)
 | 
			
		||||
            {
 | 
			
		||||
                format = colorFormatOne;
 | 
			
		||||
            }
 | 
			
		||||
            else if (i == 1)
 | 
			
		||||
            {
 | 
			
		||||
                format = colorFormatTwo;
 | 
			
		||||
            }
 | 
			
		||||
            else if (i == 2)
 | 
			
		||||
            {
 | 
			
		||||
                format = colorFormatThree;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                format = colorFormatFour;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            TextureFormat pipelineFormat = graphicsPipeline.AttachmentInfo.ColorAttachmentDescriptions[i].Format;
 | 
			
		||||
            if (pipelineFormat != format)
 | 
			
		||||
            {
 | 
			
		||||
                throw new System.InvalidOperationException(
 | 
			
		||||
                    $"Color texture format mismatch! Pipeline expects {pipelineFormat}, render pass attachment is {format}"
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (graphicsPipeline.AttachmentInfo.HasDepthStencilAttachment)
 | 
			
		||||
        {
 | 
			
		||||
            TextureFormat pipelineDepthFormat = graphicsPipeline.AttachmentInfo.DepthStencilFormat;
 | 
			
		||||
 | 
			
		||||
            if (!hasDepthStencilAttachment)
 | 
			
		||||
            {
 | 
			
		||||
                throw new System.InvalidOperationException("Pipeline expects depth attachment!");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (pipelineDepthFormat != depthStencilFormat)
 | 
			
		||||
            {
 | 
			
		||||
                throw new System.InvalidOperationException(
 | 
			
		||||
                    $"Depth texture format mismatch! Pipeline expects {pipelineDepthFormat}, render pass attachment is {depthStencilFormat}"
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void AssertGraphicsPipelineBound(string message = "No graphics pipeline is bound!")
 | 
			
		||||
    {
 | 
			
		||||
        if (currentGraphicsPipeline == null)
 | 
			
		||||
        {
 | 
			
		||||
            throw new System.InvalidOperationException(message);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void AssertTextureNonNull(in TextureSlice textureSlice)
 | 
			
		||||
    {
 | 
			
		||||
        if (textureSlice.Texture == null)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NullReferenceException("Texture must not be null!");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void AssertTextureSamplerBindingNonNull(in TextureSamplerBinding binding)
 | 
			
		||||
    {
 | 
			
		||||
        if (binding.Texture == null || binding.Texture.Handle == IntPtr.Zero)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NullReferenceException("Texture binding must not be null!");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (binding.Sampler == null || binding.Sampler.Handle == IntPtr.Zero)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NullReferenceException("Sampler binding must not be null!");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void AssertTextureHasSamplerFlag(Texture texture)
 | 
			
		||||
    {
 | 
			
		||||
        if ((texture.UsageFlags & TextureUsageFlags.Sampler) == 0)
 | 
			
		||||
        {
 | 
			
		||||
            throw new System.ArgumentException("The bound Texture's UsageFlags must include TextureUsageFlags.Sampler!");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void AssertTextureHasGraphicsStorageFlag(Texture texture)
 | 
			
		||||
    {
 | 
			
		||||
        if ((texture.UsageFlags & TextureUsageFlags.GraphicsStorage) == 0)
 | 
			
		||||
        {
 | 
			
		||||
            throw new System.ArgumentException("The bound Texture's UsageFlags must include TextureUsageFlags.GraphicsStorage!");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void AssertBufferNonNull(Buffer buffer)
 | 
			
		||||
    {
 | 
			
		||||
        if (buffer == null || buffer.Handle == IntPtr.Zero)
 | 
			
		||||
        {
 | 
			
		||||
            throw new System.NullReferenceException("Buffer must not be null!");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void AssertBufferHasGraphicsStorageFlag(Buffer buffer)
 | 
			
		||||
    {
 | 
			
		||||
        if ((buffer.UsageFlags & BufferUsageFlags.GraphicsStorage) == 0)
 | 
			
		||||
        {
 | 
			
		||||
            throw new System.ArgumentException("The bound Buffer's UsageFlags must include BufferUsageFlag.GraphicsStorage!");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								Nerfed.Runtime/Graphics/RenderPassPool.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								Nerfed.Runtime/Graphics/RenderPassPool.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
internal class RenderPassPool
 | 
			
		||||
{
 | 
			
		||||
	private ConcurrentQueue<RenderPass> RenderPasses = new ConcurrentQueue<RenderPass>();
 | 
			
		||||
 | 
			
		||||
	public RenderPass Obtain()
 | 
			
		||||
	{
 | 
			
		||||
		if (RenderPasses.TryDequeue(out RenderPass renderPass))
 | 
			
		||||
		{
 | 
			
		||||
			return renderPass;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			return new RenderPass();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void Return(RenderPass renderPass)
 | 
			
		||||
	{
 | 
			
		||||
		RenderPasses.Enqueue(renderPass);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										376
									
								
								Nerfed.Runtime/Graphics/ResourceUploader.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										376
									
								
								Nerfed.Runtime/Graphics/ResourceUploader.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,376 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
// FIXME: can we map the transfer buffer instead of maintaining a local pointer
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// A convenience structure for creating resources and uploading data to them.
 | 
			
		||||
///
 | 
			
		||||
/// Note that Upload or UploadAndWait must be called after the Create methods for the data to actually be uploaded.
 | 
			
		||||
///
 | 
			
		||||
/// Note that this structure does not magically keep memory usage down -
 | 
			
		||||
/// you may want to stagger uploads over multiple submissions to minimize memory usage.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public unsafe class ResourceUploader : GraphicsResource
 | 
			
		||||
{
 | 
			
		||||
	TransferBuffer BufferTransferBuffer;
 | 
			
		||||
	TransferBuffer TextureTransferBuffer;
 | 
			
		||||
 | 
			
		||||
	byte* bufferData;
 | 
			
		||||
	uint bufferDataOffset = 0;
 | 
			
		||||
	uint bufferDataSize = 1024;
 | 
			
		||||
 | 
			
		||||
	byte* textureData;
 | 
			
		||||
	uint textureDataOffset = 0;
 | 
			
		||||
	uint textureDataSize = 1024;
 | 
			
		||||
 | 
			
		||||
	List<(uint, BufferRegion, bool)> BufferUploads = new List<(uint, BufferRegion, bool)>();
 | 
			
		||||
	List<(uint, TextureRegion, bool)> TextureUploads = new List<(uint, TextureRegion, bool)>();
 | 
			
		||||
 | 
			
		||||
	public ResourceUploader(GraphicsDevice device) : base(device)
 | 
			
		||||
	{
 | 
			
		||||
		bufferData = (byte*) NativeMemory.Alloc(bufferDataSize);
 | 
			
		||||
		textureData = (byte*) NativeMemory.Alloc(textureDataSize);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Buffers
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a Buffer with data to be uploaded.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public Buffer CreateBuffer<T>(Span<T> data, BufferUsageFlags usageFlags) where T : unmanaged
 | 
			
		||||
	{
 | 
			
		||||
		uint lengthInBytes = (uint) (Marshal.SizeOf<T>() * data.Length);
 | 
			
		||||
		Buffer buffer = new Buffer(Device, usageFlags, lengthInBytes);
 | 
			
		||||
 | 
			
		||||
		SetBufferData(buffer, 0, data, false);
 | 
			
		||||
 | 
			
		||||
		return buffer;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Prepares upload of data into a Buffer.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public void SetBufferData<T>(Buffer buffer, uint bufferOffsetInElements, Span<T> data, bool cycle) where T : unmanaged
 | 
			
		||||
	{
 | 
			
		||||
		uint elementSize = (uint) Marshal.SizeOf<T>();
 | 
			
		||||
		uint offsetInBytes = elementSize * bufferOffsetInElements;
 | 
			
		||||
		uint lengthInBytes = (uint) (elementSize * data.Length);
 | 
			
		||||
 | 
			
		||||
		uint resourceOffset;
 | 
			
		||||
		fixed (void* spanPtr = data)
 | 
			
		||||
		{
 | 
			
		||||
			resourceOffset = CopyBufferData(spanPtr, lengthInBytes);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		BufferRegion bufferRegion = new BufferRegion(buffer, offsetInBytes, lengthInBytes);
 | 
			
		||||
		BufferUploads.Add((resourceOffset, bufferRegion, cycle));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Textures
 | 
			
		||||
 | 
			
		||||
	public Texture CreateTexture2D<T>(Span<T> pixelData, uint width, uint height) where T : unmanaged
 | 
			
		||||
	{
 | 
			
		||||
		Texture texture = Texture.CreateTexture2D(Device, width, height, TextureFormat.R8G8B8A8, TextureUsageFlags.Sampler);
 | 
			
		||||
		SetTextureData(texture, pixelData, false);
 | 
			
		||||
		return texture;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a 2D Texture from compressed image data to be uploaded.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public Texture CreateTexture2DFromCompressed(Span<byte> compressedImageData)
 | 
			
		||||
	{
 | 
			
		||||
		ImageUtils.ImageInfoFromBytes(compressedImageData, out uint width, out uint height, out uint _);
 | 
			
		||||
		Texture texture = Texture.CreateTexture2D(Device, width, height, TextureFormat.R8G8B8A8, TextureUsageFlags.Sampler);
 | 
			
		||||
		SetTextureDataFromCompressed(texture, compressedImageData);
 | 
			
		||||
		return texture;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a 2D Texture from a compressed image stream to be uploaded.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public Texture CreateTexture2DFromCompressed(Stream compressedImageStream)
 | 
			
		||||
	{
 | 
			
		||||
		long length = compressedImageStream.Length;
 | 
			
		||||
		void* buffer = NativeMemory.Alloc((nuint) length);
 | 
			
		||||
		Span<byte> span = new Span<byte>(buffer, (int) length);
 | 
			
		||||
		compressedImageStream.ReadExactly(span);
 | 
			
		||||
 | 
			
		||||
		Texture texture = CreateTexture2DFromCompressed(span);
 | 
			
		||||
 | 
			
		||||
		NativeMemory.Free(buffer);
 | 
			
		||||
 | 
			
		||||
		return texture;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a 2D Texture from a compressed image file to be uploaded.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public Texture CreateTexture2DFromCompressed(string compressedImageFilePath)
 | 
			
		||||
	{
 | 
			
		||||
		FileStream fileStream = new FileStream(compressedImageFilePath, FileMode.Open, FileAccess.Read);
 | 
			
		||||
		return CreateTexture2DFromCompressed(fileStream);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a texture from a DDS stream.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public Texture CreateTextureFromDDS(Stream stream)
 | 
			
		||||
	{
 | 
			
		||||
		using BinaryReader reader = new BinaryReader(stream);
 | 
			
		||||
		Texture texture;
 | 
			
		||||
		int faces;
 | 
			
		||||
		ImageUtils.ParseDDS(reader, out TextureFormat format, out int width, out int height, out int levels, out bool 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)
 | 
			
		||||
			{
 | 
			
		||||
				int levelWidth = width >> level;
 | 
			
		||||
				int levelHeight = height >> level;
 | 
			
		||||
 | 
			
		||||
				int levelSize = ImageUtils.CalculateDDSLevelSize(levelWidth, levelHeight, format);
 | 
			
		||||
				void* byteBuffer = NativeMemory.Alloc((nuint) levelSize);
 | 
			
		||||
				Span<byte> byteSpan = new Span<byte>(byteBuffer, levelSize);
 | 
			
		||||
				stream.ReadExactly(byteSpan);
 | 
			
		||||
 | 
			
		||||
				TextureRegion textureRegion = new TextureRegion
 | 
			
		||||
				{
 | 
			
		||||
					TextureSlice = new TextureSlice
 | 
			
		||||
					{
 | 
			
		||||
						Texture = texture,
 | 
			
		||||
						Layer = (uint) face,
 | 
			
		||||
						MipLevel = (uint) level
 | 
			
		||||
					},
 | 
			
		||||
					X = 0,
 | 
			
		||||
					Y = 0,
 | 
			
		||||
					Z = 0,
 | 
			
		||||
					Width = (uint) levelWidth,
 | 
			
		||||
					Height = (uint) levelHeight,
 | 
			
		||||
					Depth = 1
 | 
			
		||||
				};
 | 
			
		||||
 | 
			
		||||
				SetTextureData(textureRegion, byteSpan, false);
 | 
			
		||||
 | 
			
		||||
				NativeMemory.Free(byteBuffer);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return texture;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a texture from a DDS file.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public Texture CreateTextureFromDDS(string path)
 | 
			
		||||
	{
 | 
			
		||||
		FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read);
 | 
			
		||||
		return CreateTextureFromDDS(stream);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void SetTextureDataFromCompressed(TextureRegion textureRegion, Span<byte> compressedImageData)
 | 
			
		||||
	{
 | 
			
		||||
		byte* pixelData = ImageUtils.GetPixelDataFromBytes(compressedImageData, out uint _, out uint _, out uint sizeInBytes);
 | 
			
		||||
		Span<byte> pixelSpan = new Span<byte>((void*) pixelData, (int) sizeInBytes);
 | 
			
		||||
 | 
			
		||||
		SetTextureData(textureRegion, pixelSpan, false);
 | 
			
		||||
 | 
			
		||||
		ImageUtils.FreePixelData(pixelData);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void SetTextureDataFromCompressed(TextureRegion textureRegion, Stream compressedImageStream)
 | 
			
		||||
	{
 | 
			
		||||
		long length = compressedImageStream.Length;
 | 
			
		||||
		void* buffer = NativeMemory.Alloc((nuint) length);
 | 
			
		||||
		Span<byte> span = new Span<byte>(buffer, (int) length);
 | 
			
		||||
		compressedImageStream.ReadExactly(span);
 | 
			
		||||
		SetTextureDataFromCompressed(textureRegion, span);
 | 
			
		||||
		NativeMemory.Free(buffer);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void SetTextureDataFromCompressed(TextureRegion textureRegion, string compressedImageFilePath)
 | 
			
		||||
	{
 | 
			
		||||
		FileStream fileStream = new FileStream(compressedImageFilePath, FileMode.Open, FileAccess.Read);
 | 
			
		||||
		SetTextureDataFromCompressed(textureRegion, fileStream);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Prepares upload of pixel data into a TextureSlice.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public void SetTextureData<T>(TextureRegion textureRegion, Span<T> data, bool cycle) where T : unmanaged
 | 
			
		||||
	{
 | 
			
		||||
		int elementSize = Marshal.SizeOf<T>();
 | 
			
		||||
		uint dataLengthInBytes = (uint) (elementSize * data.Length);
 | 
			
		||||
 | 
			
		||||
		uint resourceOffset;
 | 
			
		||||
		fixed (T* dataPtr = data)
 | 
			
		||||
		{
 | 
			
		||||
			resourceOffset = CopyTextureData(dataPtr, dataLengthInBytes, Texture.BytesPerPixel(textureRegion.TextureSlice.Texture.Format));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		TextureUploads.Add((resourceOffset, textureRegion, cycle));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Upload
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Uploads all the data corresponding to the created resources.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public void Upload()
 | 
			
		||||
	{
 | 
			
		||||
		CopyToTransferBuffer();
 | 
			
		||||
 | 
			
		||||
		CommandBuffer commandBuffer = Device.AcquireCommandBuffer();
 | 
			
		||||
		RecordUploadCommands(commandBuffer);
 | 
			
		||||
		Device.Submit(commandBuffer);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Uploads and then blocks until the upload is finished.
 | 
			
		||||
	/// This is useful for keeping memory usage down during threaded upload.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public void UploadAndWait()
 | 
			
		||||
	{
 | 
			
		||||
		CopyToTransferBuffer();
 | 
			
		||||
 | 
			
		||||
		CommandBuffer commandBuffer = Device.AcquireCommandBuffer();
 | 
			
		||||
		RecordUploadCommands(commandBuffer);
 | 
			
		||||
		Fence fence = Device.SubmitAndAcquireFence(commandBuffer);
 | 
			
		||||
		Device.WaitForFence(fence);
 | 
			
		||||
		Device.ReleaseFence(fence);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Helper methods
 | 
			
		||||
 | 
			
		||||
	private void CopyToTransferBuffer()
 | 
			
		||||
	{
 | 
			
		||||
		if (BufferUploads.Count > 0)
 | 
			
		||||
		{
 | 
			
		||||
			if (BufferTransferBuffer == null || BufferTransferBuffer.Size < bufferDataSize)
 | 
			
		||||
			{
 | 
			
		||||
				BufferTransferBuffer?.Dispose();
 | 
			
		||||
				BufferTransferBuffer = new TransferBuffer(Device, TransferBufferUsage.Upload, bufferDataSize);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			Span<byte> dataSpan = new Span<byte>(bufferData, (int) bufferDataSize);
 | 
			
		||||
			BufferTransferBuffer.SetData(dataSpan, true);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		if (TextureUploads.Count > 0)
 | 
			
		||||
		{
 | 
			
		||||
			if (TextureTransferBuffer == null || TextureTransferBuffer.Size < textureDataSize)
 | 
			
		||||
			{
 | 
			
		||||
				TextureTransferBuffer?.Dispose();
 | 
			
		||||
				TextureTransferBuffer = new TransferBuffer(Device, TransferBufferUsage.Upload, textureDataSize);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			Span<byte> dataSpan = new Span<byte>(textureData, (int) textureDataSize);
 | 
			
		||||
			TextureTransferBuffer.SetData(dataSpan, true);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void RecordUploadCommands(CommandBuffer commandBuffer)
 | 
			
		||||
	{
 | 
			
		||||
		CopyPass copyPass = commandBuffer.BeginCopyPass();
 | 
			
		||||
 | 
			
		||||
		foreach ((uint transferOffset, BufferRegion bufferRegion, bool option) in BufferUploads)
 | 
			
		||||
		{
 | 
			
		||||
			copyPass.UploadToBuffer(
 | 
			
		||||
				new TransferBufferLocation(BufferTransferBuffer, transferOffset),
 | 
			
		||||
				bufferRegion,
 | 
			
		||||
				option
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		foreach ((uint transferOffset, TextureRegion textureRegion, bool option) in TextureUploads)
 | 
			
		||||
		{
 | 
			
		||||
			copyPass.UploadToTexture(
 | 
			
		||||
				new TextureTransferInfo(TextureTransferBuffer, transferOffset),
 | 
			
		||||
				textureRegion,
 | 
			
		||||
				option
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		commandBuffer.EndCopyPass(copyPass);
 | 
			
		||||
 | 
			
		||||
		BufferUploads.Clear();
 | 
			
		||||
		TextureUploads.Clear();
 | 
			
		||||
		bufferDataOffset = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private uint CopyBufferData(void* ptr, uint lengthInBytes)
 | 
			
		||||
	{
 | 
			
		||||
		if (bufferDataOffset + lengthInBytes >= bufferDataSize)
 | 
			
		||||
		{
 | 
			
		||||
			bufferDataSize = bufferDataOffset + lengthInBytes;
 | 
			
		||||
			bufferData = (byte*) NativeMemory.Realloc(bufferData, bufferDataSize);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		uint resourceOffset = bufferDataOffset;
 | 
			
		||||
 | 
			
		||||
		NativeMemory.Copy(ptr, bufferData + bufferDataOffset, lengthInBytes);
 | 
			
		||||
		bufferDataOffset += lengthInBytes;
 | 
			
		||||
 | 
			
		||||
		return resourceOffset;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private uint CopyTextureData(void* ptr, uint lengthInBytes, uint alignment)
 | 
			
		||||
	{
 | 
			
		||||
		textureDataOffset = RoundToAlignment(textureDataOffset, alignment);
 | 
			
		||||
 | 
			
		||||
		if (textureDataOffset + lengthInBytes >= textureDataSize)
 | 
			
		||||
		{
 | 
			
		||||
			textureDataSize = textureDataOffset + lengthInBytes;
 | 
			
		||||
			textureData = (byte*) NativeMemory.Realloc(textureData, textureDataSize);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		uint resourceOffset = textureDataOffset;
 | 
			
		||||
 | 
			
		||||
		NativeMemory.Copy(ptr, textureData + textureDataOffset, lengthInBytes);
 | 
			
		||||
		textureDataOffset += lengthInBytes;
 | 
			
		||||
 | 
			
		||||
		return resourceOffset;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private uint RoundToAlignment(uint value, uint alignment)
 | 
			
		||||
	{
 | 
			
		||||
		return alignment * ((value + alignment - 1) / alignment);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Dispose
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// It is valid to immediately call Dispose after calling Upload.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	protected override void Dispose(bool disposing)
 | 
			
		||||
	{
 | 
			
		||||
		if (!IsDisposed)
 | 
			
		||||
		{
 | 
			
		||||
			if (disposing)
 | 
			
		||||
			{
 | 
			
		||||
				BufferTransferBuffer?.Dispose();
 | 
			
		||||
				TextureTransferBuffer?.Dispose();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			NativeMemory.Free(bufferData);
 | 
			
		||||
		}
 | 
			
		||||
		base.Dispose(disposing);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										88
									
								
								Nerfed.Runtime/Graphics/Resources/Buffer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								Nerfed.Runtime/Graphics/Resources/Buffer.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
using RefreshCS;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// A data container that can be efficiently used by the GPU.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public class Buffer : RefreshResource
 | 
			
		||||
{
 | 
			
		||||
	protected override Action<IntPtr, IntPtr> ReleaseFunction => Refresh.Refresh_ReleaseBuffer;
 | 
			
		||||
 | 
			
		||||
	public BufferUsageFlags UsageFlags { get; }
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Size in bytes.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public uint Size { get; }
 | 
			
		||||
 | 
			
		||||
	private string name;
 | 
			
		||||
	public string Name
 | 
			
		||||
	{
 | 
			
		||||
		get => name;
 | 
			
		||||
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
			if (Device.DebugMode)
 | 
			
		||||
			{
 | 
			
		||||
				Refresh.Refresh_SetBufferName(
 | 
			
		||||
					Device.Handle,
 | 
			
		||||
					Handle,
 | 
			
		||||
					value
 | 
			
		||||
				);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			name = value;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a buffer of appropriate size given a type and element count.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <typeparam name="T">The type that the buffer will contain.</typeparam>
 | 
			
		||||
	/// <param name="device">The GraphicsDevice.</param>
 | 
			
		||||
	/// <param name="usageFlags">Specifies how the buffer will be used.</param>
 | 
			
		||||
	/// <param name="elementCount">How many elements of type T the buffer will contain.</param>
 | 
			
		||||
	/// <returns></returns>
 | 
			
		||||
	public unsafe static Buffer Create<T>(
 | 
			
		||||
		GraphicsDevice device,
 | 
			
		||||
		BufferUsageFlags usageFlags,
 | 
			
		||||
		uint elementCount
 | 
			
		||||
	) where T : unmanaged
 | 
			
		||||
	{
 | 
			
		||||
		return new Buffer(
 | 
			
		||||
			device,
 | 
			
		||||
			usageFlags,
 | 
			
		||||
			(uint) Marshal.SizeOf<T>() * elementCount
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a buffer.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="device">An initialized GraphicsDevice.</param>
 | 
			
		||||
	/// <param name="usageFlags">Specifies how the buffer will be used.</param>
 | 
			
		||||
	/// <param name="sizeInBytes">The length of the array. Cannot be resized.</param>
 | 
			
		||||
	public Buffer(
 | 
			
		||||
		GraphicsDevice device,
 | 
			
		||||
		BufferUsageFlags usageFlags,
 | 
			
		||||
		uint sizeInBytes
 | 
			
		||||
	) : base(device)
 | 
			
		||||
	{
 | 
			
		||||
		Handle = Refresh.Refresh_CreateBuffer(
 | 
			
		||||
			device.Handle,
 | 
			
		||||
			(Refresh.BufferUsageFlags) usageFlags,
 | 
			
		||||
			sizeInBytes
 | 
			
		||||
		);
 | 
			
		||||
		UsageFlags = usageFlags;
 | 
			
		||||
		Size = sizeInBytes;
 | 
			
		||||
		name = "";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static implicit operator BufferBinding(Buffer b)
 | 
			
		||||
	{
 | 
			
		||||
		return new BufferBinding(b, 0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										91
									
								
								Nerfed.Runtime/Graphics/Resources/ComputePipeline.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								Nerfed.Runtime/Graphics/Resources/ComputePipeline.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
			
		||||
using RefreshCS;
 | 
			
		||||
using System;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Compute pipelines perform arbitrary parallel processing on input data.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public class ComputePipeline : RefreshResource
 | 
			
		||||
{
 | 
			
		||||
	protected override Action<IntPtr, IntPtr> ReleaseFunction => Refresh.Refresh_ReleaseComputePipeline;
 | 
			
		||||
 | 
			
		||||
	public uint ReadOnlyStorageTextureCount { get; }
 | 
			
		||||
	public uint ReadOnlyStorageBufferCount { get; }
 | 
			
		||||
	public uint ReadWriteStorageTextureCount { get; }
 | 
			
		||||
	public uint ReadWriteStorageBufferCount { get; }
 | 
			
		||||
	public uint UniformBufferCount { get; }
 | 
			
		||||
 | 
			
		||||
	public ComputePipeline(
 | 
			
		||||
		GraphicsDevice device,
 | 
			
		||||
		string filePath,
 | 
			
		||||
		string entryPointName,
 | 
			
		||||
		in ComputePipelineCreateInfo computePipelineCreateInfo
 | 
			
		||||
	) : base(device)
 | 
			
		||||
	{
 | 
			
		||||
		using FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
 | 
			
		||||
		Handle = CreateFromStream(device, stream, entryPointName, computePipelineCreateInfo);
 | 
			
		||||
 | 
			
		||||
		ReadOnlyStorageTextureCount = computePipelineCreateInfo.ReadOnlyStorageTextureCount;
 | 
			
		||||
		ReadOnlyStorageBufferCount = computePipelineCreateInfo.ReadOnlyStorageBufferCount;
 | 
			
		||||
		ReadWriteStorageTextureCount = computePipelineCreateInfo.ReadWriteStorageTextureCount;
 | 
			
		||||
		ReadWriteStorageBufferCount = computePipelineCreateInfo.ReadWriteStorageBufferCount;
 | 
			
		||||
		UniformBufferCount = computePipelineCreateInfo.UniformBufferCount;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public ComputePipeline(
 | 
			
		||||
		GraphicsDevice device,
 | 
			
		||||
		Stream stream,
 | 
			
		||||
		string entryPointName,
 | 
			
		||||
		in ComputePipelineCreateInfo computePipelineCreateInfo
 | 
			
		||||
	) : base(device)
 | 
			
		||||
	{
 | 
			
		||||
		Handle = CreateFromStream(device, stream, entryPointName, computePipelineCreateInfo);
 | 
			
		||||
 | 
			
		||||
		ReadOnlyStorageTextureCount = computePipelineCreateInfo.ReadOnlyStorageTextureCount;
 | 
			
		||||
		ReadOnlyStorageBufferCount = computePipelineCreateInfo.ReadOnlyStorageBufferCount;
 | 
			
		||||
		ReadWriteStorageTextureCount = computePipelineCreateInfo.ReadWriteStorageTextureCount;
 | 
			
		||||
		ReadWriteStorageBufferCount = computePipelineCreateInfo.ReadWriteStorageBufferCount;
 | 
			
		||||
		UniformBufferCount = computePipelineCreateInfo.UniformBufferCount;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static unsafe nint CreateFromStream(
 | 
			
		||||
		GraphicsDevice device,
 | 
			
		||||
		Stream stream,
 | 
			
		||||
		string entryPointName,
 | 
			
		||||
		in ComputePipelineCreateInfo computePipelineCreateInfo
 | 
			
		||||
	) {
 | 
			
		||||
		byte* bytecodeBuffer = (byte*) NativeMemory.Alloc((nuint) stream.Length);
 | 
			
		||||
		Span<byte> bytecodeSpan = new Span<byte>(bytecodeBuffer, (int) stream.Length);
 | 
			
		||||
		stream.ReadExactly(bytecodeSpan);
 | 
			
		||||
 | 
			
		||||
		Refresh.ComputePipelineCreateInfo refreshPipelineCreateInfo;
 | 
			
		||||
		refreshPipelineCreateInfo.Code = bytecodeBuffer;
 | 
			
		||||
		refreshPipelineCreateInfo.CodeSize = (nuint) stream.Length;
 | 
			
		||||
		refreshPipelineCreateInfo.EntryPointName = entryPointName;
 | 
			
		||||
		refreshPipelineCreateInfo.Format = (Refresh.ShaderFormat) computePipelineCreateInfo.ShaderFormat;
 | 
			
		||||
		refreshPipelineCreateInfo.ReadOnlyStorageTextureCount = computePipelineCreateInfo.ReadOnlyStorageTextureCount;
 | 
			
		||||
		refreshPipelineCreateInfo.ReadOnlyStorageBufferCount = computePipelineCreateInfo.ReadOnlyStorageBufferCount;
 | 
			
		||||
		refreshPipelineCreateInfo.ReadWriteStorageTextureCount = computePipelineCreateInfo.ReadWriteStorageTextureCount;
 | 
			
		||||
		refreshPipelineCreateInfo.ReadWriteStorageBufferCount = computePipelineCreateInfo.ReadWriteStorageBufferCount;
 | 
			
		||||
		refreshPipelineCreateInfo.UniformBufferCount = computePipelineCreateInfo.UniformBufferCount;
 | 
			
		||||
		refreshPipelineCreateInfo.ThreadCountX = computePipelineCreateInfo.ThreadCountX;
 | 
			
		||||
		refreshPipelineCreateInfo.ThreadCountY = computePipelineCreateInfo.ThreadCountY;
 | 
			
		||||
		refreshPipelineCreateInfo.ThreadCountZ = computePipelineCreateInfo.ThreadCountZ;
 | 
			
		||||
 | 
			
		||||
		IntPtr computePipelineHandle = Refresh.Refresh_CreateComputePipeline(
 | 
			
		||||
			device.Handle,
 | 
			
		||||
			refreshPipelineCreateInfo
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		if (computePipelineHandle == nint.Zero)
 | 
			
		||||
		{
 | 
			
		||||
			throw new Exception("Could not create compute pipeline!");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		NativeMemory.Free(bytecodeBuffer);
 | 
			
		||||
		return computePipelineHandle;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								Nerfed.Runtime/Graphics/Resources/Fence.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								Nerfed.Runtime/Graphics/Resources/Fence.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
using System;
 | 
			
		||||
using RefreshCS;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Fences allow you to track the status of a submitted command buffer. <br/>
 | 
			
		||||
/// You should only acquire a Fence if you will need to track the command buffer. <br/>
 | 
			
		||||
/// You should make sure to call GraphicsDevice.ReleaseFence when done with a Fence to avoid memory growth. <br/>
 | 
			
		||||
/// The Fence object itself is basically just a wrapper for the Refresh_Fence. <br/>
 | 
			
		||||
/// The internal handle is replaced so that we can pool Fence objects to manage garbage.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public class Fence : RefreshResource
 | 
			
		||||
{
 | 
			
		||||
	protected override Action<nint, nint> ReleaseFunction => Refresh.Refresh_ReleaseFence;
 | 
			
		||||
 | 
			
		||||
	internal Fence(GraphicsDevice device) : base(device)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	internal void SetHandle(nint handle)
 | 
			
		||||
	{
 | 
			
		||||
		Handle = handle;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										99
									
								
								Nerfed.Runtime/Graphics/Resources/GraphicsPipeline.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								Nerfed.Runtime/Graphics/Resources/GraphicsPipeline.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
using RefreshCS;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Graphics pipelines encapsulate all of the render state in a single object. <br/>
 | 
			
		||||
/// These pipelines are bound before draw calls are issued.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public class GraphicsPipeline : RefreshResource
 | 
			
		||||
{
 | 
			
		||||
	protected override Action<IntPtr, IntPtr> ReleaseFunction => Refresh.Refresh_ReleaseGraphicsPipeline;
 | 
			
		||||
 | 
			
		||||
	public Shader VertexShader;
 | 
			
		||||
	public Shader FragmentShader;
 | 
			
		||||
	public SampleCount SampleCount { get; }
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
	internal GraphicsPipelineAttachmentInfo AttachmentInfo { get; }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	public unsafe GraphicsPipeline(
 | 
			
		||||
		GraphicsDevice device,
 | 
			
		||||
		in GraphicsPipelineCreateInfo graphicsPipelineCreateInfo
 | 
			
		||||
	) : base(device)
 | 
			
		||||
	{
 | 
			
		||||
		Refresh.GraphicsPipelineCreateInfo refreshGraphicsPipelineCreateInfo;
 | 
			
		||||
 | 
			
		||||
		Refresh.VertexAttribute* vertexAttributes = (Refresh.VertexAttribute*) NativeMemory.Alloc(
 | 
			
		||||
			(nuint) (graphicsPipelineCreateInfo.VertexInputState.VertexAttributes.Length * Marshal.SizeOf<Refresh.VertexAttribute>())
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		for (int i = 0; i < graphicsPipelineCreateInfo.VertexInputState.VertexAttributes.Length; i += 1)
 | 
			
		||||
		{
 | 
			
		||||
			vertexAttributes[i] = graphicsPipelineCreateInfo.VertexInputState.VertexAttributes[i].ToRefresh();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		Refresh.VertexBinding* vertexBindings = (Refresh.VertexBinding*) NativeMemory.Alloc(
 | 
			
		||||
			(nuint) (graphicsPipelineCreateInfo.VertexInputState.VertexBindings.Length * Marshal.SizeOf<Refresh.VertexBinding>())
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		for (int i = 0; i < graphicsPipelineCreateInfo.VertexInputState.VertexBindings.Length; i += 1)
 | 
			
		||||
		{
 | 
			
		||||
			vertexBindings[i] = graphicsPipelineCreateInfo.VertexInputState.VertexBindings[i].ToRefresh();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		Refresh.ColorAttachmentDescription* colorAttachmentDescriptions = stackalloc Refresh.ColorAttachmentDescription[
 | 
			
		||||
			graphicsPipelineCreateInfo.AttachmentInfo.ColorAttachmentDescriptions.Length
 | 
			
		||||
		];
 | 
			
		||||
 | 
			
		||||
		for (int i = 0; i < graphicsPipelineCreateInfo.AttachmentInfo.ColorAttachmentDescriptions.Length; i += 1)
 | 
			
		||||
		{
 | 
			
		||||
			colorAttachmentDescriptions[i].Format = (Refresh.TextureFormat) graphicsPipelineCreateInfo.AttachmentInfo.ColorAttachmentDescriptions[i].Format;
 | 
			
		||||
			colorAttachmentDescriptions[i].BlendState = graphicsPipelineCreateInfo.AttachmentInfo.ColorAttachmentDescriptions[i].BlendState.ToRefresh();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		refreshGraphicsPipelineCreateInfo.VertexShader = graphicsPipelineCreateInfo.VertexShader.Handle;
 | 
			
		||||
		refreshGraphicsPipelineCreateInfo.FragmentShader = graphicsPipelineCreateInfo.FragmentShader.Handle;
 | 
			
		||||
 | 
			
		||||
		refreshGraphicsPipelineCreateInfo.VertexInputState.VertexAttributes = vertexAttributes;
 | 
			
		||||
		refreshGraphicsPipelineCreateInfo.VertexInputState.VertexAttributeCount = (uint) graphicsPipelineCreateInfo.VertexInputState.VertexAttributes.Length;
 | 
			
		||||
		refreshGraphicsPipelineCreateInfo.VertexInputState.VertexBindings = vertexBindings;
 | 
			
		||||
		refreshGraphicsPipelineCreateInfo.VertexInputState.VertexBindingCount = (uint) graphicsPipelineCreateInfo.VertexInputState.VertexBindings.Length;
 | 
			
		||||
 | 
			
		||||
		refreshGraphicsPipelineCreateInfo.PrimitiveType = (Refresh.PrimitiveType) graphicsPipelineCreateInfo.PrimitiveType;
 | 
			
		||||
 | 
			
		||||
		refreshGraphicsPipelineCreateInfo.RasterizerState = graphicsPipelineCreateInfo.RasterizerState.ToRefresh();
 | 
			
		||||
		refreshGraphicsPipelineCreateInfo.MultisampleState = graphicsPipelineCreateInfo.MultisampleState.ToRefresh();
 | 
			
		||||
		refreshGraphicsPipelineCreateInfo.DepthStencilState = graphicsPipelineCreateInfo.DepthStencilState.ToRefresh();
 | 
			
		||||
 | 
			
		||||
		refreshGraphicsPipelineCreateInfo.AttachmentInfo.ColorAttachmentCount = (uint) graphicsPipelineCreateInfo.AttachmentInfo.ColorAttachmentDescriptions.Length;
 | 
			
		||||
		refreshGraphicsPipelineCreateInfo.AttachmentInfo.ColorAttachmentDescriptions = colorAttachmentDescriptions;
 | 
			
		||||
		refreshGraphicsPipelineCreateInfo.AttachmentInfo.DepthStencilFormat = (Refresh.TextureFormat) graphicsPipelineCreateInfo.AttachmentInfo.DepthStencilFormat;
 | 
			
		||||
		refreshGraphicsPipelineCreateInfo.AttachmentInfo.HasDepthStencilAttachment = Conversions.BoolToInt(graphicsPipelineCreateInfo.AttachmentInfo.HasDepthStencilAttachment);
 | 
			
		||||
 | 
			
		||||
		refreshGraphicsPipelineCreateInfo.BlendConstants[0] = graphicsPipelineCreateInfo.BlendConstants.R;
 | 
			
		||||
		refreshGraphicsPipelineCreateInfo.BlendConstants[1] = graphicsPipelineCreateInfo.BlendConstants.G;
 | 
			
		||||
		refreshGraphicsPipelineCreateInfo.BlendConstants[2] = graphicsPipelineCreateInfo.BlendConstants.B;
 | 
			
		||||
		refreshGraphicsPipelineCreateInfo.BlendConstants[3] = graphicsPipelineCreateInfo.BlendConstants.A;
 | 
			
		||||
 | 
			
		||||
		Handle = Refresh.Refresh_CreateGraphicsPipeline(device.Handle, refreshGraphicsPipelineCreateInfo);
 | 
			
		||||
		if (Handle == IntPtr.Zero)
 | 
			
		||||
		{
 | 
			
		||||
			throw new Exception("Could not create graphics pipeline!");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		NativeMemory.Free(vertexAttributes);
 | 
			
		||||
		NativeMemory.Free(vertexBindings);
 | 
			
		||||
 | 
			
		||||
		VertexShader = graphicsPipelineCreateInfo.VertexShader;
 | 
			
		||||
		FragmentShader = graphicsPipelineCreateInfo.FragmentShader;
 | 
			
		||||
		SampleCount = graphicsPipelineCreateInfo.MultisampleState.MultisampleCount;
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
		AttachmentInfo = graphicsPipelineCreateInfo.AttachmentInfo;
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								Nerfed.Runtime/Graphics/Resources/Sampler.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								Nerfed.Runtime/Graphics/Resources/Sampler.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
using System;
 | 
			
		||||
using RefreshCS;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Specifies how a texture will be sampled in a shader.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public class Sampler : RefreshResource
 | 
			
		||||
{
 | 
			
		||||
	protected override Action<IntPtr, IntPtr> ReleaseFunction => Refresh.Refresh_ReleaseSampler;
 | 
			
		||||
 | 
			
		||||
	public Sampler(
 | 
			
		||||
		GraphicsDevice device,
 | 
			
		||||
		in SamplerCreateInfo samplerCreateInfo
 | 
			
		||||
	) : base(device)
 | 
			
		||||
	{
 | 
			
		||||
		Handle = Refresh.Refresh_CreateSampler(
 | 
			
		||||
			device.Handle,
 | 
			
		||||
			samplerCreateInfo.ToRefresh()
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										91
									
								
								Nerfed.Runtime/Graphics/Resources/Shader.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								Nerfed.Runtime/Graphics/Resources/Shader.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
			
		||||
using RefreshCS;
 | 
			
		||||
using System;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Shaders are used to create graphics pipelines.
 | 
			
		||||
/// Graphics pipelines take a vertex shader and a fragment shader.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public class Shader : RefreshResource
 | 
			
		||||
{
 | 
			
		||||
	protected override Action<IntPtr, IntPtr> ReleaseFunction => Refresh.Refresh_ReleaseShader;
 | 
			
		||||
 | 
			
		||||
	public uint SamplerCount { get; }
 | 
			
		||||
	public uint StorageTextureCount { get; }
 | 
			
		||||
	public uint StorageBufferCount { get; }
 | 
			
		||||
	public uint UniformBufferCount { get; }
 | 
			
		||||
 | 
			
		||||
	public unsafe Shader(
 | 
			
		||||
		GraphicsDevice device,
 | 
			
		||||
		string filePath,
 | 
			
		||||
		string entryPointName,
 | 
			
		||||
		in ShaderCreateInfo shaderCreateInfo
 | 
			
		||||
	) : base(device)
 | 
			
		||||
	{
 | 
			
		||||
		using FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
 | 
			
		||||
		Handle = CreateFromStream(
 | 
			
		||||
			device,
 | 
			
		||||
			stream,
 | 
			
		||||
			entryPointName,
 | 
			
		||||
			shaderCreateInfo
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		SamplerCount = shaderCreateInfo.SamplerCount;
 | 
			
		||||
		StorageTextureCount = shaderCreateInfo.StorageTextureCount;
 | 
			
		||||
		StorageBufferCount = shaderCreateInfo.StorageBufferCount;
 | 
			
		||||
		UniformBufferCount = shaderCreateInfo.UniformBufferCount;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public unsafe Shader(
 | 
			
		||||
		GraphicsDevice device,
 | 
			
		||||
		Stream stream,
 | 
			
		||||
		string entryPointName,
 | 
			
		||||
		in ShaderCreateInfo shaderCreateInfo
 | 
			
		||||
	) : base(device)
 | 
			
		||||
	{
 | 
			
		||||
		Handle = CreateFromStream(
 | 
			
		||||
			device,
 | 
			
		||||
			stream,
 | 
			
		||||
			entryPointName,
 | 
			
		||||
			shaderCreateInfo
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		SamplerCount = shaderCreateInfo.SamplerCount;
 | 
			
		||||
		StorageTextureCount = shaderCreateInfo.StorageTextureCount;
 | 
			
		||||
		StorageBufferCount = shaderCreateInfo.StorageBufferCount;
 | 
			
		||||
		UniformBufferCount = shaderCreateInfo.UniformBufferCount;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static unsafe IntPtr CreateFromStream(
 | 
			
		||||
		GraphicsDevice device,
 | 
			
		||||
		Stream stream,
 | 
			
		||||
		string entryPointName,
 | 
			
		||||
		in ShaderCreateInfo shaderCreateInfo
 | 
			
		||||
	) {
 | 
			
		||||
		void* bytecodeBuffer = NativeMemory.Alloc((nuint) stream.Length);
 | 
			
		||||
		Span<byte> bytecodeSpan = new Span<byte>(bytecodeBuffer, (int) stream.Length);
 | 
			
		||||
		stream.ReadExactly(bytecodeSpan);
 | 
			
		||||
 | 
			
		||||
		Refresh.ShaderCreateInfo refreshShaderCreateInfo;
 | 
			
		||||
		refreshShaderCreateInfo.CodeSize = (nuint) stream.Length;
 | 
			
		||||
		refreshShaderCreateInfo.Code = (byte*) bytecodeBuffer;
 | 
			
		||||
		refreshShaderCreateInfo.EntryPointName = entryPointName;
 | 
			
		||||
		refreshShaderCreateInfo.Stage = (Refresh.ShaderStage) shaderCreateInfo.ShaderStage;
 | 
			
		||||
		refreshShaderCreateInfo.Format = (Refresh.ShaderFormat) shaderCreateInfo.ShaderFormat;
 | 
			
		||||
		refreshShaderCreateInfo.SamplerCount = shaderCreateInfo.SamplerCount;
 | 
			
		||||
		refreshShaderCreateInfo.StorageTextureCount = shaderCreateInfo.StorageTextureCount;
 | 
			
		||||
		refreshShaderCreateInfo.StorageBufferCount = shaderCreateInfo.StorageBufferCount;
 | 
			
		||||
		refreshShaderCreateInfo.UniformBufferCount = shaderCreateInfo.UniformBufferCount;
 | 
			
		||||
 | 
			
		||||
		IntPtr shaderModule = Refresh.Refresh_CreateShader(
 | 
			
		||||
			device.Handle,
 | 
			
		||||
			refreshShaderCreateInfo
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		NativeMemory.Free(bytecodeBuffer);
 | 
			
		||||
		return shaderModule;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										326
									
								
								Nerfed.Runtime/Graphics/Resources/Texture.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										326
									
								
								Nerfed.Runtime/Graphics/Resources/Texture.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,326 @@
 | 
			
		||||
using System;
 | 
			
		||||
using RefreshCS;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// A multi-dimensional data container that can be efficiently used by the GPU.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public class Texture : RefreshResource
 | 
			
		||||
{
 | 
			
		||||
	public uint Width { get; internal set; }
 | 
			
		||||
	public uint Height { get; internal set; }
 | 
			
		||||
	public uint Depth { get; }
 | 
			
		||||
	public TextureFormat Format { get; internal set; }
 | 
			
		||||
	public bool IsCube { get; }
 | 
			
		||||
	public uint LayerCount { get; }
 | 
			
		||||
	public uint LevelCount { get; }
 | 
			
		||||
	public SampleCount SampleCount { get; }
 | 
			
		||||
	public TextureUsageFlags UsageFlags { get; }
 | 
			
		||||
	public uint Size { get; }
 | 
			
		||||
 | 
			
		||||
	private string name;
 | 
			
		||||
	public string Name
 | 
			
		||||
	{
 | 
			
		||||
		get => name;
 | 
			
		||||
 | 
			
		||||
		set
 | 
			
		||||
		{
 | 
			
		||||
			if (Device.DebugMode)
 | 
			
		||||
			{
 | 
			
		||||
				Refresh.Refresh_SetTextureName(
 | 
			
		||||
					Device.Handle,
 | 
			
		||||
					Handle,
 | 
			
		||||
					value
 | 
			
		||||
				);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			name = value;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// FIXME: this allocates a delegate instance
 | 
			
		||||
	protected override Action<IntPtr, IntPtr> ReleaseFunction => Refresh.Refresh_ReleaseTexture;
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a 2D texture.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="device">An initialized GraphicsDevice.</param>
 | 
			
		||||
	/// <param name="width">The width of the texture.</param>
 | 
			
		||||
	/// <param name="height">The height of the texture.</param>
 | 
			
		||||
	/// <param name="format">The format of the texture.</param>
 | 
			
		||||
	/// <param name="usageFlags">Specifies how the texture will be used.</param>
 | 
			
		||||
	/// <param name="levelCount">Specifies the number of mip levels.</param>
 | 
			
		||||
	public static Texture CreateTexture2D(
 | 
			
		||||
		GraphicsDevice device,
 | 
			
		||||
		uint width,
 | 
			
		||||
		uint height,
 | 
			
		||||
		TextureFormat format,
 | 
			
		||||
		TextureUsageFlags usageFlags,
 | 
			
		||||
		uint levelCount = 1,
 | 
			
		||||
		SampleCount sampleCount = SampleCount.One
 | 
			
		||||
	) {
 | 
			
		||||
		TextureCreateInfo textureCreateInfo = new TextureCreateInfo
 | 
			
		||||
		{
 | 
			
		||||
			Width = width,
 | 
			
		||||
			Height = height,
 | 
			
		||||
			Depth = 1,
 | 
			
		||||
			IsCube = false,
 | 
			
		||||
			LayerCount = 1,
 | 
			
		||||
			LevelCount = levelCount,
 | 
			
		||||
			SampleCount = sampleCount,
 | 
			
		||||
			Format = format,
 | 
			
		||||
			UsageFlags = usageFlags
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		return new Texture(device, textureCreateInfo);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a 2D texture array.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="device">An initialized GraphicsDevice.</param>
 | 
			
		||||
	/// <param name="width">The width of the texture.</param>
 | 
			
		||||
	/// <param name="height">The height of the texture.</param>
 | 
			
		||||
	/// <param name="layerCount">The layer count of the texture.</param>
 | 
			
		||||
	/// <param name="format">The format of the texture.</param>
 | 
			
		||||
	/// <param name="usageFlags">Specifies how the texture will be used.</param>
 | 
			
		||||
	/// <param name="levelCount">Specifies the number of mip levels.</param>
 | 
			
		||||
	public static Texture CreateTexture2DArray(
 | 
			
		||||
		GraphicsDevice device,
 | 
			
		||||
		uint width,
 | 
			
		||||
		uint height,
 | 
			
		||||
		uint layerCount,
 | 
			
		||||
		TextureFormat format,
 | 
			
		||||
		TextureUsageFlags usageFlags,
 | 
			
		||||
		uint levelCount = 1
 | 
			
		||||
	) {
 | 
			
		||||
		TextureCreateInfo textureCreateInfo = new TextureCreateInfo
 | 
			
		||||
		{
 | 
			
		||||
			Width = width,
 | 
			
		||||
			Height = height,
 | 
			
		||||
			Depth = 1,
 | 
			
		||||
			IsCube = false,
 | 
			
		||||
			LayerCount = layerCount,
 | 
			
		||||
			LevelCount = levelCount,
 | 
			
		||||
			Format = format,
 | 
			
		||||
			UsageFlags = usageFlags
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		return new Texture(device, textureCreateInfo);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a 3D texture.
 | 
			
		||||
	/// Note that the width, height and depth all form one slice and cannot be subdivided in a texture slice.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public static Texture CreateTexture3D(
 | 
			
		||||
		GraphicsDevice device,
 | 
			
		||||
		uint width,
 | 
			
		||||
		uint height,
 | 
			
		||||
		uint depth,
 | 
			
		||||
		TextureFormat format,
 | 
			
		||||
		TextureUsageFlags usageFlags,
 | 
			
		||||
		uint levelCount = 1
 | 
			
		||||
	) {
 | 
			
		||||
		TextureCreateInfo textureCreateInfo = new TextureCreateInfo
 | 
			
		||||
		{
 | 
			
		||||
			Width = width,
 | 
			
		||||
			Height = height,
 | 
			
		||||
			Depth = depth,
 | 
			
		||||
			IsCube = false,
 | 
			
		||||
			LayerCount = 1,
 | 
			
		||||
			LevelCount = levelCount,
 | 
			
		||||
			Format = format,
 | 
			
		||||
			UsageFlags = usageFlags
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		return new Texture(device, textureCreateInfo);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a cube texture.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="device">An initialized GraphicsDevice.</param>
 | 
			
		||||
	/// <param name="size">The length of one side of the cube.</param>
 | 
			
		||||
	/// <param name="format">The format of the texture.</param>
 | 
			
		||||
	/// <param name="usageFlags">Specifies how the texture will be used.</param>
 | 
			
		||||
	/// <param name="levelCount">Specifies the number of mip levels.</param>
 | 
			
		||||
	public static Texture CreateTextureCube(
 | 
			
		||||
		GraphicsDevice device,
 | 
			
		||||
		uint size,
 | 
			
		||||
		TextureFormat format,
 | 
			
		||||
		TextureUsageFlags usageFlags,
 | 
			
		||||
		uint levelCount = 1
 | 
			
		||||
	) {
 | 
			
		||||
		TextureCreateInfo textureCreateInfo = new TextureCreateInfo
 | 
			
		||||
		{
 | 
			
		||||
			Width = size,
 | 
			
		||||
			Height = size,
 | 
			
		||||
			Depth = 1,
 | 
			
		||||
			IsCube = true,
 | 
			
		||||
			LayerCount = 6,
 | 
			
		||||
			LevelCount = levelCount,
 | 
			
		||||
			Format = format,
 | 
			
		||||
			UsageFlags = usageFlags
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		return new Texture(device, textureCreateInfo);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a new texture using a TextureCreateInfo struct.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="device">An initialized GraphicsDevice.</param>
 | 
			
		||||
	/// <param name="textureCreateInfo">The parameters to use when creating the texture.</param>
 | 
			
		||||
	public Texture(
 | 
			
		||||
		GraphicsDevice device,
 | 
			
		||||
		in TextureCreateInfo textureCreateInfo
 | 
			
		||||
	) : base(device)
 | 
			
		||||
	{
 | 
			
		||||
		Handle = Refresh.Refresh_CreateTexture(
 | 
			
		||||
			device.Handle,
 | 
			
		||||
			textureCreateInfo.ToRefresh()
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		Format = textureCreateInfo.Format;
 | 
			
		||||
		Width = textureCreateInfo.Width;
 | 
			
		||||
		Height = textureCreateInfo.Height;
 | 
			
		||||
		Depth = textureCreateInfo.Depth;
 | 
			
		||||
		IsCube = textureCreateInfo.IsCube;
 | 
			
		||||
		LayerCount = textureCreateInfo.LayerCount;
 | 
			
		||||
		LevelCount = textureCreateInfo.LevelCount;
 | 
			
		||||
		SampleCount = textureCreateInfo.SampleCount;
 | 
			
		||||
		UsageFlags = textureCreateInfo.UsageFlags;
 | 
			
		||||
		Size = Width * Height * BytesPerPixel(Format) / BlockSizeSquared(Format);
 | 
			
		||||
		name = "";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Used by Window. Swapchain texture handles are managed by the driver backend.
 | 
			
		||||
	internal Texture(
 | 
			
		||||
		GraphicsDevice device,
 | 
			
		||||
		TextureFormat format
 | 
			
		||||
	) : base(device)
 | 
			
		||||
	{
 | 
			
		||||
		Handle = IntPtr.Zero;
 | 
			
		||||
 | 
			
		||||
		Format = format;
 | 
			
		||||
		Width = 0;
 | 
			
		||||
		Height = 0;
 | 
			
		||||
		Depth = 1;
 | 
			
		||||
		IsCube = false;
 | 
			
		||||
		LevelCount = 1;
 | 
			
		||||
		SampleCount = SampleCount.One;
 | 
			
		||||
		UsageFlags = TextureUsageFlags.ColorTarget;
 | 
			
		||||
		Size = Width * Height * BytesPerPixel(Format) / BlockSizeSquared(Format);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static uint BytesPerPixel(TextureFormat format)
 | 
			
		||||
	{
 | 
			
		||||
		switch (format)
 | 
			
		||||
		{
 | 
			
		||||
			case TextureFormat.R8:
 | 
			
		||||
			case TextureFormat.R8_UINT:
 | 
			
		||||
				return 1;
 | 
			
		||||
			case TextureFormat.R5G6B5:
 | 
			
		||||
			case TextureFormat.B4G4R4A4:
 | 
			
		||||
			case TextureFormat.A1R5G5B5:
 | 
			
		||||
			case TextureFormat.R16_SFLOAT:
 | 
			
		||||
			case TextureFormat.R8G8_SNORM:
 | 
			
		||||
			case TextureFormat.R8G8_UINT:
 | 
			
		||||
			case TextureFormat.R16_UINT:
 | 
			
		||||
			case TextureFormat.D16_UNORM:
 | 
			
		||||
				return 2;
 | 
			
		||||
			case TextureFormat.R8G8B8A8:
 | 
			
		||||
			case TextureFormat.B8G8R8A8:
 | 
			
		||||
			case TextureFormat.R32_SFLOAT:
 | 
			
		||||
			case TextureFormat.R16G16:
 | 
			
		||||
			case TextureFormat.R16G16_SFLOAT:
 | 
			
		||||
			case TextureFormat.R8G8B8A8_SNORM:
 | 
			
		||||
			case TextureFormat.A2R10G10B10:
 | 
			
		||||
			case TextureFormat.R8G8B8A8_UINT:
 | 
			
		||||
			case TextureFormat.R16G16_UINT:
 | 
			
		||||
			case TextureFormat.D24_UNORM_S8_UINT:
 | 
			
		||||
			case TextureFormat.D32_SFLOAT:
 | 
			
		||||
				return 4;
 | 
			
		||||
			case TextureFormat.D32_SFLOAT_S8_UINT:
 | 
			
		||||
				return 5;
 | 
			
		||||
			case TextureFormat.R16G16B16A16_SFLOAT:
 | 
			
		||||
			case TextureFormat.R16G16B16A16:
 | 
			
		||||
			case TextureFormat.R32G32_SFLOAT:
 | 
			
		||||
			case TextureFormat.R16G16B16A16_UINT:
 | 
			
		||||
			case TextureFormat.BC1:
 | 
			
		||||
				return 8;
 | 
			
		||||
			case TextureFormat.R32G32B32A32_SFLOAT:
 | 
			
		||||
			case TextureFormat.BC2:
 | 
			
		||||
			case TextureFormat.BC3:
 | 
			
		||||
			case TextureFormat.BC7:
 | 
			
		||||
				return 16;
 | 
			
		||||
			default:
 | 
			
		||||
				Log.Error("Texture format not recognized!");
 | 
			
		||||
				return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static uint TexelSize(TextureFormat format)
 | 
			
		||||
	{
 | 
			
		||||
		switch (format)
 | 
			
		||||
		{
 | 
			
		||||
			case TextureFormat.BC2:
 | 
			
		||||
			case TextureFormat.BC3:
 | 
			
		||||
			case TextureFormat.BC7:
 | 
			
		||||
				return 16;
 | 
			
		||||
			case TextureFormat.BC1:
 | 
			
		||||
				return 8;
 | 
			
		||||
			default:
 | 
			
		||||
				return 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static uint BlockSizeSquared(TextureFormat format)
 | 
			
		||||
	{
 | 
			
		||||
		switch (format)
 | 
			
		||||
		{
 | 
			
		||||
			case TextureFormat.BC1:
 | 
			
		||||
			case TextureFormat.BC2:
 | 
			
		||||
			case TextureFormat.BC3:
 | 
			
		||||
			case TextureFormat.BC7:
 | 
			
		||||
				return 16;
 | 
			
		||||
			case TextureFormat.R8G8B8A8:
 | 
			
		||||
			case TextureFormat.B8G8R8A8:
 | 
			
		||||
			case TextureFormat.R5G6B5:
 | 
			
		||||
			case TextureFormat.A1R5G5B5:
 | 
			
		||||
			case TextureFormat.B4G4R4A4:
 | 
			
		||||
			case TextureFormat.A2R10G10B10:
 | 
			
		||||
			case TextureFormat.R16G16:
 | 
			
		||||
			case TextureFormat.R16G16B16A16:
 | 
			
		||||
			case TextureFormat.R8:
 | 
			
		||||
			case TextureFormat.R8G8_SNORM:
 | 
			
		||||
			case TextureFormat.R8G8B8A8_SNORM:
 | 
			
		||||
			case TextureFormat.R16_SFLOAT:
 | 
			
		||||
			case TextureFormat.R16G16_SFLOAT:
 | 
			
		||||
			case TextureFormat.R16G16B16A16_SFLOAT:
 | 
			
		||||
			case TextureFormat.R32_SFLOAT:
 | 
			
		||||
			case TextureFormat.R32G32_SFLOAT:
 | 
			
		||||
			case TextureFormat.R32G32B32A32_SFLOAT:
 | 
			
		||||
			case TextureFormat.R8_UINT:
 | 
			
		||||
			case TextureFormat.R8G8_UINT:
 | 
			
		||||
			case TextureFormat.R8G8B8A8_UINT:
 | 
			
		||||
			case TextureFormat.R16_UINT:
 | 
			
		||||
			case TextureFormat.R16G16_UINT:
 | 
			
		||||
			case TextureFormat.R16G16B16A16_UINT:
 | 
			
		||||
			case TextureFormat.D16_UNORM:
 | 
			
		||||
			case TextureFormat.D24_UNORM:
 | 
			
		||||
			case TextureFormat.D24_UNORM_S8_UINT:
 | 
			
		||||
			case TextureFormat.D32_SFLOAT:
 | 
			
		||||
			case TextureFormat.D32_SFLOAT_S8_UINT:
 | 
			
		||||
				return 1;
 | 
			
		||||
			default:
 | 
			
		||||
				Log.Error("Texture format not recognized!");
 | 
			
		||||
				return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static implicit operator TextureSlice(Texture t) => new TextureSlice(t);
 | 
			
		||||
	public static implicit operator TextureRegion(Texture t) => new TextureRegion(t);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										209
									
								
								Nerfed.Runtime/Graphics/Resources/TransferBuffer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								Nerfed.Runtime/Graphics/Resources/TransferBuffer.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,209 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
using RefreshCS;
 | 
			
		||||
 | 
			
		||||
namespace Nerfed.Runtime.Graphics;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// A data container that can efficiently transfer data to and from the GPU.
 | 
			
		||||
/// </summary>
 | 
			
		||||
public unsafe class TransferBuffer : RefreshResource
 | 
			
		||||
{
 | 
			
		||||
	protected override Action<IntPtr, IntPtr> ReleaseFunction => Refresh.Refresh_ReleaseTransferBuffer;
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Size in bytes.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public uint Size { get; }
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
	public bool Mapped { get; private set; }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a buffer of requested size given a type and element count.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <typeparam name="T">The type that the buffer will contain.</typeparam>
 | 
			
		||||
	/// <param name="device">The GraphicsDevice.</param>
 | 
			
		||||
	/// <param name="elementCount">How many elements of type T the buffer will contain.</param>
 | 
			
		||||
	/// <returns></returns>
 | 
			
		||||
	public unsafe static TransferBuffer Create<T>(
 | 
			
		||||
		GraphicsDevice device,
 | 
			
		||||
		TransferBufferUsage usage,
 | 
			
		||||
		uint elementCount
 | 
			
		||||
	) where T : unmanaged
 | 
			
		||||
	{
 | 
			
		||||
		return new TransferBuffer(
 | 
			
		||||
			device,
 | 
			
		||||
			usage,
 | 
			
		||||
			(uint) Marshal.SizeOf<T>() * elementCount
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Creates a TransferBuffer.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="device">An initialized GraphicsDevice.</param>
 | 
			
		||||
	/// <param name="usage">Whether this will be used to upload buffers or textures.</param>
 | 
			
		||||
	/// <param name="sizeInBytes">The length of the buffer. Cannot be resized.</param>
 | 
			
		||||
	public TransferBuffer(
 | 
			
		||||
		GraphicsDevice device,
 | 
			
		||||
		TransferBufferUsage usage,
 | 
			
		||||
		uint sizeInBytes
 | 
			
		||||
	) : base(device)
 | 
			
		||||
	{
 | 
			
		||||
		Handle = Refresh.Refresh_CreateTransferBuffer(
 | 
			
		||||
			device.Handle,
 | 
			
		||||
			(Refresh.TransferBufferUsage) usage,
 | 
			
		||||
			sizeInBytes
 | 
			
		||||
		);
 | 
			
		||||
		Size = sizeInBytes;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Immediately copies data from a Span to the TransferBuffer.
 | 
			
		||||
	/// Returns the length of the copy in bytes.
 | 
			
		||||
	///
 | 
			
		||||
	/// If cycle is set to true and this TransferBuffer was used in an Upload command,
 | 
			
		||||
	/// that command will still use the correct data at the cost of increased memory usage.
 | 
			
		||||
	///
 | 
			
		||||
	/// If cycle is set to false, the data will be overwritten immediately,
 | 
			
		||||
	/// which could cause a data race.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public unsafe uint SetData<T>(
 | 
			
		||||
		Span<T> source,
 | 
			
		||||
		uint bufferOffsetInBytes,
 | 
			
		||||
		bool cycle
 | 
			
		||||
	) where T : unmanaged
 | 
			
		||||
	{
 | 
			
		||||
		int elementSize = Marshal.SizeOf<T>();
 | 
			
		||||
		uint dataLengthInBytes = (uint) (elementSize * source.Length);
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
		AssertBufferBoundsCheck(Size, bufferOffsetInBytes, dataLengthInBytes);
 | 
			
		||||
		AssertNotMapped();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		fixed (T* dataPtr = source)
 | 
			
		||||
		{
 | 
			
		||||
			Refresh.Refresh_SetTransferData(
 | 
			
		||||
				Device.Handle,
 | 
			
		||||
				(nint) dataPtr,
 | 
			
		||||
				new Refresh.TransferBufferRegion
 | 
			
		||||
				{
 | 
			
		||||
					TransferBuffer = Handle,
 | 
			
		||||
					Offset = bufferOffsetInBytes,
 | 
			
		||||
					Size = dataLengthInBytes
 | 
			
		||||
				},
 | 
			
		||||
				Conversions.BoolToInt(cycle)
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return dataLengthInBytes;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Immediately copies data from a Span to the TransferBuffer.
 | 
			
		||||
	/// Returns the length of the copy in bytes.
 | 
			
		||||
	///
 | 
			
		||||
	/// If cycle is set to true and this TransferBuffer was used in an Upload command,
 | 
			
		||||
	/// that command will still use the corret data at the cost of increased memory usage.
 | 
			
		||||
	///
 | 
			
		||||
	/// If cycle is set to false, the data will be overwritten immediately,
 | 
			
		||||
	/// which could cause a data race.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public unsafe uint SetData<T>(
 | 
			
		||||
		Span<T> source,
 | 
			
		||||
		bool cycle
 | 
			
		||||
	) where T : unmanaged
 | 
			
		||||
	{
 | 
			
		||||
		return SetData(source, 0, cycle);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Immediately copies data from the TransferBuffer into a Span.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public unsafe void GetData<T>(
 | 
			
		||||
		Span<T> destination,
 | 
			
		||||
		uint bufferOffsetInBytes = 0
 | 
			
		||||
	) where T : unmanaged
 | 
			
		||||
	{
 | 
			
		||||
		int elementSize = Marshal.SizeOf<T>();
 | 
			
		||||
		uint dataLengthInBytes = (uint) (elementSize * destination.Length);
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
		AssertBufferBoundsCheck(Size, bufferOffsetInBytes, dataLengthInBytes);
 | 
			
		||||
		AssertNotMapped();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		fixed (T* dataPtr = destination)
 | 
			
		||||
		{
 | 
			
		||||
			Refresh.Refresh_GetTransferData(
 | 
			
		||||
				Device.Handle,
 | 
			
		||||
				new Refresh.TransferBufferRegion
 | 
			
		||||
				{
 | 
			
		||||
					TransferBuffer = Handle,
 | 
			
		||||
					Offset = bufferOffsetInBytes,
 | 
			
		||||
					Size = dataLengthInBytes
 | 
			
		||||
				},
 | 
			
		||||
				(nint) dataPtr
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Maps the transfer buffer into application address space.
 | 
			
		||||
	/// You must call Unmap before encoding transfer commands.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public unsafe void Map(bool cycle, out byte* data)
 | 
			
		||||
	{
 | 
			
		||||
#if DEBUG
 | 
			
		||||
		AssertNotMapped();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		Refresh.Refresh_MapTransferBuffer(
 | 
			
		||||
			Device.Handle,
 | 
			
		||||
			Handle,
 | 
			
		||||
			Conversions.BoolToInt(cycle),
 | 
			
		||||
			out data
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
		Mapped = true;
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Unmaps the transfer buffer.
 | 
			
		||||
	/// The pointer given by Map is no longer valid.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public void Unmap()
 | 
			
		||||
	{
 | 
			
		||||
		Refresh.Refresh_UnmapTransferBuffer(
 | 
			
		||||
			Device.Handle,
 | 
			
		||||
			Handle
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
		Mapped = false;
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
	private void AssertBufferBoundsCheck(uint bufferLengthInBytes, uint offsetInBytes, uint copyLengthInBytes)
 | 
			
		||||
	{
 | 
			
		||||
		if (copyLengthInBytes > bufferLengthInBytes + offsetInBytes)
 | 
			
		||||
		{
 | 
			
		||||
			throw new InvalidOperationException($"Data overflow! Transfer buffer length {bufferLengthInBytes}, offset {offsetInBytes}, copy length {copyLengthInBytes}");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void AssertNotMapped()
 | 
			
		||||
	{
 | 
			
		||||
		if (Mapped)
 | 
			
		||||
		{
 | 
			
		||||
			throw new InvalidOperationException("Transfer buffer must not be mapped!");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								Nerfed.Runtime/Graphics/StockShaders/Binary/fullscreen.vert.spv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Nerfed.Runtime/Graphics/StockShaders/Binary/fullscreen.vert.spv
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								Nerfed.Runtime/Graphics/StockShaders/Binary/text_msdf.frag.spv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Nerfed.Runtime/Graphics/StockShaders/Binary/text_msdf.frag.spv
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
#version 450
 | 
			
		||||
 | 
			
		||||
layout(location = 0) out vec2 outTexCoord;
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
	outTexCoord = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
 | 
			
		||||
	gl_Position = vec4(outTexCoord * vec2(2.0, -2.0) + vec2(-1.0, 1.0), 0.0, 1.0);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								Nerfed.Runtime/Graphics/StockShaders/Source/text_msdf.frag
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								Nerfed.Runtime/Graphics/StockShaders/Source/text_msdf.frag
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
#version 450
 | 
			
		||||
 | 
			
		||||
layout(location = 0) in vec2 inTexCoord;
 | 
			
		||||
layout(location = 1) in vec4 inColor;
 | 
			
		||||
 | 
			
		||||
layout(location = 0) out vec4 outColor;
 | 
			
		||||
 | 
			
		||||
layout(set = 2, binding = 0) uniform sampler2D msdf;
 | 
			
		||||
 | 
			
		||||
layout(set = 3, binding = 0) uniform UBO
 | 
			
		||||
{
 | 
			
		||||
	float pxRange;
 | 
			
		||||
} ubo;
 | 
			
		||||
 | 
			
		||||
float median(float r, float g, float b)
 | 
			
		||||
{
 | 
			
		||||
	return max(min(r, g), min(max(r, g), b));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float screenPxRange()
 | 
			
		||||
{
 | 
			
		||||
    vec2 unitRange = vec2(ubo.pxRange)/vec2(textureSize(msdf, 0));
 | 
			
		||||
    vec2 screenTexSize = vec2(1.0)/fwidth(inTexCoord);
 | 
			
		||||
    return max(0.5*dot(unitRange, screenTexSize), 1.0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
	vec3 msd = texture(msdf, inTexCoord).rgb;
 | 
			
		||||
	float sd = median(msd.r, msd.g, msd.b);
 | 
			
		||||
    float screenPxDistance = screenPxRange() * (sd - 0.5);
 | 
			
		||||
    float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0);
 | 
			
		||||
    outColor = mix(vec4(0.0, 0.0, 0.0, 0.0), inColor, opacity);
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,20 @@
 | 
			
		||||
#version 450
 | 
			
		||||
 | 
			
		||||
layout(location = 0) in vec3 inPos;
 | 
			
		||||
layout(location = 1) in vec2 inTexCoord;
 | 
			
		||||
layout(location = 2) in vec4 inColor;
 | 
			
		||||
 | 
			
		||||
layout(location = 0) out vec2 outTexCoord;
 | 
			
		||||
layout(location = 1) out vec4 outColor;
 | 
			
		||||
 | 
			
		||||
layout(set = 1, binding = 0) uniform UBO
 | 
			
		||||
{
 | 
			
		||||
	mat4 ViewProjection;
 | 
			
		||||
} ubo;
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
	gl_Position = ubo.ViewProjection * vec4(inPos, 1.0);
 | 
			
		||||
	outTexCoord = inTexCoord;
 | 
			
		||||
	outColor = inColor;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,38 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This effect is based on the YUV-to-RGBA GLSL shader found in SDL.
 | 
			
		||||
 * Thus, it also released under the zlib license:
 | 
			
		||||
 * http://libsdl.org/license.php
 | 
			
		||||
 */
 | 
			
		||||
#version 450
 | 
			
		||||
 | 
			
		||||
layout(location = 0) in vec2 TexCoord;
 | 
			
		||||
 | 
			
		||||
layout(location = 0) out vec4 FragColor;
 | 
			
		||||
 | 
			
		||||
layout(set = 2, binding = 0) uniform sampler2D YSampler;
 | 
			
		||||
layout(set = 2, binding = 1) uniform sampler2D USampler;
 | 
			
		||||
layout(set = 2, binding = 2) uniform sampler2D VSampler;
 | 
			
		||||
 | 
			
		||||
/* More info about colorspace conversion:
 | 
			
		||||
 * http://www.equasys.de/colorconversion.html
 | 
			
		||||
 * http://www.equasys.de/colorformat.html
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
const vec3 offset = vec3(-0.0625, -0.5, -0.5);
 | 
			
		||||
const vec3 Rcoeff = vec3(1.164,  0.000,  1.793);
 | 
			
		||||
const vec3 Gcoeff = vec3(1.164, -0.213, -0.533);
 | 
			
		||||
const vec3 Bcoeff = vec3(1.164,  2.112,  0.000);
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
	vec3 yuv;
 | 
			
		||||
	yuv.x = texture(YSampler, TexCoord).r;
 | 
			
		||||
	yuv.y = texture(USampler, TexCoord).r;
 | 
			
		||||
	yuv.z = texture(VSampler, TexCoord).r;
 | 
			
		||||
	yuv += offset;
 | 
			
		||||
 | 
			
		||||
	FragColor.r = dot(yuv, Rcoeff);
 | 
			
		||||
	FragColor.g = dot(yuv, Gcoeff);
 | 
			
		||||
	FragColor.b = dot(yuv, Bcoeff);
 | 
			
		||||
	FragColor.a = 1.0;
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user