Inheritance: EmitValHLSL
 public IEnumerable<string> DeclareBaseImpl(
     SimpleValHLSL val,
     string prefix,
     string semantic,
     string suffix)
 {
     yield return string.Format("{0} {1}{2}{3}",
         prefix,
         val.RealType.DeclareVar(val.Name),
         semantic,
         suffix);
 }
        public override void EmitImplSetup()
        {
            var constantElement = GetElement("Constant");
            var uniformElement = GetElement("Uniform");
            var coarseVertexElement = GetElement("CoarseVertex");

            InitBlock.AppendComment("D3D11 Hull Shader");

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

            var superPatchElement = GetElement( "__InputPatch" );
            var inputPatchElement = GetElement( "InputPatch" );
            var outputPatchElement = GetElement( "OutputPatch" );
            var controlPointElement = GetElement( "ControlPoint" );

            var patchEdgeElement = GetElement( "PatchEdge" );
            var patchCornerElement = GetElement( "PatchCorner" );
            var patchInteriorElement = GetElement( "PatchInterior" );

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

            var inputCoarseVertexCount = GetAttribute(constantElement, "HS_InputCoarseVertexCount");
            var outputControlPointCount = GetAttribute(constantElement, "HS_OutputControlPointCount");

            var tsDomain = GetAttribute(constantElement, "TS_Domain");
            var tsPartitioning = GetAttribute(constantElement, "TS_Partitioning");
            var tsOutputTopology = GetAttribute(constantElement, "TS_OutputTopology");
            var tsMaxTessFactor = GetAttribute(constantElement, "TS_MaxTessFactor");

            var hsPatchEdgeCount = GetAttribute(constantElement, "HS_PatchEdgeCount");
            var hsPatchInsideCount = GetAttribute(constantElement, "HS_PatchInsideCount");
            var hsPatchCornerCount = GetAttribute(constantElement, "HS_PatchCornerCount");

            var hsCullPatchAttr = GetAttribute(outputPatchElement, "HS_CullPatch");

            hlslContext.GenerateConnectorType(coarseVertexElement);
            hlslContext.GenerateConnectorType(controlPointElement);
            hlslContext.GenerateConnectorType(outputPatchElement);

            // OutputPatch entry point

            var outputPatchConnector = hlslContext.GenerateConnectorType(outputPatchElement);
            entryPointSpan.WriteLine("{0} __patchMain(",
                outputPatchConnector);

            bool first = true;
            hlslContext.DeclareParamAndBind(
                GetAttribute(superPatchElement, "HS_InputCoarseVertices"),
                null,
                ref first,
                entryPointSpan);

            // \todo:
            // @OutputPatch Array[ControlPoint, HS_OutputControlPointCount] HS_OutputControlPoints

            hlslContext.DeclareParamAndBind(
                GetAttribute(superPatchElement, "HS_PatchID"),
                "SV_PrimitiveID",
                ref first,
                entryPointSpan);

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

            // Declare the output patch variable, but don't initialize it
            var outputPatch = outputPatchConnector.CreateVal( "HS_OutputPatch" );
            hlslContext.DeclareLocal( outputPatch, entryPointSpan );

            // Do any input-patch initialization stuff
            var ip2op = hlslContext.EmitTempRecordCtor(
                entryPointSpan,
                inputPatchElement,
                GetAttribute(outputPatchElement, "__ip2op"));

            // Iterate over the corners of the patch, and initialize each
            entryPointSpan.WriteLine( "for( uint HS_CornerID = 0; HS_CornerID < {0}; HS_CornerID++ )",
                hlslContext.EmitAttribRef( hsPatchCornerCount, null ) );
            entryPointSpan.WriteLine("{" );

            hlslContext.BindAttr(
                GetAttribute( patchCornerElement, "__ip2pc" ),
                ip2op );

            var patchCornerIDAttr = GetAttribute( patchCornerElement, "HS_PatchCornerID" );
            var hsCornerIDVal = new SimpleValHLSL( "HS_CornerID",
                    (RealTypeHLSL) hlslContext.EmitType( patchCornerIDAttr.Type ) );
            hlslContext.BindAttr(
                patchCornerIDAttr,
                hsCornerIDVal );

            var hsPatchCornersAttr = GetAttribute( outputPatchElement, "HS_PatchCorners" );
            var hsPatchCornersVal = hlslContext.FetchAttr(
                outputPatch,
                hsPatchCornersAttr.Attribute,
                entryPointSpan );
            hlslContext.BindAttr(hsPatchCornersAttr, hsPatchCornersVal);
            var hsPatchCornerVal = hlslContext.GetElem(
                hsPatchCornersVal,
                hsCornerIDVal);

            hlslContext.InitRecord(
                entryPointSpan,
                patchCornerElement,
                hsPatchCornerVal );

            entryPointSpan.WriteLine( "}" );

            entryPointSpan.WriteLine( "for( uint HS_EdgeID = 0; HS_EdgeID < {0}; HS_EdgeID++ )",
                hlslContext.EmitAttribRef(hsPatchEdgeCount, null));
            entryPointSpan.WriteLine( "{" );

            hlslContext.BindAttr(
                GetAttribute(patchEdgeElement, "__ip2pe"),
                ip2op);

            hlslContext.BindAttr(
                GetAttribute(patchEdgeElement, "__op2pe"),
                outputPatch);

            var patchEdgeIDAttr = GetAttribute(patchEdgeElement, "HS_PatchEdgeID");
            var hsEdgeIDVal = new SimpleValHLSL("HS_EdgeID",
                (RealTypeHLSL)hlslContext.EmitType(patchEdgeIDAttr.Type));
            hlslContext.BindAttr(
                patchEdgeIDAttr,
                hsEdgeIDVal );

            var hsPatchEdgesAttr = GetAttribute(outputPatchElement, "HS_PatchEdges");
            var hsPatchEdgesVal = hlslContext.FetchAttr(
                outputPatch,
                hsPatchEdgesAttr.Attribute,
                entryPointSpan );
            hlslContext.BindAttr(hsPatchEdgesAttr, hsPatchEdgesVal);
            var hsPatchEdgeVal = hlslContext.GetElem(
                hsPatchEdgesVal,
                hsEdgeIDVal);
            hlslContext.InitRecord(
                entryPointSpan,
                patchEdgeElement,
                hsPatchEdgeVal);

            var hsEdgeFactorSrcVal = hlslContext.FetchAttr(
                hsPatchEdgeVal,
                GetAttribute(patchEdgeElement, "HS_EdgeFactor").Attribute,
                entryPointSpan);

            var hsEdgeFactorsAttr = GetAttribute(outputPatchElement, "HS_EdgeFactors").Attribute;
            var hsEdgeFactorsVal = hlslContext.FetchAttr(
                outputPatch,
                hsEdgeFactorsAttr,
                entryPointSpan);
            hlslContext.BindAttr(hsEdgeFactorsAttr, hsEdgeFactorsVal);
            var hsEdgeFactorDstVal = hlslContext.GetElem(
                hsEdgeFactorsVal,
                hsEdgeIDVal);
            hlslContext.Assign(
                hsEdgeFactorDstVal,
                hsEdgeFactorSrcVal,
                entryPointSpan);
            entryPointSpan.WriteLine("}");

            var hsPatchInsideCountStr = hlslContext.EmitAttribRef(hsPatchInsideCount, null).ToString();
            var onlyOneInside = hsPatchInsideCountStr == "1";

            if (!onlyOneInside)
            {
                entryPointSpan.WriteLine("for( uint HS_InsideID = 0; HS_InsideID < {0}; HS_InsideID++ )",
                    hlslContext.EmitAttribRef(hsPatchInsideCount, null));
                entryPointSpan.WriteLine("{");
            }
            else
            {
                entryPointSpan.WriteLine("uint HS_InsideID = 0;");
            }

            hlslContext.BindAttr(
                GetAttribute(patchInteriorElement, "__ip2pi"),
                ip2op);

            hlslContext.BindAttr(
                GetAttribute(patchInteriorElement, "__op2pi"),
                outputPatch);

            var hsPatchInsideIDAttr = GetAttribute(patchInteriorElement, "HS_PatchInteriorID");
            var hsInsideIDVal = new SimpleValHLSL("HS_InsideID",
                (RealTypeHLSL)hlslContext.EmitType(hsPatchInsideIDAttr.Type));
            hlslContext.BindAttr(
                hsPatchInsideIDAttr,
                hsInsideIDVal);

            var hsPatchInteriorsAttr = GetAttribute(outputPatchElement, "HS_PatchInteriors");
            var hsPatchInteriorsVal = hlslContext.FetchAttr(
                outputPatch,
                hsPatchInteriorsAttr.Attribute,
                entryPointSpan);
            hlslContext.BindAttr(hsPatchInteriorsAttr, hsPatchInteriorsVal);

            var hsPatchInteriorVal = hlslContext.GetElem(
                hsPatchInteriorsVal,
                hsInsideIDVal);
            hlslContext.InitRecord(
                entryPointSpan,
                patchInteriorElement,
                hsPatchInteriorVal);

            var hsInsideFactorSrcVal = hlslContext.FetchAttr(
                hsPatchInteriorVal,
                GetAttribute(patchInteriorElement, "HS_InsideFactor").Attribute,
                entryPointSpan);

            var hsInsideFactorsAttr = GetAttribute(outputPatchElement, "HS_InsideFactors").Attribute;
            var hsInsideFactorsVal = hlslContext.FetchAttr(
                outputPatch,
                hsInsideFactorsAttr,
                entryPointSpan);
            hlslContext.BindAttr(hsInsideFactorsAttr, hsInsideFactorsVal);
            var hsInsideFactorDstVal = hlslContext.GetElem(
                hsInsideFactorsVal,
                hsInsideIDVal);
            hlslContext.Assign(
                hsInsideFactorDstVal,
                hsInsideFactorSrcVal,
                entryPointSpan);

            if (!onlyOneInside)
            {
                entryPointSpan.WriteLine("}");
            }

            hlslContext.InitRecord(
                entryPointSpan,
                outputPatchElement,
                outputPatch);

            var hsCullPatchVal = hlslContext.EmitAttribRef(hsCullPatchAttr, entryPointSpan);

            entryPointSpan.WriteLine("if( {0} )", hsCullPatchVal);
            entryPointSpan.WriteLine("{");

            var hsEdgeFactor0Val = hlslContext.GetElem(
                hsEdgeFactorsVal,
                new SimpleValHLSL("0", new ScalarTypeHLSL("int")));
            hlslContext.Assign(
                hsEdgeFactor0Val,
                new SimpleValHLSL("0.0f", new ScalarTypeHLSL("float")),
                entryPointSpan);

            entryPointSpan.WriteLine("}");

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

            entryPointSpan.WriteLine("}");

            // ControlPoint entry point

            foreach (var a in inputPatchElement.Attributes)
                hlslContext.UnbindAttribute(a);

            // 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");

            entryPointSpan.WriteLine("[domain(\"{0}\")]",
                hlslContext.EmitAttrLit( tsDomain ));
            entryPointSpan.WriteLine("[partitioning(\"{0}\")]",
                hlslContext.EmitAttrLit( tsPartitioning ));
            entryPointSpan.WriteLine("[outputtopology(\"{0}\")]",
                hlslContext.EmitAttrLit( tsOutputTopology ));
            entryPointSpan.WriteLine("[outputcontrolpoints({0})]",
                hlslContext.EmitAttrLit( outputControlPointCount ));
            entryPointSpan.WriteLine("[patchconstantfunc(\"__patchMain\")]");
            //            entryPointSpan.WriteLine("[maxtessfactor({0:f})]",
            //                hlslContext.EmitAttribRef(
            //                    tsMaxTessFactor,
            //                    null));
            entryPointSpan.WriteLine("{0} main(",
                hlslContext.GenerateConnectorType(controlPointElement));

            first = true;
            hlslContext.DeclareParamAndBind(
                GetAttribute(superPatchElement, "HS_InputCoarseVertices"),
                null,
                ref first,
                entryPointSpan);
            hlslContext.DeclareParamAndBind(
                GetAttribute(superPatchElement, "HS_PatchID"),
                "SV_PrimitiveID",
                ref first,
                entryPointSpan);

            hlslContext.DeclareParamAndBind(
                GetAttribute(controlPointElement, "HS_ControlPointID"),
                "SV_OutputControlPointID",
                ref first,
                entryPointSpan);

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

            hlslContext.EmitTempRecordCtor(
                entryPointSpan,
                inputPatchElement,
                GetAttribute(controlPointElement, "__ip2ocp"));

            var cpOutput = hlslContext.EmitConnectorCtor(
                entryPointSpan,
                controlPointElement);

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

            entryPointSpan.WriteLine("}");

            hlslContext.EmitConstantBufferDecl();

            EmitShaderSetup(
                hlslContext,
                "hs_5_0",
                "Hull",
                "HS");
        }
 public void DeclareAndInitLocalImpl(
     SimpleValHLSL local,
     LitHLSL init,
     Span span)
 {
     span.WriteLine("{0} = {1};",
         local.RealType.DeclareVar(local.Name),
         init);
 }
        public void DeclareAndInitLocalImpl(
            SimpleValHLSL local,
            TupleValHLSL init,
            Span span)
        {
            // If the record has *no* non-void fields, then
            // we shouldn't initialize
            if (!init.FieldVals.Any((fv) => !(fv is VoidValHLSL)))
            {
                span.WriteLine("{0};",
                    local.RealType.DeclareVar(local.Name));
                return;
            }

            span.WriteLine("{0} = {1};",
                local.RealType.DeclareVar(local.Name),
                init);
        }
        /*
        private EmitValHLSL GetFieldImpl(
            SimpleValHLSL objVal,
            IArrayTypeHLSL fieldRep,
            string fieldName,
            int fieldIndex,
            Span span)
        {
            return new ArrayValHLSL(
                string.Format("({0}).{1}", objVal, fieldName),
                fieldRep);
        }
        */
        private EmitValHLSL GetFieldImpl(
            SimpleValHLSL objVal,
            TupleTypeHLSL fieldRep,
            string fieldName,
            int fieldIndex,
            Span span)
        {
            List<EmitValHLSL> fieldFieldVals = new List<EmitValHLSL>();
            int fieldFieldCount = fieldRep.GetFieldCount();
            for (int ff = 0; ff < fieldFieldCount; ++ff)
            {
                var fieldFieldVal = GetField(
                    objVal,
                    fieldRep.GetFieldType(ff),
                    fieldName + fieldRep.GetFieldName(ff),
                    -1,
                    span);
                fieldFieldVals.Add(fieldFieldVal);
            }

            return new TupleValHLSL(
                fieldRep,
                fieldFieldVals);
        }
        private EmitValHLSL GetFieldImpl(
            SimpleValHLSL objVal,
            PseudoArrayTypeHLSL fieldRep,
            string fieldName,
            int fieldIndex,
            Span span)
        {
            var innerVal = GetField(
                objVal,
                fieldRep.ElementType,
                fieldName,
                fieldIndex,
                span);

            return new PseudoArrayValHLSL(
                fieldRep,
                innerVal);
        }
        private EmitValHLSL EmitShaderResourceRef(
            MidBuiltinType type,
            MidVal uniformVal,
            Span span)
        {
            object key = GetUniformValKey(uniformVal);
            EmitValHLSL result = VoidVal;
            if (_uniformResourceCache.TryGetValue(key, out result))
            {
                return result;
            }

            int index = _shaderResources.Count;
            string name = _shared.GenerateName(uniformVal.ToString());

            DeclareFields(
                EmitType(type),
                _resourceHeaderSpan,
                name,
                suffix: string.Format(" : register(t{0})", index));
            _shaderResources.Add(uniformVal);

            result = new SimpleValHLSL(
                name,
                (SimpleTypeHLSL)EmitType(uniformVal.Type));
            _uniformResourceCache[key] = result;
            return result;
        }
 private EmitValHLSL GetFieldImpl(
     SimpleValHLSL objVal,
     RealTypeHLSL fieldType,
     string fieldName,
     int fieldIndex,
     Span span)
 {
     return new SimpleValHLSL(
         string.Format("({0}).{1}", objVal, fieldName),
         fieldType);
 }
 private void DeclareLocalImpl(
     SimpleValHLSL val,
     Span span)
 {
     span.WriteLine("{0};",
         val.RealType.DeclareVar(val.Name));
 }
        private void AssignImpl(
            SimpleValHLSL dest,
            TupleValHLSL src,
            Span span)
        {
            int fieldCount = src.GetFieldCount();
            var aggType = src.AggType;

            for (int ii = 0; ii < fieldCount; ++ii)
            {
                var destField = GetField(
                    dest,
                    aggType.GetFieldType(ii),
                    aggType.GetFieldName(ii),
                    ii,
                    span);
                Assign(
                    destField,
                    src.GetFieldVal(ii),
                    span);
            }
        }
 private void AssignImpl(
     SimpleValHLSL dest,
     SimpleValHLSL src,
     Span span)
 {
     span.WriteLine("{0} = {1};",
         dest,
         src);
 }
        private void AddArgsImpl(
            SimpleValHLSL val,
            ref bool first,
            Span span)
        {
            if (!first)
                span.Write(", ");
            first = false;

            span.Write("{0}", val);
        }
 public EmitValHLSL GetElemImpl(
     SimpleValHLSL obj,
     EmitValHLSL idx)
 {
     return new SimpleValHLSL(
         string.Format("{0}[{1}]", obj, idx),
         ((ArrayTypeBaseHLSL)obj.Type).ElementType);
 }