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