using RefreshCS; using System; using System.IO; using System.Runtime.InteropServices; namespace Nerfed.Runtime.Graphics; /// /// Shaders are used to create graphics pipelines. /// Graphics pipelines take a vertex shader and a fragment shader. /// public class Shader : RefreshResource { protected override Action 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 bytecodeSpan = new Span(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; } }