DeclareConnectorAndBind() public method

public DeclareConnectorAndBind ( MidElementDecl element, MidAttributeWrapperDecl attr, bool &firstParam, Span span ) : void
element Spark.Mid.MidElementDecl
attr Spark.Mid.MidAttributeWrapperDecl
firstParam bool
span Span
return void
        public override void EmitImplSetup()
        {
            var uniformElement = GetElement("Uniform");
            var vertexElement = GetElement("CoarseVertex");
            var assembledVertex = GetElement("AssembledVertex");

            var constantElement = GetElement("Constant");
            var tessEnabledAttr = FindAttribute( constantElement, "__D3D11TessellationEnabled" );
            var gsEnabledAttr = FindAttribute( constantElement, "__D3D11GeometryShaderEnabled" );

            // \todo: We eventually need to support both tessellation enabled/disabled...

            var fineVertexElement = GetElement("FineVertex");
            var rasterVertexElement = GetElement("RasterVertex");

            var outputElement = vertexElement;
            if( tessEnabledAttr == null )
            {
                if( gsEnabledAttr == null )
                {
                    outputElement = rasterVertexElement;
                }
                else
                {
                    outputElement = fineVertexElement;
                }
            }

            InitBlock.AppendComment("D3D11 Vertex Shader");

            var outputAttributes = new List<MidAttributeDecl>();
            foreach (var a in outputElement.Attributes)
            {
                if (a.IsOutput) outputAttributes.Add(a);
            }

            hlslContext = new EmitContextHLSL(SharedHLSL, Range, this.EmitClass.GetName());

            var entryPointSpan = hlslContext.EntryPointSpan;

            entryPointSpan.WriteLine("{0} main(",
                hlslContext.GenerateConnectorType(outputElement));

            bool first = true;

            hlslContext.DeclareConnectorAndBind(
                assembledVertex,
                GetAttribute(vertexElement, "__ia2vs"),
                ref first,
                entryPointSpan);

            hlslContext.DeclareParamAndBind(
                GetAttribute(vertexElement, "VS_VertexID"),
                "SV_VertexID",
                ref first,
                entryPointSpan);
            hlslContext.DeclareParamAndBind(
                GetAttribute(vertexElement, "VS_InstanceID"),
                "SV_InstanceID",
                ref first,
                entryPointSpan);

            entryPointSpan.WriteLine("\t)");
            entryPointSpan.WriteLine("{");

            if( tessEnabledAttr == null )
            {
                hlslContext.EmitTempRecordCtor(
                    entryPointSpan,
                    vertexElement,
                    GetAttribute(fineVertexElement, "__c2fhelper"));

                if( gsEnabledAttr == null )
                {
                    hlslContext.EmitTempRecordCtor(
                        entryPointSpan,
                        fineVertexElement,
                        GetAttribute(rasterVertexElement, "__f2rhelper"));
                }
            }

            var resultVal = hlslContext.EmitConnectorCtor(
                entryPointSpan,
                outputElement);
            entryPointSpan.WriteLine("\treturn {0};", resultVal);
            entryPointSpan.WriteLine("}");

            hlslContext.EmitConstantBufferDecl();

            //

            EmitShaderSetup(
                hlslContext,
                "vs_5_0",
                "Vertex",
                "VS");
        }
        //
        public override void EmitImplSetup()
        {
            var uniformElement = GetElement("Uniform");
            var rasterVertex = GetElement("RasterVertex");
            var fragmentElement = GetElement("Fragment");
            var pixelElement = GetElement("Pixel");

            // Find all render targets:

            renderTargetAttributes = (from a in pixelElement.Attributes
                                      where a.Exp != null
                                      where a.IsOutput
                                      select a).ToArray();
            renderTargetCount = renderTargetAttributes.Length;

            // Depth-stencil view

            depthStencilViewAttribute = GetAttribute(uniformElement, "depthStencilView");

            // Compute the setup required by the OM

            // Blending stuff
            var blendStateType = EmitTarget.GetOpaqueType("ID3D11BlendState*");

            blendStateField = EmitClass.AddPrivateField(
                blendStateType,
                "_blendState");

            _renderTargetBlendDescs = new TargetBlendDesc[renderTargetCount];
            _renderTargetSources = new SourceInfo[renderTargetCount];
            for (int ii = 0; ii < renderTargetCount; ++ii)
            {
                DecomposeAttr(renderTargetAttributes[ii], ii);
            }

            var rtBlendDescType = EmitTarget.GetBuiltinType("D3D11_RENDER_TARGET_BLEND_DESC");
            var blendSpecVals = (from desc in _renderTargetBlendDescs
                                 select InitBlock.Struct(
                                    "D3D11_RENDER_TARGET_BLEND_DESC",
                                    InitBlock.LiteralBool(desc.blendEnable),
                                    InitBlock.Enum32(desc.color.srcBlend),
                                    InitBlock.Enum32(desc.color.destBlend),
                                    InitBlock.Enum32(desc.color.op),
                                    InitBlock.Enum32(desc.alpha.srcBlend),
                                    InitBlock.Enum32(desc.alpha.destBlend),
                                    InitBlock.Enum32(desc.alpha.op),
                                    InitBlock.LiteralU32(desc.writeMask))).ToList();
            while (blendSpecVals.Count < 8) // \todo: get the limits from somwhere!!!
            {
                blendSpecVals.Add(
                    InitBlock.Struct(
                        "D3D11_RENDER_TARGET_BLEND_DESC",
                        InitBlock.LiteralBool(false),
                        InitBlock.Enum32("D3D11_BLEND", "D3D11_BLEND_ONE", D3D11_BLEND.D3D11_BLEND_ONE),
                        InitBlock.Enum32("D3D11_BLEND", "D3D11_BLEND_ZERO", D3D11_BLEND.D3D11_BLEND_ZERO),
                        InitBlock.Enum32("D3D11_BLEND_OP", "D3D11_BLEND_OP_ADD", D3D11_BLEND_OP.D3D11_BLEND_OP_ADD),
                        InitBlock.Enum32("D3D11_BLEND", "D3D11_BLEND_ONE", D3D11_BLEND.D3D11_BLEND_ONE),
                        InitBlock.Enum32("D3D11_BLEND", "D3D11_BLEND_ZERO", D3D11_BLEND.D3D11_BLEND_ZERO),
                        InitBlock.Enum32("D3D11_BLEND_OP", "D3D11_BLEND_OP_ADD", D3D11_BLEND_OP.D3D11_BLEND_OP_ADD),
                        InitBlock.LiteralU32((UInt32)D3D11_COLOR_WRITE_ENABLE.D3D11_COLOR_WRITE_ENABLE_ALL)));
            }

            var blendSpecsVal = InitBlock.Array(
                rtBlendDescType,
                blendSpecVals);

            InitBlock.AppendComment("D3D11 Output Merger");
            var blendDescVal =
                InitBlock.Temp("blendDesc",
                    InitBlock.Struct(
                        "D3D11_BLEND_DESC",
                        InitBlock.LiteralBool(false),
                        InitBlock.LiteralBool(true),
                        blendSpecsVal));

            InitBlock.SetArrow(
                CtorThis,
                blendStateField,
                EmitTarget.GetNullPointer(blendStateType));

            InitBlock.CallCOM(
                CtorDevice,
                "ID3D11Device",
                "CreateBlendState",
                blendDescVal.GetAddress(),
                InitBlock.GetArrow(CtorThis, blendStateField).GetAddress());

            DtorBlock.CallCOM(
                DtorBlock.GetArrow(DtorThis, blendStateField),
                "IUnknown",
                "Release");

            // Emit HLSL code for PS

            InitBlock.AppendComment("D3D11 Pixel Shader");

            hlslContext = new EmitContextHLSL(SharedHLSL, Range, this.EmitClass.GetName());

            var entryPointSpan = hlslContext.EntryPointSpan;

            entryPointSpan.WriteLine("void main(");

            bool firstParam = true;
            hlslContext.DeclareConnectorAndBind(
                rasterVertex,
                GetAttribute(fragmentElement, "__rv2f"),
                ref firstParam,
                entryPointSpan);

            hlslContext.DeclareParamAndBind(
                GetAttribute(fragmentElement, "PS_ScreenSpacePosition"),
                "SV_Position",
                ref firstParam,
                entryPointSpan);

            for (int ii = 0; ii < renderTargetCount; ++ii)
            {
                if( !firstParam ) entryPointSpan.WriteLine(",");
                firstParam = false;

                var sourceInfo = _renderTargetSources[ii];
                MidExp exp = null;
                if (sourceInfo.combinedExp != null)
                {
                    // \todo: Validate other bits and bobs!!!
                    exp = sourceInfo.combinedExp;
                }
                else
                {
                    throw new NotImplementedException();
                }

                entryPointSpan.Write("\tout {1} target{0} : SV_Target{0}", ii,
                    hlslContext.EmitType(exp.Type));
            }
            entryPointSpan.WriteLine(" )");
            entryPointSpan.WriteLine("{");

            hlslContext.EmitTempRecordCtor(
                entryPointSpan,
                fragmentElement,
                GetAttribute(pixelElement, "__ps2om"));

            var psCullFragmentAttr = GetAttribute(fragmentElement, "PS_CullFragment");
            entryPointSpan.WriteLine("\tif( {0} ) discard;",
                hlslContext.EmitAttribRef(psCullFragmentAttr, entryPointSpan));

            for (int ii = 0; ii < renderTargetCount; ++ii)
            {
                var sourceInfo = _renderTargetSources[ii];
                MidExp exp = null;
                if (sourceInfo.combinedExp != null)
                {
                    // \todo: Validate other bits and bobs!!!
                    exp = sourceInfo.combinedExp;
                }
                else
                {
                    throw new NotImplementedException();
                }

                entryPointSpan.WriteLine("\ttarget{0} = {1};",
                    ii,
                    hlslContext.EmitExp(exp, entryPointSpan));
            }

            entryPointSpan.WriteLine("}");

            hlslContext.EmitConstantBufferDecl();

            //

            EmitShaderSetup(
                hlslContext,
                "ps_5_0",
                "Pixel",
                "PS");
        }
        public override void EmitImplSetup()
        {
            constantElement = GetElement("Constant");
            var uniformElement = GetElement("Uniform");
            var fineVertexElement = GetElement("FineVertex");
            var rasterVertexElement = GetElement("RasterVertex");

            InitBlock.AppendComment("D3D11 Domain Shader");

            var tessEnabledAttr = FindAttribute( constantElement, "__D3D11TessellationEnabled" );
            if( tessEnabledAttr  == null )
            {
                return;
            }

            var outputPatchElement = GetElement( "OutputPatch" );
            var controlPointElement = GetElement( "ControlPoint" );

            // \todo: Need to check whether GS is enabled.
            var gsEnabledAttr = FindAttribute( constantElement, "__D3D11GeometryShaderEnabled" );
            var outputElement = fineVertexElement;
            if( gsEnabledAttr == null )
            {
                outputElement = rasterVertexElement;
            }

            hlslContext = new EmitContextHLSL(SharedHLSL, Range, this.EmitClass.GetName());
            var entryPointSpan = hlslContext.EntryPointSpan;

            var outputControlPointCount = GetAttribute(constantElement, "HS_OutputControlPointCount");
            var tsDomain = GetAttribute(constantElement, "TS_Domain");

            // Bind a bunch of attributes that really represent constants:
            hlslContext.BindAttrLit(
                GetAttribute(constantElement, "TriangleDomain"),
                "tri");
            hlslContext.BindAttrLit(
                GetAttribute(constantElement, "QuadDomain"),
                "quad");
            hlslContext.BindAttrLit(
                GetAttribute(constantElement, "FractionalOddPartitioning"),
                "fractional_odd");
            hlslContext.BindAttrLit(
                GetAttribute(constantElement, "IntegerPartitioning"),
                "integer");
            hlslContext.BindAttrLit(
                GetAttribute(constantElement, "TriangleCWTopology"),
                "triangle_cw");

            hlslContext.GenerateConnectorType(controlPointElement);
            hlslContext.GenerateConnectorType(outputElement);

            entryPointSpan.WriteLine("[domain(\"{0}\")]",
                hlslContext.EmitAttrLit( tsDomain ));
            entryPointSpan.WriteLine("{0} main(",
                hlslContext.GenerateConnectorType(outputElement));

            bool first = true;
            if (outputPatchElement.Attributes.Any((a) => a.IsOutput))
            {
                hlslContext.DeclareConnectorAndBind(
                    outputPatchElement,
                    GetAttribute(fineVertexElement, "__op2dv"),
                    ref first,
                    entryPointSpan);
            }

            // \todo: These should not be required, but seem related
            // to an fxc bug where it expects the tess-factor inputs
            // to be re-declared in the DS...
            var edgeFactors = GetAttribute(outputPatchElement, "HS_EdgeFactors");
            var insideFactors = GetAttribute(outputPatchElement, "HS_InsideFactors");

            /*
            hlslContext.DeclareParamAndBind(
                edgeFactors,
                "SV_TessFactor",
                ref first,
                entryPointSpan);

            hlslContext.DeclareParamAndBind(
                insideFactors,
                "SV_InsideTessFactor",
                ref first,
                entryPointSpan);
            */

            hlslContext.DeclareParamAndBind(
                GetAttribute(fineVertexElement, "DS_DomainLocation"),
                "SV_DomainLocation",
                ref first,
                entryPointSpan);

            hlslContext.DeclareParamAndBind(
                GetAttribute(fineVertexElement, "DS_InputControlPoints"),
                null,
                ref first,
                entryPointSpan);
            /*

            entryPointSpan.WriteLine(",");
            entryPointSpan.WriteLine("\tconst OutputPatch<{0}, {1}> DS_InputControlPoints",
                hlslContext.GenerateConnectorType(outputControlPointElement),
                hlslContext.EmitAttribRef(
                    outputControlPointCount,
                    null));
            */

            entryPointSpan.WriteLine("\t)");
            entryPointSpan.WriteLine("{");

            if (fineVertexElement != outputElement)
            {
                hlslContext.EmitTempRecordCtor(
                    entryPointSpan,
                    fineVertexElement,
                    GetAttribute(rasterVertexElement, "__f2rhelper"));
            }

            var output = hlslContext.EmitConnectorCtor(
                entryPointSpan,
                outputElement );

            entryPointSpan.WriteLine("\treturn {0};", output);
            entryPointSpan.WriteLine("}");

            hlslContext.EmitConstantBufferDecl();

            EmitShaderSetup(
                hlslContext,
                "ds_5_0",
                "Domain",
                "DS");
        }