Nerfed/Nerfed.Runtime/Graphics/Resources/ComputePipeline.cs

92 lines
3.8 KiB
C#

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;
}
}