using RefreshCS; using System; using System.IO; using System.Runtime.InteropServices; namespace Nerfed.Runtime.Graphics; /// /// Compute pipelines perform arbitrary parallel processing on input data. /// public class ComputePipeline : RefreshResource { protected override Action 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 bytecodeSpan = new Span(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; } }