Beispiel #1
0
            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);
            }
Beispiel #2
0
            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);
            }
Beispiel #3
0
            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);
            }
Beispiel #4
0
            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);
            }
Beispiel #5
0
        /// <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;
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
 /// <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);
Beispiel #9
0
        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));
            }
Beispiel #10
0
    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();
                }
            }
        }