/// <summary> /// Creates a new instance of the Shader class. /// </summary> /// <param name="shaderBytecode">Byte array containing the compiled shader bytecode.</param> public Shader(byte[] shaderBytecode) { var bytecodeContainer = new BytecodeContainer(shaderBytecode); var programType = bytecodeContainer.Shader.Version.ProgramType; switch (programType) { case ProgramType.GeometryShader: case ProgramType.HullShader: case ProgramType.DomainShader: case ProgramType.ComputeShader: throw new NotSupportedException(string.Format( "The '{0}' shader type is not yet supported.", bytecodeContainer.Shader.Version.ProgramType)); } _constantBuffers = bytecodeContainer.ResourceDefinition.ConstantBuffers; _resourceBindings = bytecodeContainer.ResourceDefinition.ResourceBindings; _inputSignature = bytecodeContainer.InputSignature; _inputSignatureSize = _inputSignature.Parameters.Sum(x => x.ByteCount); _outputSignature = bytecodeContainer.OutputSignature; _outputSignatureSize = _outputSignature.Parameters.Sum(x => x.ByteCount); var numContexts = (programType == ProgramType.PixelShader) ? 4 : 1; _virtualMachine = new VirtualMachine(bytecodeContainer, numContexts); }
internal IEnumerable <FragmentQuad> Execute( IEnumerable <InputAssemblerPrimitiveOutput> inputs, PrimitiveTopology primitiveTopology, OutputSignatureChunk previousStageOutputSignature, BytecodeContainer pixelShader, int multiSampleCount) { // TODO: Allow selection of different viewport. var viewport = _viewports[0]; var outputInputBindings = ShaderOutputInputBindings.FromShaderSignatures( previousStageOutputSignature, pixelShader); var rasterizer = PrimitiveRasterizerFactory.CreateRasterizer( primitiveTopology, State.Description, multiSampleCount, outputInputBindings, ref viewport, FragmentFilter); foreach (var primitive in inputs) { // Frustum culling. if (ViewportCuller.ShouldCullTriangle(primitive.Vertices)) { continue; } // TODO: Clipping. // http://simonstechblog.blogspot.tw/2012/04/software-rasterizer-part-2.html#softwareRasterizerDemo // Perspective divide. for (int i = 0; i < primitive.Vertices.Length; i++) { PerspectiveDivide(ref primitive.Vertices[i].Position); } // Backface culling. if (State.Description.CullMode != CullMode.None && rasterizer.ShouldCull(primitive.Vertices)) { continue; } // Transform from clip space to screen space. for (int i = 0; i < primitive.Vertices.Length; i++) { viewport.MapClipSpaceToScreenSpace(ref primitive.Vertices[i].Position); } // Rasterize. foreach (var fragmentQuad in rasterizer.Rasterize(primitive)) { yield return(fragmentQuad); } } }
/// <summary> /// Registers are effectively shared between outputs of the previous stage /// and inputs of the next stage, so we don't need to do any mapping. We only /// need to keep track of the interpolation mode, and system value semantic, /// of the inputs. /// <seealso cref="http://msdn.microsoft.com/en-us/library/windows/desktop/bb509650(v=vs.85).aspx"/> /// /// TODO: Add some sort of runtime validation that signatures match. Direct3D /// does this, but only when debugging. /// </summary> public static ShaderOutputInputBindings FromShaderSignatures( OutputSignatureChunk outputSignature, BytecodeContainer inputShader) { var inputRegisterDeclarations = inputShader.Shader.DeclarationTokens .OfType <PixelShaderInputRegisterDeclarationToken>() .ToList(); // Only create a binding if the value is actually used in the next shader. // We can gather this information from the declaration tokens. If there is // no declaration token for an item, then it isn't used. var bindings = new List <ShaderOutputInputBinding>(); foreach (var inputParameter in inputShader.InputSignature.Parameters) { // Get register declaration for this parameter. If there is no register // declaration, then it isn't used, and we can move on. var inputRegisterDeclaration = FindInputRegisterDeclaration( inputRegisterDeclarations, inputParameter); if (inputRegisterDeclaration == null) { continue; } bindings.Add(new ShaderOutputInputBinding { Register = (int)inputParameter.Register, ComponentMask = inputParameter.Mask, InterpolationMode = inputRegisterDeclaration.InterpolationMode, SystemValueType = inputParameter.SystemValueType }); } return(new ShaderOutputInputBindings { Bindings = bindings.ToArray() }); }