static ReadOnlySpan <sbyte> GetD3D12CompileTarget(GraphicsShaderKind graphicsShaderKind) { ReadOnlySpan <sbyte> d3d12CompileTarget; switch (graphicsShaderKind) { case GraphicsShaderKind.Vertex: { d3d12CompileTarget = D3D12CompileTarget_vs_5_0; break; } case GraphicsShaderKind.Pixel: { d3d12CompileTarget = D3D12CompileTarget_ps_5_0; break; } default: { ThrowArgumentOutOfRangeException(nameof(graphicsShaderKind), graphicsShaderKind); d3d12CompileTarget = default; break; } } return(d3d12CompileTarget); }
static string GetVulkanShaderStage(GraphicsShaderKind graphicsShaderKind) { string vulkanShaderStage; switch (graphicsShaderKind) { case GraphicsShaderKind.Vertex: { vulkanShaderStage = "vertex"; break; } case GraphicsShaderKind.Pixel: { vulkanShaderStage = "fragment"; break; } default: { ThrowArgumentOutOfRangeException(nameof(graphicsShaderKind), graphicsShaderKind); vulkanShaderStage = string.Empty; break; } } return(vulkanShaderStage); }
static string GetVulkanShaderStage(GraphicsShaderKind graphicsShaderKind) { string vulkanShaderStage; switch (graphicsShaderKind) { case GraphicsShaderKind.Vertex: { vulkanShaderStage = "vertex"; break; } case GraphicsShaderKind.Pixel: { vulkanShaderStage = "fragment"; break; } default: { ThrowNotImplementedException(); vulkanShaderStage = string.Empty; break; } } return(vulkanShaderStage); }
static ReadOnlySpan <sbyte> GetD3D12CompileTarget(GraphicsShaderKind graphicsShaderKind) { ReadOnlySpan <sbyte> d3d12CompileTarget; switch (graphicsShaderKind) { case GraphicsShaderKind.Vertex: { d3d12CompileTarget = D3D12CompileTarget_vs_5_0; break; } case GraphicsShaderKind.Pixel: { d3d12CompileTarget = D3D12CompileTarget_ps_5_0; break; } default: { ThrowNotImplementedException(); d3d12CompileTarget = default; break; } } return(d3d12CompileTarget); }
/// <summary>Initializes a new instance of the <see cref="GraphicsShader" /> class.</summary> /// <param name="device">The device for which the shader was created.</param> /// <param name="kind">The shader kind.</param> /// <param name="entryPointName">The name of the entry point for the shader.</param> /// <exception cref="ArgumentNullException"><paramref name="device" /> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException"><paramref name="entryPointName" /> is <c>null</c>.</exception> protected GraphicsShader(GraphicsDevice device, GraphicsShaderKind kind, string entryPointName) : base(device) { ThrowIfNull(entryPointName, nameof(entryPointName)); _entryPointName = entryPointName; _kind = kind; }
internal D3D12GraphicsShader(D3D12GraphicsDevice device, GraphicsShaderKind kind, ReadOnlySpan <byte> bytecode, string entryPointName) : base(device, kind, entryPointName) { var bytecodeLength = (nuint)bytecode.Length; _d3d12ShaderBytecode.pShaderBytecode = Allocate(bytecodeLength); _d3d12ShaderBytecode.BytecodeLength = bytecodeLength; var destination = new Span <byte>(_d3d12ShaderBytecode.pShaderBytecode, (int)bytecodeLength); bytecode.CopyTo(destination); _ = _state.Transition(to: Initialized); }
internal VulkanGraphicsShader(VulkanGraphicsDevice device, GraphicsShaderKind kind, ReadOnlySpan <byte> bytecode, string entryPointName) : base(device, kind, entryPointName) { var bytecodeLength = (nuint)bytecode.Length; _vulkanShaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; _vulkanShaderModuleCreateInfo.codeSize = bytecodeLength; _vulkanShaderModuleCreateInfo.pCode = (uint *)Allocate(bytecodeLength); var destination = new Span <byte>(_vulkanShaderModuleCreateInfo.pCode, (int)bytecodeLength); bytecode.CopyTo(destination); _vulkanShaderModule = new ValueLazy <VkShaderModule>(CreateVulkanShaderModule); _ = _state.Transition(to: Initialized); }
/// <summary>Creates a new graphics shader for the device.</summary> /// <param name="kind">The kind of graphics shader to create.</param> /// <param name="bytecode">The underlying bytecode for the graphics shader.</param> /// <param name="entryPointName">The name of the entry point for the graphics shader.</param> /// <returns>A new graphics shader created for the device.</returns> /// <exception cref="ArgumentNullException"><paramref name="entryPointName" /> is <c>null</c>.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="kind" /> is unsupported.</exception> /// <exception cref="ObjectDisposedException">The device has been disposed.</exception> public abstract GraphicsShader CreateShader(GraphicsShaderKind kind, ReadOnlySpan <byte> bytecode, string entryPointName);
protected unsafe GraphicsShader CompileShader(GraphicsDevice graphicsDevice, GraphicsShaderKind kind, string shaderName, string entryPointName) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && _compositionAssemblies.Contains(Program.s_graphicsProviderD3D12)) { var assetName = $"{shaderName}{kind}.hlsl"; fixed(char *assetPath = GetAssetFullPath("Shaders", assetName)) fixed(sbyte *entryPoint = MarshalStringToUtf8(entryPointName)) { var compileFlags = 0u; #if DEBUG // Enable better shader debugging with the graphics debugging tools. compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; #endif ID3DBlob *d3dShaderBlob = null; try { var result = D3DCompileFromFile((ushort *)assetPath, pDefines: null, (ID3DInclude *)D3D_COMPILE_STANDARD_FILE_INCLUDE, entryPoint, GetD3D12CompileTarget(kind).AsPointer(), compileFlags, Flags2: 0, &d3dShaderBlob, ppErrorMsgs: null); if (FAILED(result)) { ThrowExternalException(nameof(D3DCompileFromFile), result); } var shaderBytecode = new ReadOnlySpan <byte>(d3dShaderBlob->GetBufferPointer(), (int)d3dShaderBlob->GetBufferSize()); return(graphicsDevice.CreateGraphicsShader(kind, shaderBytecode, entryPointName)); } finally { if (d3dShaderBlob != null) { d3dShaderBlob->Release(); } } } } else { var assetName = $"{shaderName}{kind}.glsl"; var assetPath = GetAssetFullPath("Shaders", assetName); var assetOutput = Path.ChangeExtension(assetPath, "spirv"); var additionalArgs = string.Empty; #if DEBUG // Enable better shader debugging with the graphics debugging tools. additionalArgs += $" -g -O0"; #endif var glslcProcessStartInfo = new ProcessStartInfo { Arguments = $"-fshader-stage={GetVulkanShaderStage(kind)} -o \"{assetOutput}\" -std=450core --target-env=vulkan1.0 --target-spv=spv1.0 -x glsl{additionalArgs} {assetPath}", FileName = "glslc.exe", WorkingDirectory = Path.GetDirectoryName(assetPath) !, }; Process.Start(glslcProcessStartInfo) !.WaitForExit(); using var fileReader = File.OpenRead(assetOutput); var bytecode = new byte[fileReader.Length]; _ = fileReader.Read(bytecode); return(graphicsDevice.CreateGraphicsShader(kind, bytecode, entryPointName)); }
protected unsafe GraphicsShader CompileShader(GraphicsDevice graphicsDevice, GraphicsShaderKind kind, string shaderName, string entryPointName) { var assetName = $"{shaderName}{kind}.hlsl"; fixed(char *assetPath = GetAssetFullPath("Shaders", shaderName, assetName)) fixed(sbyte *entryPoint = entryPointName.GetUtf8Span()) { var compileFlags = 0u; if (GraphicsService.EnableDebugMode) { // Enable better shader debugging with the graphics debugging tools. compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; } else { compileFlags |= D3DCOMPILE_OPTIMIZATION_LEVEL3; } ID3DBlob *d3dShaderBlob = null; ID3DBlob *d3dShaderErrorBlob = null; try { var result = D3DCompileFromFile((ushort *)assetPath, pDefines: null, D3D_COMPILE_STANDARD_FILE_INCLUDE, entryPoint, GetD3D12CompileTarget(kind).GetPointer(), compileFlags, Flags2: 0, &d3dShaderBlob, ppErrorMsgs: &d3dShaderErrorBlob); if (FAILED(result)) { // todo: var span = TerraFX.Utilities.InteropUtilities.MarshalUtf8ToReadOnlySpan((sbyte*)pError->GetBufferPointer(), (int)pError->GetBufferSize()); var errorMsg = System.Text.Encoding.UTF8.GetString((byte *)d3dShaderErrorBlob->GetBufferPointer(), (int)d3dShaderErrorBlob->GetBufferSize()); Console.WriteLine(errorMsg); ExceptionUtilities.ThrowExternalException(nameof(D3DCompileFromFile), result); } var bytecode = new UnmanagedArray <byte>(d3dShaderBlob->GetBufferSize()); new UnmanagedReadOnlySpan <byte>((byte *)d3dShaderBlob->GetBufferPointer(), bytecode.Length).CopyTo(bytecode); switch (kind) { case GraphicsShaderKind.Pixel: { return(graphicsDevice.CreatePixelShader(bytecode, entryPointName)); } case GraphicsShaderKind.Vertex: { return(graphicsDevice.CreateVertexShader(bytecode, entryPointName)); } default: { ThrowForInvalidKind(kind); return(null !); } } } finally { if (d3dShaderBlob != null) { _ = d3dShaderBlob->Release(); } if (d3dShaderErrorBlob != null) { _ = d3dShaderErrorBlob->Release(); } } }