You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

4657 lines
219 KiB

using System;
using System.Collections.Generic;
using UnityEngine.Assertions;
using UnityEditor.ShaderGraph;
using UnityEditor.ShaderGraph.Internal;
namespace UnityEditor.Rendering.HighDefinition
{
// This class manages writing partial derivatives helper funcs.
// 1. It maintains a list of which functions need to be generated.
// 2. When needed, it writes a list of only the function it uses. Since there
// the number of permuations grows exponentially (like swizzle) we need to keep
// the output trimmed otherwise the file size will explode.
// 3. This class also manages writing the shader code to covert to/from the analytic
// and finite versions.
class PartialDerivUtilWriter
{
internal static readonly int kBinaryFuncNum = (int)BinaryFunc.Num;
internal static readonly int kSingleFuncNum = (int)SingleFunc.Num;
internal static readonly int kFunc1Num = (int)Func1.Num;
internal static readonly int kFunc2Num = (int)Func2.Num;
internal static readonly int kFunc3Num = (int)Func3.Num;
internal static readonly int kTexSampleTypeNum = (int)TexSampleType.Num;
internal static readonly int kUvChanNum = (int)8; // is 8 correct?
internal static readonly int kColorChanNum = (int)8; // is 8 correct?
internal bool[] MakeBoolVecAndInitFalse(int num)
{
bool[] ret = new bool[num];
System.Array.Fill(ret, false);
return ret;
}
static internal string GetPrecLower(int prec)
{
return (prec == 1) ? "half" : "float";
}
static internal string GetPrecUpper(int prec)
{
return (prec == 1) ? "Half" : "Float";
}
internal PartialDerivUtilWriter()
{
m_extractFromApd = new BoolDim2[2];
m_mergeToApd = new bool[2][];
m_selectApd = new bool[2][];
m_makeStructFromFpd = new bool[2][];
m_makeStructFromFpdFinite = new bool[2][];
m_splatStructFromScalar = new bool[2][];
m_extractIndexApd = new bool[2][];
m_insertIndexApd = new bool[2][];
m_texSample2d = new bool[2][];
m_texSample2dArray = new bool[2][];
m_texSampleCube = new bool[2][];
m_texSampleCubeArray = new bool[2][];
m_texSample3d = new bool[2][];
m_makeStructDirect = new bool[2][];
m_mulMatVecApd = new bool[2][];
m_mulVecMatApd = new bool[2][];
m_binaryFunc = new BoolDim2[2];
m_singleFunc = new BoolDim2[2];
m_fetchUv = new BoolDim2[2];
m_fetchColor = new BoolDim2[2];
m_func1 = new BoolDim2[2];
m_func2 = new BoolDim2[2];
m_func3 = new BoolDim2[2];
// 6-dimentional, but array total size is only 4096
// type, swizzle length, 0, 1, 2, 3,
m_swizzles = new BoolDim6[2];
m_swizzlesAssign = new BoolDim6[2];
for (int prec = 0; prec < 2; prec++)
{
m_extractFromApd[prec] = new BoolDim2(4, 4);
m_mergeToApd[prec] = MakeBoolVecAndInitFalse(4);
m_selectApd[prec] = MakeBoolVecAndInitFalse(4);
m_makeStructFromFpd[prec] = MakeBoolVecAndInitFalse(4);
m_makeStructFromFpdFinite[prec] = MakeBoolVecAndInitFalse(4);
m_splatStructFromScalar[prec] = MakeBoolVecAndInitFalse(4);
m_extractIndexApd[prec] = MakeBoolVecAndInitFalse(4);
m_insertIndexApd[prec] = MakeBoolVecAndInitFalse(4);
m_makeStructDirect[prec] = MakeBoolVecAndInitFalse(4);
m_mulMatVecApd[prec] = MakeBoolVecAndInitFalse(4);
m_mulVecMatApd[prec] = MakeBoolVecAndInitFalse(4);
m_texSample2d[prec] = MakeBoolVecAndInitFalse(kTexSampleTypeNum);
m_texSample2dArray[prec] = MakeBoolVecAndInitFalse(kTexSampleTypeNum);
m_texSampleCube[prec] = MakeBoolVecAndInitFalse(kTexSampleTypeNum);
m_texSampleCubeArray[prec] = MakeBoolVecAndInitFalse(kTexSampleTypeNum);
m_texSample3d[prec] = MakeBoolVecAndInitFalse(kTexSampleTypeNum);
m_binaryFunc[prec] = new BoolDim2(kBinaryFuncNum, 4);
m_singleFunc[prec] = new BoolDim2(kSingleFuncNum, 4);
m_fetchUv[prec] = new BoolDim2(kUvChanNum, 2);
m_fetchColor[prec] = new BoolDim2(kColorChanNum, 2);
m_func1[prec] = new BoolDim2(kFunc1Num, 4);
m_func2[prec] = new BoolDim2(kFunc2Num, 4);
m_func3[prec] = new BoolDim2(kFunc3Num, 4);
// 6-dimentional, but array total size is only 4096
// type, swizzle length, 0, 1, 2, 3,
m_swizzles[prec] = new BoolDim6(4, 4, 4, 4, 4, 4);
m_swizzlesAssign[prec] = new BoolDim6(4, 4, 4, 4, 4, 4);
}
// src is Apd, dst is Apd, src is float, dst is float, src len, dst len
m_implicitCast = new BoolDim6(2, 2, 2, 2, 4, 4);
}
static bool IsEitherOfStatus(ApdStatus lhs, ApdStatus rhs, ApdStatus status)
{
return (lhs == status) || (rhs == status);
}
static string[] GetSuffixUpper()
{
string[] ret = new string[4] { "X", "Y", "Z", "W" };
return ret;
}
static string[] GetSuffixLower()
{
string[] ret = new string[4] { "x", "y", "z", "w" };
return ret;
}
static string[] GetSuffix(bool isUpper)
{
string[] ret = isUpper ? GetSuffixUpper() : GetSuffixLower();
return ret;
}
static string GetSwizzleName(int numChar, int i0, int i1, int i2, int i3, bool caps)
{
string[] suffixVec = GetSuffix(caps);
int[] list = new int[4]{ i0, i1, i2, i3 };
HlslUtil.ParserAssert(numChar > 0);
string ret = "";
for (int i = 0; i < numChar; i++)
{
int coord = list[i];
ret += suffixVec[coord];
}
return ret;
}
// rules:
// 1. If either is unknown or invalid, result is invalid.
// 2. If both not needed, result is not needed. But if just one is not needed then the result is invalid.
// 3. If both are zero, result is zero.
// 4. If both are valid, or one is valid and the other is zero, then the result is valid.
// 5. That should be all the cases.
static internal ApdStatus MergeStatus(ApdStatus lhs, ApdStatus rhs)
{
if (IsEitherOfStatus(lhs,rhs,ApdStatus.Invalid))
{
return ApdStatus.Invalid;
}
if (IsEitherOfStatus(lhs,rhs,ApdStatus.Unknown))
{
return ApdStatus.Invalid;
}
if (IsEitherOfStatus(lhs,rhs,ApdStatus.NotNeeded))
{
if (lhs == ApdStatus.NotNeeded && rhs == ApdStatus.NotNeeded)
{
return ApdStatus.NotNeeded;
}
else
{
return ApdStatus.Invalid;
}
}
// only options left are zero or valid
if (lhs == ApdStatus.Zero && rhs == ApdStatus.Zero)
{
return ApdStatus.Zero;
}
if (IsEitherOfStatus(lhs,rhs,ApdStatus.Valid))
{
HlslUtil.ParserAssert(lhs == ApdStatus.Valid || lhs == ApdStatus.Zero);
HlslUtil.ParserAssert(rhs == ApdStatus.Valid || rhs == ApdStatus.Zero);
return ApdStatus.Valid;
}
HlslUtil.ParserAssert(false);
return ApdStatus.Invalid;
}
internal static string GetDeclName(int index, ApdStatus apdStatus, ConcretePrecision precision)
{
string ret = "";
if (apdStatus == ApdStatus.Valid)
{
ret = GetApdStructName(index,precision);
}
else
{
ret = GetApdBaseName(index, precision);
}
return ret;
}
internal static string GetApdStructName(int index, ConcretePrecision prec)
{
switch (index)
{
case 0:
return (prec == ConcretePrecision.Single) ? "FloatApd" : "HalfApd";
case 1:
return (prec == ConcretePrecision.Single) ? "FloatApd2" : "HalfApd2";
case 2:
return (prec == ConcretePrecision.Single) ? "FloatApd3" : "HalfApd3";
case 3:
return (prec == ConcretePrecision.Single) ? "FloatApd4" : "HalfApd4";
}
HlslUtil.ParserAssert(false);
return "Invalid";
}
internal static string GetPrecisionName(ConcretePrecision precision)
{
string ret;
switch (precision)
{
case ConcretePrecision.Half:
ret = "half";
break;
case ConcretePrecision.Single:
ret = "float";
break;
default:
HlslUtil.ParserAssert(false);
ret = "<invalid>";
break;
}
return ret;
}
static bool IsVectorType(ConcreteSlotValueType type)
{
bool ret = false;
switch (type)
{
case ConcreteSlotValueType.Vector1:
case ConcreteSlotValueType.Vector2:
case ConcreteSlotValueType.Vector3:
case ConcreteSlotValueType.Vector4:
ret = true;
break;
default:
ret = false;
break;
}
return ret;
}
static ConcreteSlotValueType ParamTypeFromIndex(int index)
{
ConcreteSlotValueType ret = ConcreteSlotValueType.Vector1;
switch (index)
{
case 0:
ret = ConcreteSlotValueType.Vector1;
break;
case 1:
ret = ConcreteSlotValueType.Vector2;
break;
case 2:
ret = ConcreteSlotValueType.Vector3;
break;
case 3:
ret = ConcreteSlotValueType.Vector4;
break;
default:
HlslUtil.ParserAssert(false);
break;
}
return ret;
}
static int IndexFromParamType(ConcreteSlotValueType type)
{
int ret = -1;
switch (type)
{
case ConcreteSlotValueType.Vector1:
ret = 0;
break;
case ConcreteSlotValueType.Vector2:
ret = 1;
break;
case ConcreteSlotValueType.Vector3:
ret = 2;
break;
case ConcreteSlotValueType.Vector4:
ret = 3;
break;
default:
ret = -1;
break;
}
return ret;
}
static string GetApdBaseName(int index, ConcretePrecision precision)
{
string precName = GetPrecisionName(precision);
switch (index)
{
case 0:
return precName;
case 1:
return precName + "2";
case 2:
return precName + "3";
case 3:
return precName + "4";
}
HlslUtil.ParserAssert(false);
return "(invalid)";
}
static string GetApdMatrixName(int index, ConcretePrecision precision)
{
string precName = GetPrecisionName(precision);
switch (index)
{
case 0:
return precName;
case 1:
return precName + "2x2";
case 2:
return precName + "3x3";
case 3:
return precName + "4x4";
}
HlslUtil.ParserAssert(false);
return "(invalid)";
}
private static string GetImplicitCastFuncName(int dstApdVal, int srcApdVal, int dstPrecisionVal, int srcPrecisionVal, int dstChanVal, int srcChanVal)
{
HlslUtil.ParserAssert(srcChanVal >= 0);
HlslUtil.ParserAssert(dstChanVal >= 0);
HlslUtil.ParserAssert(dstApdVal < 2);
HlslUtil.ParserAssert(srcApdVal < 2);
HlslUtil.ParserAssert(dstPrecisionVal < 2);
HlslUtil.ParserAssert(srcPrecisionVal < 2);
HlslUtil.ParserAssert(dstChanVal < 4);
HlslUtil.ParserAssert(srcChanVal < 4);
string dstApdName = (dstApdVal == 0) ? "Fpd" : "Apd";
string srcApdName = (srcApdVal == 0) ? "Fpd" : "Apd";
string dstPrecName = dstPrecisionVal == 0 ? "Half" : "Float";
string srcPrecName = srcPrecisionVal == 0 ? "Half" : "Float";
string dstChanName = (dstChanVal + 1).ToString();
string srcChanName = (srcChanVal + 1).ToString();
string ret = "ImplicitCast" + dstPrecName + dstApdName + dstChanName + "From" + srcPrecName + srcApdName + srcChanName;
return ret;
}
private static void WriteImplicitCastVariationHelper(ShaderStringBuilder builder, int dstApd, int srcApd, int dstPrecision, int srcPrecision, int dstChan, int srcChan)
{
string srcStructName = GetApdStructName(srcChan,(ConcretePrecision)srcPrecision);
string dstStructName = GetApdStructName(dstChan,(ConcretePrecision)dstPrecision);
ConcretePrecision srcPrec = srcPrecision == 0 ? ConcretePrecision.Half : ConcretePrecision.Single;
ConcretePrecision dstPrec = dstPrecision == 0 ? ConcretePrecision.Half : ConcretePrecision.Single;
string srcBaseName = GetApdBaseName(srcChan, srcPrec);
string dstBaseName = GetApdBaseName(dstChan, dstPrec);
string funcName = GetImplicitCastFuncName(dstApd, srcApd, dstPrecision, srcPrecision, dstChan, srcChan);
ApdStatus srcApdStatus = (srcApd == 0) ? ApdStatus.Zero : ApdStatus.Valid;
ApdStatus dstApdStatus = (dstApd == 0) ? ApdStatus.Zero : ApdStatus.Valid;
string srcDeclName = GetDeclName(srcChan, srcApdStatus, srcPrec);
string dstDeclName = GetDeclName(dstChan, dstApdStatus, dstPrec);
ConcreteSlotValueType srcType = ParamTypeFromIndex(srcChan);
ConcreteSlotValueType dstType = ParamTypeFromIndex(dstChan);
builder.AppendLine("{0} {1}({2} src)", dstDeclName, funcName, srcDeclName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", dstDeclName);
string valSuffix = (srcApd == 1) ? ".m_val" : "";
string valLine = ConvertBaseVariable(dstType, dstPrec, srcType, srcPrec, "src" + valSuffix);
if (dstApdStatus == ApdStatus.Valid)
{
string ddxLine;
string ddyLine;
if (srcApdStatus == ApdStatus.Valid)
{
ddxLine = ConvertBaseVariable(dstType, dstPrec, srcType, srcPrec, "src.m_ddx");
ddyLine = ConvertBaseVariable(dstType, dstPrec, srcType, srcPrec, "src.m_ddy");
}
else
{
ddxLine = "0.0";
ddyLine = "0.0";
}
builder.AppendLine("ret.m_val = {0};", valLine);
builder.AppendLine("ret.m_ddx = {0};", ddxLine);
builder.AppendLine("ret.m_ddy = {0};", ddyLine);
}
else
{
builder.AppendLine("ret = {0};", valLine);
}
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
}
internal void ForceGenerateAllDefinitionsAndFuncs()
{
for (int prec = 0; prec < 2; prec++)
{
for (int i = 0; i < 4; i++)
{
for (int funcIter = 0; funcIter < kBinaryFuncNum; funcIter++)
{
m_binaryFunc[prec].Set(funcIter, i, true);
}
for (int funcIter = 0; funcIter < kSingleFuncNum; funcIter++)
{
m_singleFunc[prec].Set(funcIter, i, true);
}
for (int funcIter = 0; funcIter < kFunc1Num; funcIter++)
{
m_func1[prec].Set(funcIter, i, true);
}
for (int funcIter = 0; funcIter < kFunc2Num; funcIter++)
{
if (funcIter == (int)Func2.Dot)
{
m_func2[prec].Set(funcIter, i, true);
}
}
m_func2[prec].Set((int)Func2.Cross, 2, true);
for (int funcIter = 0; funcIter < kFunc3Num; funcIter++)
{
m_func3[prec].Set(funcIter, i, true);
}
}
for (int i = 0; i < 4; i++)
{
m_makeStructFromFpd[prec][i] = true;
m_makeStructFromFpdFinite[prec][i] = true;
m_makeStructDirect[prec][i] = true;
m_mulMatVecApd[prec][i] = true;
m_mulVecMatApd[prec][i] = true;
m_splatStructFromScalar[prec][i] = true;
m_extractIndexApd[prec][i] = true;
m_insertIndexApd[prec][i] = true;
if (i >= 1)
{
m_mergeToApd[prec][i] = true;
}
m_selectApd[prec][i] = true;
for (int funcIter = 0; funcIter < kTexSampleTypeNum; funcIter++)
{
m_texSample2d[prec][funcIter] = true;
m_texSample2dArray[prec][funcIter] = true;
m_texSampleCube[prec][funcIter] = true;
m_texSampleCubeArray[prec][funcIter] = true;
m_texSample3d[prec][funcIter] = true;
}
for (int j = 0; j < 4; j++)
{
if (j <= i)
{
m_extractFromApd[prec].Set(i, j, true);
}
}
}
// generate one random swizzle from each combination of vector size and swizzle length
for (int type = 0; type < 4; type++)
{
for (int swizzleLen = 0; swizzleLen < 4; swizzleLen++)
{
int[] randomVals = new int[4] { 72, 173, 34, 91 };
int[] vals = new int[4];
for (int i = 0; i < 4; i++)
{
// Pick a random value between [0,type]. It's just for debugging,
// so arbitrarily choosing the 4 seeds is fine. Multiply swizzleLen and
// type to add a little variety.
vals[i] = (randomVals[i] + 7 * swizzleLen + 13 * type) % (type + 1);
}
m_swizzles[prec].Set(type, swizzleLen, vals[0], vals[1], vals[2], vals[3], true);
m_swizzlesAssign[prec].Set(type, swizzleLen, vals[0], vals[1], vals[2], vals[3], true);
}
}
}
for (int dstApd = 0; dstApd < 2; dstApd++)
{
for (int srcApd = 0; srcApd < 2; srcApd++)
{
for (int dstPrecision = 0; dstPrecision < 2; dstPrecision++)
{
for (int srcPrecision = 0; srcPrecision < 2; srcPrecision++)
{
for (int dstChan = 0; dstChan < 4; dstChan++)
{
for (int srcChan = 0; srcChan < 4; srcChan++)
{
m_implicitCast.Set(dstApd, srcApd, dstPrecision, srcPrecision, dstChan, srcChan, true);
}
}
}
}
}
}
for (int prec = 0; prec < 2; prec++)
{
for (int i = 0; i < kUvChanNum; i++)
{
for (int j = 0; j < 2; j++)
{
m_fetchUv[prec].Set(i, j, true);
}
}
for (int i = 0; i < kColorChanNum; i++)
{
for (int j = 0; j < 2; j++)
{
m_fetchColor[prec].Set(i, j, true);
}
}
}
}
internal void GenerateDefinitionsAndFuncs(ShaderStringBuilder builder)
{
builder.AppendLine("");
for (int prec = 0; prec < 2; prec++)
{
string precUpper = GetPrecUpper(prec);
string precLower = GetPrecLower(prec);
// generate base structs
for (int i = 0; i < 4; i++)
{
string structName = GetApdStructName(i,(ConcretePrecision)prec);
string baseName = GetApdBaseName(i, (ConcretePrecision)prec);
builder.AppendLine("struct {0}", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} m_val;", baseName);
builder.AppendLine("{0} m_ddx;", baseName);
builder.AppendLine("{0} m_ddy;", baseName);
builder.DecreaseIndent();
builder.AppendLine("};");
builder.AppendLine("");
}
// note that apd funcs only use floats (not halfs)
for (int i = 0; i < 4; i++)
{
string structName = GetApdStructName(i,(ConcretePrecision)prec);
string baseName = GetApdBaseName(i, (ConcretePrecision)prec);
string boolName = "bool" + (i + 1).ToString();
builder.AppendLine("{0} SelectHelper({1} cond, {0} lhs, {0} rhs)", baseName, boolName);
builder.AppendLine("{");
builder.IncreaseIndent();
if (i == 0)
{
builder.AppendLine("return cond ? lhs : rhs;");
}
else
{
builder.AppendLine("{0} ret = 0.0f;", baseName);
for (int j = 0; j <= i; j++)
{
string suffix = GetSuffixLower()[j];
builder.AppendLine("ret.{0} = cond.{0} ? lhs.{0} : rhs.{0};", suffix);
}
builder.AppendLine("return ret;");
}
builder.DecreaseIndent();
builder.AppendLine("};");
builder.AppendLine("");
}
for (int i = 0; i < 4; i++)
{
if (m_makeStructFromFpd[prec][i])
{
string structName = GetApdStructName(i,(ConcretePrecision)prec);
string baseName = GetApdBaseName(i, (ConcretePrecision)prec);
builder.AppendLine("{0} Make{0}({1} src)",structName,baseName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = src;");
builder.AppendLine("ret.m_ddx = 0.0f;");
builder.AppendLine("ret.m_ddy = 0.0f;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
}
}
for (int i = 0; i < 4; i++)
{
if (m_makeStructFromFpdFinite[prec][i])
{
string structName = GetApdStructName(i, (ConcretePrecision)prec);
string baseName = GetApdBaseName(i, (ConcretePrecision)prec);
builder.AppendLine("{0} Make{0}Finite({1} src)", structName, baseName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = src;");
builder.AppendLine("ret.m_ddx = ddx(src);");
builder.AppendLine("ret.m_ddy = ddy(src);");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
}
}
for (int i = 0; i < 4; i++)
{
if (m_makeStructDirect[prec][i])
{
string structName = GetApdStructName(i, (ConcretePrecision)prec);
string baseName = GetApdBaseName(i, (ConcretePrecision)prec);
builder.AppendLine("{0} Make{0}Direct({1} val, {1} derivX, {1} derivY)", structName, baseName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = val;");
builder.AppendLine("ret.m_ddx = derivX;");
builder.AppendLine("ret.m_ddy = derivY;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
}
}
//m_mulMatVecApd[prec][i] = true;
//m_mulVecMatApd[prec][i] = true;
for (int i = 0; i < 4; i++)
{
if (m_mulMatVecApd[prec][i])
{
string structName = GetApdStructName(i, (ConcretePrecision)prec);
string baseName = GetApdBaseName(i, (ConcretePrecision)prec);
string matrixName = GetApdMatrixName(i, (ConcretePrecision)prec);
builder.AppendLine("{0} MulMatVec{0}({1} lhs, {0} rhs)", structName, matrixName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = mul(lhs,rhs.m_val);");
builder.AppendLine("ret.m_ddx = mul(lhs,rhs.m_ddx);");
builder.AppendLine("ret.m_ddy = mul(lhs,rhs.m_ddy);");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
}
}
for (int i = 0; i < 4; i++)
{
if (m_mulVecMatApd[prec][i])
{
string structName = GetApdStructName(i, (ConcretePrecision)prec);
string baseName = GetApdBaseName(i, (ConcretePrecision)prec);
string matrixName = GetApdMatrixName(i, (ConcretePrecision)prec);
builder.AppendLine("{0} MulVecMat{0}({0} lhs, {1} rhs)", structName, matrixName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = mul(lhs.m_val,rhs);");
builder.AppendLine("ret.m_ddx = mul(lhs.m_ddx,rhs);");
builder.AppendLine("ret.m_ddy = mul(lhs.m_ddy,rhs);");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
}
}
for (int i = 0; i < 4; i++)
{
if (m_selectApd[prec][i])
{
string structName = GetApdStructName(i, (ConcretePrecision)prec);
string baseName = GetApdBaseName(i, (ConcretePrecision)prec);
string precName = GetPrecisionName((ConcretePrecision)prec);
builder.AppendLine("{0} Make{0}Select({1} conditional, {2} lhs, {2} rhs)", structName, precName, structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("bool side = (conditional != 0);");
builder.AppendLine("ret.m_val = side ? lhs.m_val : rhs.m_val;");
builder.AppendLine("ret.m_ddx = side ? lhs.m_ddx : rhs.m_ddx;");
builder.AppendLine("ret.m_ddy = side ? lhs.m_ddy : rhs.m_ddy;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
}
}
for (int i = 0; i < 4; i++)
{
if (m_mergeToApd[prec][i])
{
HlslUtil.ParserAssert(i >= 0);
string structName = GetApdStructName(i, (ConcretePrecision)prec);
string baseName = GetApdBaseName(i, (ConcretePrecision)prec);
string startLine = structName + " Merge" + structName + "(";
int numParam = i + 1;
for (int iter = 0; iter < numParam; iter++)
{
if (iter != 0)
{
startLine += ", ";
}
startLine += precUpper + "Apd param" + iter.ToString();
}
startLine += ")";
builder.AppendLine(startLine);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
string dstVal = baseName + "(";
string dstDdx = baseName + "(";
string dstDdy = baseName + "(";
for (int iter = 0; iter < numParam; iter++)
{
if (iter != 0)
{
dstVal += ",";
dstDdx += ",";
dstDdy += ",";
}
string param = "param" + iter.ToString();
dstVal += param + ".m_val";
dstDdx += param + ".m_ddx";
dstDdy += param + ".m_ddy";
}
dstVal += ")";
dstDdx += ")";
dstDdy += ")";
builder.AppendLine("ret.m_val = {0};",dstVal);
builder.AppendLine("ret.m_ddx = {0};", dstDdx);
builder.AppendLine("ret.m_ddy = {0};", dstDdy);
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
}
}
for (int iterType = 0; iterType < 4; iterType++)
{
for (int iterIndex = 0; iterIndex < 4; iterIndex++)
{
if (m_extractFromApd[prec].Get(iterType, iterIndex))
{
HlslUtil.ParserAssert(iterIndex <= iterType);
string structName = GetApdStructName(iterType, (ConcretePrecision)prec);
string baseName = GetApdBaseName(iterType, (ConcretePrecision)prec);
string suffix = GetSuffixLower()[iterIndex];
builder.AppendLine("{0}Apd Extract{1}_{2}({3} src)", precUpper, structName, iterIndex.ToString(), structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0}Apd ret;", precUpper);
builder.AppendLine("ret.m_val = src.m_val.{0};", suffix);
builder.AppendLine("ret.m_ddx = src.m_ddx.{0};", suffix);
builder.AppendLine("ret.m_ddy = src.m_ddy.{0};", suffix);
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
}
}
}
for (int i = 0; i < 4; i++)
{
if (m_splatStructFromScalar[prec][i])
{
string structName = GetApdStructName(i, (ConcretePrecision)prec);
string baseName = GetApdBaseName(i, (ConcretePrecision)prec);
builder.AppendLine("{0} Splat{1}({2}Apd src)", structName, structName,precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = ({0})src.m_val;", baseName);
builder.AppendLine("ret.m_ddx = ({0})src.m_ddx;", baseName);
builder.AppendLine("ret.m_ddy = ({0})src.m_ddy;", baseName);
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
}
}
for (int i = 0; i < 4; i++)
{
if (m_extractIndexApd[prec][i])
{
string structName = GetApdStructName(i, (ConcretePrecision)prec);
string scalarName = GetApdStructName(0, (ConcretePrecision)prec);
// lhs is the vector to insert, index is where to pus it, and rhs is a one channel apd
builder.AppendLine("{1} Extract{0}(inout {0} lhs, int index)", structName, scalarName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", scalarName);
builder.AppendLine("ret.m_val = lhs.m_val[index];");
builder.AppendLine("ret.m_ddx = lhs.m_ddx[index];");
builder.AppendLine("ret.m_ddy = lhs.m_ddy[index];");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
}
}
for (int i = 0; i < 4; i++)
{
if (m_insertIndexApd[prec][i])
{
string structName = GetApdStructName(i, (ConcretePrecision)prec);
string scalarName = GetApdStructName(0, (ConcretePrecision)prec);
// lhs is the vector to insert, index is where to pus it, and rhs is a one channel apd
builder.AppendLine("void Insert{0}(inout {0} lhs, int index, {1} rhs)", structName, scalarName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("lhs.m_val[index] = rhs.m_val;");
builder.AppendLine("lhs.m_ddx[index] = rhs.m_ddx;");
builder.AppendLine("lhs.m_ddy[index] = rhs.m_ddy;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
}
}
for (int type = 0; type < 4; type++)
{
for (int len = 0; len < 4; len++)
{
int numChar = len + 1;
for (int baseI = 0; baseI < 4*4*4*4; baseI++)
{
int i0 = (baseI>>0)%4;
int i1 = (baseI>>2)%4;
int i2 = (baseI>>4)%4;
int i3 = (baseI>>6)%4;
if (m_swizzles[prec].Get(type,len,i0,i1,i2,i3))
{
HlslUtil.ParserAssert(i0 <= type);
HlslUtil.ParserAssert(i1 <= type);
HlslUtil.ParserAssert(i2 <= type);
HlslUtil.ParserAssert(i3 <= type);
string srcStructName = GetApdStructName(type, (ConcretePrecision)prec);
string dstStructName = GetApdStructName(len, (ConcretePrecision)prec);
string srcBaseName = GetApdBaseName(type, (ConcretePrecision)prec);
string dstBaseName = GetApdBaseName(len, (ConcretePrecision)prec);
string capsName = GetSwizzleName(numChar,i0,i1,i2,i3,true);
string lowerName = GetSwizzleName(numChar,i0,i1,i2,i3,false);
builder.AppendLine("{0} Swizzle{1}_{2}({1} src)",dstStructName,srcStructName,capsName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;",dstStructName);
builder.AppendLine("ret.m_val = src.m_val.{0};",lowerName);
builder.AppendLine("ret.m_ddx = src.m_ddx.{0};",lowerName);
builder.AppendLine("ret.m_ddy = src.m_ddy.{0};",lowerName);
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
}
if (m_swizzlesAssign[prec].Get(type, len, i0, i1, i2, i3))
{
HlslUtil.ParserAssert(i0 <= type);
HlslUtil.ParserAssert(i1 <= type);
HlslUtil.ParserAssert(i2 <= type);
HlslUtil.ParserAssert(i3 <= type);
string lhsStructName = GetApdStructName(type, (ConcretePrecision)prec);
string rhsStructName = GetApdStructName(len, (ConcretePrecision)prec);
string lhsBaseName = GetApdBaseName(type, (ConcretePrecision)prec);
string rhsBaseName = GetApdBaseName(len, (ConcretePrecision)prec);
string capsName = GetSwizzleName(numChar, i0, i1, i2, i3, true);
string lowerName = GetSwizzleName(numChar, i0, i1, i2, i3, false);
builder.AppendLine("{1} SwizzleAssign{0}_{2}(inout {0} lhs, {1} rhs)", lhsStructName, rhsStructName, capsName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("lhs.m_val.{0} = rhs.m_val;", lowerName);
builder.AppendLine("lhs.m_ddx.{0} = rhs.m_ddx;", lowerName);
builder.AppendLine("lhs.m_ddy.{0} = rhs.m_ddy;", lowerName);
builder.AppendLine("{0} ret;", rhsStructName);
builder.AppendLine("ret.m_val = lhs.m_val.{0};", lowerName);
builder.AppendLine("ret.m_ddx = lhs.m_ddx.{0};", lowerName);
builder.AppendLine("ret.m_ddy = lhs.m_ddy.{0};", lowerName);
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
}
}
}
}
}
// generate APD version of GetTransformedUV()
{
builder.AppendLine("FloatApd2 GetTransformedUVApd(UnityTexture2D unityTex, FloatApd2 uv)");
builder.AppendLine("{");
builder.IncreaseIndent();
{
builder.AppendLine("FloatApd2 ret;");
builder.AppendLine("ret.m_val = uv.m_val * unityTex.scaleTranslate.xy + unityTex.scaleTranslate.zw;");
builder.AppendLine("ret.m_ddx = uv.m_ddx * unityTex.scaleTranslate.xy;");
builder.AppendLine("ret.m_ddy = uv.m_ddy * unityTex.scaleTranslate.xy;");
builder.AppendLine("return ret;");
}
builder.DecreaseIndent();
builder.AppendLine("}");
}
for (int dstApd = 0; dstApd < 2; dstApd++)
{
for (int srcApd = 0; srcApd < 2; srcApd++)
{
for (int dstPrecision = 0; dstPrecision < 2; dstPrecision++)
{
for (int srcPrecision = 0; srcPrecision < 2; srcPrecision++)
{
for (int dstChan = 0; dstChan < 4; dstChan++)
{
for (int srcChan = 0; srcChan < 4; srcChan++)
{
if (m_implicitCast.Get(dstApd, srcApd, dstPrecision, srcPrecision, dstChan, srcChan))
{
WriteImplicitCastVariationHelper(builder,dstApd, srcApd, dstPrecision, srcPrecision, dstChan, srcChan);
}
}
}
}
}
}
}
for (int prec = 0; prec < 2; prec++)
{
string precUpper = GetPrecUpper(prec);
string precLower = GetPrecLower(prec);
for (int funcIter = 0; funcIter < kSingleFuncNum; funcIter++)
{
for (int i = 0; i < 4; i++)
{
string structName = GetApdStructName(i, (ConcretePrecision)prec);
string baseName = GetApdBaseName(i, (ConcretePrecision)prec);
string boolName = "bool" + (i + 1).ToString();
if (m_singleFunc[prec].Get(funcIter, i))
{
switch ((SingleFunc)funcIter)
{
case SingleFunc.Saturate:
builder.AppendLine("{0} SaturateApd({1} src)", structName, structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} zero = 0.0f;", baseName);
builder.AppendLine("{0} one = 1.0f;", baseName);
builder.AppendLine("{0} cond = (zero <= src.m_val && src.m_val <= one);", boolName);
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = saturate(src.m_val);");
builder.AppendLine("ret.m_ddx = SelectHelper(cond,src.m_ddx,zero);");
builder.AppendLine("ret.m_ddy = SelectHelper(cond,src.m_ddy,zero);");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.Frac:
builder.AppendLine("{0} FracApd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = frac(src.m_val);");
builder.AppendLine("ret.m_ddx = src.m_ddx;");
builder.AppendLine("ret.m_ddy = src.m_ddy;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.Abs:
builder.AppendLine("{0} AbsApd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("float scale = (src.m_val >= 0) ? 1.0f : -1.0f;");
builder.AppendLine("ret.m_val = src.m_val * scale;");
builder.AppendLine("ret.m_ddx = src.m_ddx * scale;");
builder.AppendLine("ret.m_ddy = src.m_ddy * scale;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.Negate:
builder.AppendLine("{0} NegateApd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = -src.m_val;");
builder.AppendLine("ret.m_ddx = -src.m_ddx;");
builder.AppendLine("ret.m_ddy = -src.m_ddy;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.Ceil:
builder.AppendLine("{0} CeilApd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = ceil(src.m_val);");
builder.AppendLine("ret.m_ddx = 0.0;");
builder.AppendLine("ret.m_ddy = 0.0;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.Floor:
builder.AppendLine("{0} FloorApd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = floor(src.m_val);");
builder.AppendLine("ret.m_ddx = 0.0f;");
builder.AppendLine("ret.m_ddy = 0.0f;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.Cos:
builder.AppendLine("{0} CosApd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = cos(src.m_val);");
builder.AppendLine("ret.m_ddx = -sin(src.m_val)*src.m_ddx;");
builder.AppendLine("ret.m_ddy = -sin(src.m_val)*src.m_ddy;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.CosH:
builder.AppendLine("{0} CosHApd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = cosh(src.m_val);");
builder.AppendLine("ret.m_ddx = sinh(src.m_ddx)*src.m_ddx;");
builder.AppendLine("ret.m_ddy = sinh(src.m_ddy)*src.m_ddy;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.Sin:
builder.AppendLine("{0} SinApd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = sin(src.m_val);");
builder.AppendLine("ret.m_ddx = cos(src.m_val)*src.m_ddx;");
builder.AppendLine("ret.m_ddy = cos(src.m_val)*src.m_ddy;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.SinH:
builder.AppendLine("{0} SinHApd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = sinh(src.m_val);");
builder.AppendLine("ret.m_ddx = cosh(src.m_val)*src.m_ddx;");
builder.AppendLine("ret.m_ddy = cosh(src.m_val)*src.m_ddy;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.Tan:
builder.AppendLine("{0} TanApd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("float scale = cos(src.m_val);", structName);
builder.AppendLine("ret.m_val = tan(src.m_val);");
builder.AppendLine("ret.m_ddx = src.m_ddx/(scale * scale);");
builder.AppendLine("ret.m_ddy = src.m_ddy/(scale * scale);");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.TanH:
builder.AppendLine("{0} TanHApd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("float scale = 1-tanh(src.m_val)*tanh(src.m_val);", structName);
builder.AppendLine("ret.m_val = tanh(src.m_val);");
builder.AppendLine("ret.m_ddx = scale*src.m_ddx;");
builder.AppendLine("ret.m_ddy = scale*src.m_ddy;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.Log:
builder.AppendLine("{0} LogApd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = log(src.m_val);");
builder.AppendLine("ret.m_ddx = src.m_ddx/src.m_val;");
builder.AppendLine("ret.m_ddy = src.m_ddy/src.m_val;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.Log2:
builder.AppendLine("{0} Log2Apd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("float logScale = log(2.0f); // natural log of 2.0");
builder.AppendLine("ret.m_val = log2(src.m_val);");
builder.AppendLine("ret.m_ddx = src.m_ddx/(src.m_val*logScale);");
builder.AppendLine("ret.m_ddy = src.m_ddy/(src.m_val*logScale);");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.Log10:
builder.AppendLine("{0} Log10Apd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("float logScale = log(10.0f); // natural log of 10.0");
builder.AppendLine("ret.m_val = log10(src.m_val);");
builder.AppendLine("ret.m_ddx = src.m_ddx/(src.m_val*logScale);");
builder.AppendLine("ret.m_ddy = src.m_ddy/(src.m_val*logScale);");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.Exp:
builder.AppendLine("{0} ExpApd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = exp(src.m_val);");
builder.AppendLine("ret.m_ddx = exp(src.m_val) * src.m_ddx;");
builder.AppendLine("ret.m_ddy = exp(src.m_val) * src.m_ddy;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.Exp2:
builder.AppendLine("{0} Exp2Apd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("float logScale = log(2.0);");
builder.AppendLine("ret.m_val = exp2(src.m_val);");
builder.AppendLine("ret.m_ddx = exp(src.m_val) * src.m_ddx * logScale;");
builder.AppendLine("ret.m_ddy = exp(src.m_val) * src.m_ddy * logScale;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.Rcp:
builder.AppendLine("{0} RcpApd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = rcp(src.m_val);");
builder.AppendLine("ret.m_ddx = (-src.m_ddx) * ret.m_val * ret.m_val;");
builder.AppendLine("ret.m_ddy = (-src.m_ddy) * ret.m_val * ret.m_val;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.Sqrt:
builder.AppendLine("{0} SqrtApd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = sqrt(src.m_val);");
builder.AppendLine("ret.m_ddx = rsqrt(src.m_val) * src.m_ddx;");
builder.AppendLine("ret.m_ddy = rsqrt(src.m_val) * src.m_ddy;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.Rsqrt:
HlslUtil.ParserAssert(m_singleFunc[prec].Get((int)SingleFunc.Sqrt, i));
HlslUtil.ParserAssert(m_singleFunc[prec].Get((int)SingleFunc.Rcp, i));
builder.AppendLine("{0} RsqrtApd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret = RcpApd(SqrtApd(src));", structName);
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case SingleFunc.Sqr:
builder.AppendLine("{0} SqrApd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = src.m_val * src.m_val;");
builder.AppendLine("ret.m_ddx = 2.0f * (src.m_val) * src.m_ddx;");
builder.AppendLine("ret.m_ddy = 2.0f * (src.m_val) * src.m_ddy;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
// handle these funcs later
case SingleFunc.Normalize:
break;
default:
HlslUtil.ParserAssert(false);
break;
}
}
}
}
for (int funcIter = 0; funcIter < kBinaryFuncNum; funcIter++)
{
for (int i = 0; i < 4; i++)
{
string structName = GetApdStructName(i, (ConcretePrecision)prec);
string baseName = GetApdBaseName(i, (ConcretePrecision)prec);
if (m_binaryFunc[prec].Get(funcIter, i))
{
switch ((BinaryFunc)funcIter)
{
case BinaryFunc.Add:
builder.AppendLine("{0} AddApd({0} lhs, {0} rhs)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = lhs.m_val + rhs.m_val;");
builder.AppendLine("ret.m_ddx = lhs.m_ddx + rhs.m_ddx;");
builder.AppendLine("ret.m_ddy = lhs.m_ddy + rhs.m_ddy;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case BinaryFunc.Sub:
builder.AppendLine("{0} SubApd({0} lhs, {0} rhs)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = lhs.m_val - rhs.m_val;");
builder.AppendLine("ret.m_ddx = lhs.m_ddx - rhs.m_ddx;");
builder.AppendLine("ret.m_ddy = lhs.m_ddy - rhs.m_ddy;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case BinaryFunc.Mul:
builder.AppendLine("{0} MulApd({0} lhs, {0} rhs)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = lhs.m_val * rhs.m_val;");
builder.AppendLine("ret.m_ddx = lhs.m_val * rhs.m_ddx + lhs.m_ddx * rhs.m_val;");
builder.AppendLine("ret.m_ddy = lhs.m_val * rhs.m_ddy + lhs.m_ddy * rhs.m_val;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case BinaryFunc.Div:
builder.AppendLine("{0} DivApd({0} lhs, {0} rhs)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = lhs.m_val / rhs.m_val;");
builder.AppendLine("ret.m_ddx = (lhs.m_val * rhs.m_ddx + lhs.m_ddx * rhs.m_val) / (rhs.m_val * rhs.m_val);");
builder.AppendLine("ret.m_ddy = (lhs.m_val * rhs.m_ddy + lhs.m_ddy * rhs.m_val) / (rhs.m_val * rhs.m_val);");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case BinaryFunc.Min:
builder.AppendLine("{0} MinApd({0} lhs, {0} rhs)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = min(lhs.m_val,rhs.m_val);");
builder.AppendLine("ret.m_ddx = lhs.m_val < rhs.m_val ? lhs.m_ddx : rhs.m_ddx;");
builder.AppendLine("ret.m_ddy = lhs.m_val < rhs.m_val ? lhs.m_ddy : rhs.m_ddy;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case BinaryFunc.Max:
builder.AppendLine("{0} MaxApd({0} lhs, {0} rhs)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = max(lhs.m_val,rhs.m_val);");
builder.AppendLine("ret.m_ddx = lhs.m_val > rhs.m_val ? lhs.m_ddx : rhs.m_ddx;");
builder.AppendLine("ret.m_ddy = lhs.m_val > rhs.m_val ? lhs.m_ddy : rhs.m_ddy;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case BinaryFunc.Pow:
// main:
// pow(x,y) = exp(y*ln(x))
//
// ingredients:
// exp'(y) = exp(y)*y'
// log'(y) = y'/y
//
// chain rule:
// dz(pow(x,y)) = dz(exp(y*ln(x)))
// = exp'( (y*ln(x)) ) * dz(y*ln(x))
// = exp'( (y*ln(x)) ) * (dy * ln(x) + y * ln'(x) )
// = exp ( (y*ln(x)) ) * (dy * ln(x) + y * dx/x)
//
builder.AppendLine("{0} PowApd({0} lhs, {0} rhs)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} ret;", structName);
builder.AppendLine("ret.m_val = pow(lhs.m_val,rhs.m_val);");
builder.AppendLine("{0} logLhs = log(lhs.m_val);", baseName);
builder.AppendLine("{0} temp = exp(rhs.m_val * logLhs);", baseName); // this line is actually just pow(x,y)
builder.AppendLine("ret.m_ddx = temp * (rhs.m_ddx * logLhs + rhs.m_val * (lhs.m_ddx/lhs.m_val));");
builder.AppendLine("ret.m_ddy = temp * (rhs.m_ddy * logLhs + rhs.m_val * (lhs.m_ddy/lhs.m_val));");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case BinaryFunc.Reflect:
HlslUtil.ParserAssert(m_func2[prec].Get((int)Func2.Dot, i));
HlslUtil.ParserAssert(m_binaryFunc[prec].Get((int)BinaryFunc.Add, 0));
HlslUtil.ParserAssert(m_binaryFunc[prec].Get((int)BinaryFunc.Mul, 0));
HlslUtil.ParserAssert(m_binaryFunc[prec].Get((int)BinaryFunc.Sub, 0));
HlslUtil.ParserAssert(m_mergeToApd[prec][i]);
HlslUtil.ParserAssert(m_splatStructFromScalar[prec][i]);
builder.AppendLine("{0} ReflectApd({0} lhs, {0} rhs)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0}Apd dotVal = DotApd(lhs,rhs);", precUpper);
builder.AppendLine("{0}Apd dotVal2 = AddApd(dotVal,dotVal);", precUpper);
builder.AppendLine("{0} scale = Splat{0}(dotVal2);", structName);
builder.AppendLine("{0} ret = SubApd(lhs,MulApd(scale,rhs));", structName);
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
default:
HlslUtil.ParserAssert(false);
break;
}
}
}
}
Func1[] funcReorderList = new Func1[4]
{
Func1.LenSqr,
Func1.Len,
Func1.InvLen,
Func1.InvLenSqr
};
// do a few that are used by other functions
for (int funcReorder = 0; funcReorder < funcReorderList.Length; funcReorder++)
{
int funcIter = (int)funcReorderList[funcReorder];
for (int i = 0; i < 4; i++)
{
string structName = GetApdStructName(i, (ConcretePrecision)prec);
string baseName = GetApdBaseName(i, (ConcretePrecision)prec);
if (m_func1[prec].Get((int)funcIter, i))
{
switch ((Func1)funcIter)
{
case Func1.LenSqr:
{
HlslUtil.ParserAssert(m_binaryFunc[prec].Get((int)BinaryFunc.Add, 0));
HlslUtil.ParserAssert(m_singleFunc[prec].Get((int)SingleFunc.Sqr, 0));
for (int debugIter = 0; debugIter <= i; debugIter++)
{
HlslUtil.ParserAssert(m_extractFromApd[prec].Get(i, debugIter));
}
builder.AppendLine("{0}Apd LenSqrApd({1} src)", precUpper, structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0}Apd ret = SqrApd(Extract{1}_0(src));", precUpper, structName);
for (int chan = 1; chan < i+1; chan++)
{
builder.AppendLine("ret = AddApd(ret,SqrApd(Extract{0}_{1}(src)));", structName, i.ToString());
}
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
}
break;
case Func1.Len:
HlslUtil.ParserAssert(m_func1[prec].Get((int)Func1.Len, i));
HlslUtil.ParserAssert(m_singleFunc[prec].Get((int)SingleFunc.Sqrt, 0));
builder.AppendLine("{0}Apd LenApd({1} src)", precUpper, structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0}Apd ret = SqrtApd(LenSqrApd(src));",precUpper);
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case Func1.InvLen:
HlslUtil.ParserAssert(m_func1[prec].Get((int)Func1.LenSqr, i));
HlslUtil.ParserAssert(m_singleFunc[prec].Get((int)SingleFunc.Rsqrt, 0));
builder.AppendLine("{0}Apd InvLenApd({1} src)", precUpper, structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0}Apd ret = RsqrtApd(LenSqrApd(src));",precUpper);
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case Func1.InvLenSqr:
HlslUtil.ParserAssert(m_func1[prec].Get((int)Func1.LenSqr, i));
HlslUtil.ParserAssert(m_singleFunc[prec].Get((int)SingleFunc.Rcp, 0));
builder.AppendLine("{0}Apd InvLenSqrApd({1} src)", precUpper, structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0}Apd ret = RcpApd(LenSqrApd(src));",precUpper);
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
}
}
}
}
for (int funcIter = 0; funcIter < kSingleFuncNum; funcIter++)
{
for (int i = 0; i < 4; i++)
{
string structName = GetApdStructName(i, (ConcretePrecision)prec);
string baseName = GetApdBaseName(i, (ConcretePrecision)prec);
string boolName = "bool" + (i + 1).ToString();
if (m_singleFunc[prec].Get(funcIter, i))
{
switch ((SingleFunc)funcIter)
{
// these are implemented above
case SingleFunc.Saturate:
case SingleFunc.Frac:
case SingleFunc.Log:
case SingleFunc.Log2:
case SingleFunc.Log10:
case SingleFunc.Exp:
case SingleFunc.Rcp:
case SingleFunc.Sqrt:
case SingleFunc.Rsqrt:
case SingleFunc.Sqr:
case SingleFunc.Cos:
case SingleFunc.CosH:
case SingleFunc.Sin:
case SingleFunc.SinH:
case SingleFunc.Tan:
case SingleFunc.TanH:
case SingleFunc.Abs:
case SingleFunc.Negate:
case SingleFunc.Floor:
case SingleFunc.Ceil:
break;
case SingleFunc.Normalize:
HlslUtil.ParserAssert(m_func1[prec].Get((int)Func1.InvLen, i));
HlslUtil.ParserAssert(m_splatStructFromScalar[prec][i]);
HlslUtil.ParserAssert(m_singleFunc[prec].Get((int)BinaryFunc.Mul, i));
builder.AppendLine("{0} NormalizeApd({0} src)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0}Apd invLen = InvLenApd(src);",precUpper);
builder.AppendLine("{0} invLenSplat = Splat{0}(invLen);", structName, structName);
builder.AppendLine("{0} ret = MulApd(invLenSplat,src);", structName);
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
default:
HlslUtil.ParserAssert(false);
break;
}
}
}
}
for (int funcIter = 0; funcIter < kFunc2Num; funcIter++)
{
for (int i = 0; i < 4; i++)
{
string structName = GetApdStructName(i, (ConcretePrecision)prec);
string baseName = GetApdBaseName(i, (ConcretePrecision)prec);
if (m_func2[prec].Get(funcIter, i))
{
switch ((Func2)funcIter)
{
case Func2.Dot:
{
HlslUtil.ParserAssert(m_binaryFunc[prec].Get((int)BinaryFunc.Add, 0));
HlslUtil.ParserAssert(m_binaryFunc[prec].Get((int)BinaryFunc.Mul, 0));
for (int debugIter = 0; debugIter <= i; debugIter++)
{
HlslUtil.ParserAssert(m_extractFromApd[prec].Get(i, debugIter));
}
builder.AppendLine("{0}Apd DotApd({1} lhs, {1} rhs)", precUpper, structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} mulVal = MulApd(lhs,rhs);", structName);
builder.AppendLine("{0}Apd ret = Extract{1}_0(mulVal);", precUpper, structName);
for (int chan = 1; chan <= i; chan++)
{
builder.AppendLine("ret = AddApd(ret,Extract{0}_{1}(mulVal));", structName, i.ToString());
}
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
}
break;
case Func2.Cross:
HlslUtil.ParserAssert(i == 2); // only valid for vec3 data
HlslUtil.ParserAssert(m_binaryFunc[prec].Get((int)BinaryFunc.Add, 0));
HlslUtil.ParserAssert(m_binaryFunc[prec].Get((int)BinaryFunc.Mul, 0));
HlslUtil.ParserAssert(m_binaryFunc[prec].Get((int)BinaryFunc.Sub, 0));
for (int debugIter = 0; debugIter < 3; debugIter++)
{
HlslUtil.ParserAssert(m_extractFromApd[prec].Get(2, debugIter));
}
HlslUtil.ParserAssert(m_mergeToApd[prec][2]);
builder.AppendLine("{0}Apd3 CrossApd({0}Apd3 lhs, {0}Apd3 rhs)", precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0}Apd lhs_x = Extract{0}Apd3_0(lhs);",precUpper);
builder.AppendLine("{0}Apd lhs_y = Extract{0}Apd3_1(lhs);",precUpper);
builder.AppendLine("{0}Apd lhs_z = Extract{0}Apd3_2(lhs);",precUpper);
builder.AppendLine("{0}Apd rhs_x = Extract{0}Apd3_0(rhs);",precUpper);
builder.AppendLine("{0}Apd rhs_y = Extract{0}Apd3_1(rhs);",precUpper);
builder.AppendLine("{0}Apd rhs_z = Extract{0}Apd3_2(rhs);",precUpper);
builder.AppendLine("{0}Apd ret_x = SubApd(MulApd(lhs_y,rhs_z),MulApd(lhs_z,rhs_y));",precUpper);
builder.AppendLine("{0}Apd ret_y = SubApd(MulApd(lhs_z,rhs_x),MulApd(lhs_x,rhs_z));",precUpper);
builder.AppendLine("{0}Apd ret_z = SubApd(MulApd(lhs_x,rhs_y),MulApd(lhs_y,rhs_x));",precUpper);
builder.AppendLine("{0}Apd3 ret = Merge{0}Apd3(ret_x,ret_y,ret_z);",precUpper);
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
default:
HlslUtil.ParserAssert(false);
break;
}
}
}
}
for (int funcIter = 0; funcIter < kFunc3Num; funcIter++)
{
for (int i = 0; i < 4; i++)
{
string structName = GetApdStructName(i, (ConcretePrecision)prec);
string baseName = GetApdBaseName(i, (ConcretePrecision)prec);
if (m_func3[prec].Get(funcIter, i))
{
switch ((Func3)funcIter)
{
case Func3.Lerp:
HlslUtil.ParserAssert(m_binaryFunc[prec].Get((int)BinaryFunc.Add, i));
HlslUtil.ParserAssert(m_binaryFunc[prec].Get((int)BinaryFunc.Mul, i));
HlslUtil.ParserAssert(m_binaryFunc[prec].Get((int)BinaryFunc.Sub, i));
HlslUtil.ParserAssert(m_splatStructFromScalar[prec][i]);
HlslUtil.ParserAssert(m_makeStructFromFpd[prec][i]);
builder.AppendLine("{0} LerpApd({0} lhs, {0} rhs, {0} t)", structName);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0} one = Splat{0}(Make{1}Apd(1.0f));", structName,precUpper);
builder.AppendLine("{0} invT = SubApd(one,t);", structName);
builder.AppendLine("{0} ret = AddApd(MulApd(lhs,invT),MulApd(rhs,t));", structName);
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
default:
HlslUtil.ParserAssert(false);
break;
}
}
}
}
for (int funcIter = 0; funcIter < kTexSampleTypeNum; funcIter++)
{
if (m_texSample2d[prec][funcIter])
{
switch ((TexSampleType)funcIter)
{
case TexSampleType.Lod0:
builder.AppendLine("{0}4 TextureSample2d{1}Lod0(Texture2D tex, SamplerState sam, float2 uv)", precLower,precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("return ({0}4)tex.SampleLevel(sam,uv,0);", precLower);
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case TexSampleType.Fpd:
builder.AppendLine("{0}4 TextureSample2d{1}Fpd(Texture2D tex, SamplerState sam, float2 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("return tex.Sample(sam,uv);");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case TexSampleType.Apd:
builder.AppendLine("{0}4 TextureSample2d{1}Apd(Texture2D tex, SamplerState sam, FloatApd2 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("return tex.SampleGrad(sam,uv.m_val,uv.m_ddx,uv.m_ddy);");
builder.DecreaseIndent();
//builder.AppendLine("return tex.SampleLevel(sam,uv.m_val,0);");
builder.AppendLine("}");
builder.AppendLine("");
break;
case TexSampleType.Apd_3x:
builder.AppendLine("{1}Apd4 TextureSample2d{1}Apd3x(Texture2D tex, SamplerState sam, FloatApd2 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0}4 val0 = tex.SampleGrad(sam,uv.m_val ,uv.m_ddx,uv.m_ddy);", precLower);
builder.AppendLine("{0}4 val1 = tex.SampleGrad(sam,uv.m_val + uv.m_ddx,uv.m_ddx,uv.m_ddy);", precLower);
builder.AppendLine("{0}4 val2 = tex.SampleGrad(sam,uv.m_val + uv.m_ddy,uv.m_ddx,uv.m_ddy);", precLower);
builder.AppendLine("{0}Apd4 ret;", precUpper);
builder.AppendLine("ret.m_val = val0;");
builder.AppendLine("ret.m_ddx = val1 - val0;");
builder.AppendLine("ret.m_ddy = val2 - val0;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
default:
HlslUtil.ParserAssert(false);
break;
}
}
if (m_texSample2dArray[prec][funcIter])
{
switch ((TexSampleType)funcIter)
{
case TexSampleType.Lod0:
builder.AppendLine("{0}4 TextureSample2dArray{1}Lod0(Texture2DArray tex, SamplerState sam, float3 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("return ({0})tex.SampleLevel(sam,uv,0);", precLower);
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case TexSampleType.Fpd:
builder.AppendLine("{0}4 TextureSample2dArray{1}Fpd(Texture2DArray tex, SamplerState sam, float3 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("return tex.Sample(sam,uv);");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case TexSampleType.Apd:
builder.AppendLine("{0}4 TextureSample2dArray{1}Apd(Texture2DArray tex, SamplerState sam, FloatApd3 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("return tex.SampleGrad(sam,uv.m_val,uv.m_ddx.xy,uv.m_ddy.xy);");
builder.DecreaseIndent();
//builder.AppendLine("return tex.SampleLevel(sam,uv.m_val,0);");
builder.AppendLine("}");
builder.AppendLine("");
break;
case TexSampleType.Apd_3x:
builder.AppendLine("{1}Apd4 TextureSample2dArray{1}Apd3x(Texture2DArray tex, SamplerState sam, FloatApd3 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0}4 val0 = tex.SampleGrad(sam,uv.m_val ,uv.m_ddx.xy,uv.m_ddy.xy);", precLower);
builder.AppendLine("{0}4 val1 = tex.SampleGrad(sam,uv.m_val + float3(uv.m_ddx.xy,0),uv.m_ddx.xy,uv.m_ddy.xy);", precLower);
builder.AppendLine("{0}4 val2 = tex.SampleGrad(sam,uv.m_val + float3(uv.m_ddy.xy,0),uv.m_ddx.xy,uv.m_ddy.xy);", precLower);
builder.AppendLine("{0}Apd4 ret;", precUpper);
builder.AppendLine("ret.m_val = val0;");
builder.AppendLine("ret.m_ddx = val1 - val0;");
builder.AppendLine("ret.m_ddy = val2 - val0;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
default:
HlslUtil.ParserAssert(false);
break;
}
}
if (m_texSampleCube[prec][funcIter])
{
switch ((TexSampleType)funcIter)
{
case TexSampleType.Lod0:
builder.AppendLine("{0}4 TextureSampleCube{1}Lod0(TextureCube tex, SamplerState sam, float3 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("return ({0})tex.SampleLevel(sam,uv,0);", precLower);
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case TexSampleType.Fpd:
builder.AppendLine("{0}4 TextureSampleCube{1}Fpd(TextureCube tex, SamplerState sam, float3 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("return tex.Sample(sam,uv);");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case TexSampleType.Apd:
builder.AppendLine("{0}4 TextureSampleCube{1}Apd(TextureCube tex, SamplerState sam, FloatApd3 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("return tex.SampleGrad(sam,uv.m_val,uv.m_ddx,uv.m_ddy);");
builder.DecreaseIndent();
//builder.AppendLine("return tex.SampleLevel(sam,uv.m_val,0);");
builder.AppendLine("}");
builder.AppendLine("");
break;
case TexSampleType.Apd_3x:
builder.AppendLine("{1}Apd4 TextureSampleCube{1}Apd3x(TextureCube tex, SamplerState sam, FloatApd3 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0}4 val0 = tex.SampleGrad(sam,uv.m_val ,uv.m_ddx,uv.m_ddy);", precLower);
builder.AppendLine("{0}4 val1 = tex.SampleGrad(sam,uv.m_val + uv.m_ddx,uv.m_ddx,uv.m_ddy);", precLower);
builder.AppendLine("{0}4 val2 = tex.SampleGrad(sam,uv.m_val + uv.m_ddy,uv.m_ddx,uv.m_ddy);", precLower);
builder.AppendLine("{0}Apd4 ret;", precUpper);
builder.AppendLine("ret.m_val = val0;");
builder.AppendLine("ret.m_ddx = val1 - val0;");
builder.AppendLine("ret.m_ddy = val2 - val0;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
default:
HlslUtil.ParserAssert(false);
break;
}
}
if (m_texSampleCubeArray[prec][funcIter])
{
switch ((TexSampleType)funcIter)
{
case TexSampleType.Lod0:
builder.AppendLine("{0}4 TextureSampleCubeArray{1}Lod0(TextureCubeArray tex, SamplerState sam, float4 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("return ({0})tex.SampleLevel(sam,uv,0);", precLower);
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case TexSampleType.Fpd:
builder.AppendLine("{0}4 TextureSampleCubeArray{1}Fpd(TextureCubeArray tex, SamplerState sam, float4 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("return tex.Sample(sam,uv);");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case TexSampleType.Apd:
builder.AppendLine("{0}4 TextureSampleCubeArray{1}Apd(TextureCubeArray tex, SamplerState sam, FloatApd4 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("return tex.SampleGrad(sam,uv.m_val,uv.m_ddx.xyz,uv.m_ddy.xyz);");
builder.DecreaseIndent();
//builder.AppendLine("return tex.SampleLevel(sam,uv.m_val,0);");
builder.AppendLine("}");
builder.AppendLine("");
break;
case TexSampleType.Apd_3x:
builder.AppendLine("{1}Apd4 TextureSampleCubeArray{1}Apd3x(TextureCubeArray tex, SamplerState sam, FloatApd4 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0}4 val0 = tex.SampleGrad(sam,uv.m_val ,uv.m_ddx.xyz,uv.m_ddy.xyz);", precLower);
builder.AppendLine("{0}4 val1 = tex.SampleGrad(sam,uv.m_val + float4(uv.m_ddx.xyz,0),uv.m_ddx.xyz,uv.m_ddy.xyz);", precLower);
builder.AppendLine("{0}4 val2 = tex.SampleGrad(sam,uv.m_val + float4(uv.m_ddy.xyz,0),uv.m_ddx.xyz,uv.m_ddy.xyz);", precLower);
builder.AppendLine("{0}Apd4 ret;", precUpper);
builder.AppendLine("ret.m_val = val0;");
builder.AppendLine("ret.m_ddx = val1 - val0;");
builder.AppendLine("ret.m_ddy = val2 - val0;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
default:
HlslUtil.ParserAssert(false);
break;
}
}
if (m_texSample3d[prec][funcIter])
{
switch ((TexSampleType)funcIter)
{
case TexSampleType.Lod0:
builder.AppendLine("{0}4 TextureSample3d{1}Lod0(Texture3D tex, SamplerState sam, float3 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("return ({0})tex.SampleLevel(sam,uv,0);", precLower);
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case TexSampleType.Fpd:
builder.AppendLine("{0}4 TextureSample3d{1}Fpd(Texture3D tex, SamplerState sam, float3 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("return tex.Sample(sam,uv);");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
case TexSampleType.Apd:
builder.AppendLine("{0}4 TextureSample3d{1}Apd(Texture3D tex, SamplerState sam, FloatApd3 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("return tex.SampleGrad(sam,uv.m_val,uv.m_ddx,uv.m_ddy);");
builder.DecreaseIndent();
//builder.AppendLine("return tex.SampleLevel(sam,uv.m_val,0);");
builder.AppendLine("}");
builder.AppendLine("");
break;
case TexSampleType.Apd_3x:
builder.AppendLine("{1}Apd4 TextureSample3d{1}Apd3x(Texture3D tex, SamplerState sam, FloatApd3 uv)", precLower, precUpper);
builder.AppendLine("{");
builder.IncreaseIndent();
builder.AppendLine("{0}4 val0 = tex.SampleGrad(sam,uv.m_val ,uv.m_ddx,uv.m_ddy);", precLower);
builder.AppendLine("{0}4 val1 = tex.SampleGrad(sam,uv.m_val + uv.m_ddx,uv.m_ddx,uv.m_ddy);", precLower);
builder.AppendLine("{0}4 val2 = tex.SampleGrad(sam,uv.m_val + uv.m_ddy,uv.m_ddx,uv.m_ddy);", precLower);
builder.AppendLine("{0}Apd4 ret;", precUpper);
builder.AppendLine("ret.m_val = val0;");
builder.AppendLine("ret.m_ddx = val1 - val0;");
builder.AppendLine("ret.m_ddy = val2 - val0;");
builder.AppendLine("return ret;");
builder.DecreaseIndent();
builder.AppendLine("}");
builder.AppendLine("");
break;
default:
HlslUtil.ParserAssert(false);
break;
}
}
}
for (int uvIndex = 0; uvIndex < kUvChanNum; uvIndex++)
{
for (int apdIndex = 0; apdIndex < 2; apdIndex++)
{
if (m_fetchUv[prec].Get(uvIndex, apdIndex))
{
if (apdIndex == 1)
{
// apd
// TODO
}
else
{
// fpd
// TODO
}
}
}
}
}
// todo: color fetch
}
static bool IsFloatType(ConcreteSlotValueType type)
{
switch(type)
{
case ConcreteSlotValueType.Vector1:
case ConcreteSlotValueType.Vector2:
case ConcreteSlotValueType.Vector3:
case ConcreteSlotValueType.Vector4:
return true;
default:
break;
}
return false;
}
static int FloatTypeToIndex(ConcreteSlotValueType type)
{
switch(type)
{
case ConcreteSlotValueType.Boolean:
case ConcreteSlotValueType.Vector1:
return 0;
case ConcreteSlotValueType.Vector2:
return 1;
case ConcreteSlotValueType.Vector3:
return 2;
case ConcreteSlotValueType.Vector4:
return 3;
default:
HlslUtil.ParserAssert(false);
break;
}
return -1;
}
static bool IsFloatTypeNotAny(ConcreteSlotValueType type)
{
switch(type)
{
case ConcreteSlotValueType.Vector1:
case ConcreteSlotValueType.Vector2:
case ConcreteSlotValueType.Vector3:
case ConcreteSlotValueType.Vector4:
return true;
default:
break;
}
return false;
}
static bool IsApdStruct(ApdStatus status)
{
return status == ApdStatus.Valid;
}
internal static bool IsAnyVectorType(ConcreteSlotValueType paramType)
{
bool isAnyVector = (paramType == ConcreteSlotValueType.Vector1 || paramType == ConcreteSlotValueType.Vector2 || paramType == ConcreteSlotValueType.Vector3 || paramType == ConcreteSlotValueType.Vector4);
return isAnyVector;
}
// loose conversion rules. Any float1/2/3/4 to/from any float1/2/3/4
static bool ConvertBaseVariableIsLegal(ConcreteSlotValueType dstParam, ConcreteSlotValueType srcParam)
{
if (dstParam == srcParam)
{
return true;
}
bool ret = false;
switch(dstParam)
{
case ConcreteSlotValueType.Vector1:
case ConcreteSlotValueType.Vector2:
case ConcreteSlotValueType.Vector3:
case ConcreteSlotValueType.Vector4:
ret = IsAnyVectorType(srcParam);
break;
case ConcreteSlotValueType.Matrix4:
case ConcreteSlotValueType.Matrix3:
case ConcreteSlotValueType.Matrix2:
// The only time we can implicitly convert to a matrix is from a float
ret = (srcParam == ConcreteSlotValueType.Vector1);
break;
case ConcreteSlotValueType.SamplerState:
case ConcreteSlotValueType.Texture2D:
case ConcreteSlotValueType.Texture2DArray:
case ConcreteSlotValueType.Texture3D:
case ConcreteSlotValueType.Cubemap:
case ConcreteSlotValueType.Gradient:
case ConcreteSlotValueType.Boolean:
case ConcreteSlotValueType.VirtualTexture:
case ConcreteSlotValueType.PropertyConnectionState:
ret = false;
break;
default:
HlslUtil.ParserAssert(false);
break;
}
return ret;
}
// for now this will always be single precision, but we will need to add half precision as an option
static string ConvertBaseVariable(ConcreteSlotValueType dstParam, ConcretePrecision dstPrecision, ConcreteSlotValueType srcParam, ConcretePrecision srcPrecision, string paramName)
{
bool isValid = ConvertBaseVariableIsLegal(dstParam,srcParam);
if (!isValid)
{
HlslUtil.ParserAssert(isValid);
}
bool isDstMatrix = ShaderTokenUtil.IsMatrixType(dstParam);
bool isDstVector = ShaderTokenUtil.IsVectorType(dstParam);
bool isSrcMatrix = ShaderTokenUtil.IsMatrixType(srcParam);
string ret = "<invalid>";
if (isDstMatrix)
{
// the only type that we can legally convert to a matrix is a scalar, and we can implicitly conver the precision
HlslUtil.ParserAssert(isSrcMatrix || srcParam == ConcreteSlotValueType.Vector1);
ret = paramName;
}
else if (isDstVector)
{
int srcIndex = FloatTypeToIndex(srcParam);
int dstIndex = FloatTypeToIndex(dstParam);
bool needsPrecisionChange = (dstPrecision != srcPrecision);
string dstPrecisionName = GetApdBaseName(dstIndex, dstPrecision);
string castPrefix = needsPrecisionChange ? ("((" + dstPrecisionName + ")") : "";
string castSuffix = needsPrecisionChange ? (")") : "";
string constructorPrefix = dstPrecisionName + "(";
string constructorSuffix = ")";
switch (dstParam)
{
case ConcreteSlotValueType.Vector1:
case ConcreteSlotValueType.Boolean:
if (srcParam == ConcreteSlotValueType.Vector1 || srcParam == ConcreteSlotValueType.Boolean)
{
ret = castPrefix + paramName + castSuffix;
}
else
{
ret = castPrefix + paramName + ".x" + castSuffix;
}
break;
case ConcreteSlotValueType.Vector2:
if (srcParam == ConcreteSlotValueType.Vector2)
{
ret = castPrefix + paramName + castSuffix;
}
else if (srcParam == ConcreteSlotValueType.Vector1 || srcParam == ConcreteSlotValueType.Boolean)
{
//ret = castPrefix + paramName + ".xx" + castSuffix;
ret = castPrefix + paramName + castSuffix;
}
else
{
ret = castPrefix + paramName + ".xy" + castSuffix;
}
break;
case ConcreteSlotValueType.Vector3:
if (srcParam == ConcreteSlotValueType.Vector3)
{
ret = castPrefix + paramName + castSuffix;
}
else if (srcParam == ConcreteSlotValueType.Vector1 || srcParam == ConcreteSlotValueType.Boolean)
{
ret = castPrefix + paramName + castSuffix;
}
else if (srcParam == ConcreteSlotValueType.Vector2)
{
ret = constructorPrefix + paramName + ".x," + paramName + ".y," + "0" + constructorSuffix;
}
else
{
HlslUtil.ParserAssert(srcParam == ConcreteSlotValueType.Vector4);
ret = castPrefix + paramName + ".xyz" + castSuffix;
}
break;
case ConcreteSlotValueType.Vector4:
if (srcParam == ConcreteSlotValueType.Vector4)
{
ret = castPrefix + paramName + castSuffix;
}
else if (srcParam == ConcreteSlotValueType.Vector1 || srcParam == ConcreteSlotValueType.Boolean)
{
//ret = castPrefix + paramName + ".xxxx" + castSuffix;
ret = castPrefix + paramName + castSuffix;
}
else if (srcParam == ConcreteSlotValueType.Vector2)
{
ret = constructorPrefix + paramName + ".x," + paramName + ".y,0,0" + constructorSuffix;
}
else if (srcParam == ConcreteSlotValueType.Vector3)
{
ret = constructorPrefix + paramName + ".x," + paramName + ".y," + paramName + ".z,0" + constructorSuffix;
}
else
{
HlslUtil.ParserAssert(false);
}
break;
default:
HlslUtil.ParserAssert(false);
break;
}
}
else
{
HlslUtil.ParserAssert(srcParam == dstParam);
ret = paramName;
}
return ret;
}
string SplatStructFromScalar(ConcreteSlotValueType dstParam, string paramName, ConcretePrecision precision)
{
int index = FloatTypeToIndex(dstParam);
m_splatStructFromScalar[(int)precision][index] = true;
string structName = GetApdStructName(index,precision);
string adjName = ConvertToSinglePrecision(dstParam, paramName, precision);
string ret = "Splat" + structName + "(" + adjName + ")";
return ret;
}
internal string InsertIndexApd(ConcreteSlotValueType lhsParam, ApdStatus lhsStatus, string lhsName, ConcretePrecision lhsPrecision,
ConcreteSlotValueType rhsParam, ApdStatus rhsStatus, string rhsName, ConcretePrecision rhsPrecision,
string indexName)
{
int index = FloatTypeToIndex(lhsParam);
HlslUtil.ParserAssert(rhsParam == ConcreteSlotValueType.Vector1);
HlslUtil.ParserAssert(lhsStatus == ApdStatus.Valid);
ConcretePrecision dstPrecision = lhsPrecision;
m_insertIndexApd[(int)lhsPrecision][index] = true;
string structName = GetApdStructName(index, lhsPrecision);
string scalarName = GetApdStructName(0, lhsPrecision);
// convert precision if necessary
string rhsAdj = MakeImplicitCast(rhsParam, ApdStatus.Valid, dstPrecision,
rhsParam, rhsStatus, rhsPrecision,
rhsName);
string ret = "Insert" + structName + "(" + lhsName + "," + indexName + "," + rhsAdj + ")";
return ret;
}
internal string ExtractIndexApd(ConcreteSlotValueType lhsParam, string lhsName, ConcretePrecision lhsPrecision,
string indexName)
{
int index = FloatTypeToIndex(lhsParam);
m_extractIndexApd[(int)lhsPrecision][index] = true;
string structName = GetApdStructName(index, lhsPrecision);
string ret = "Extract" + structName + "(" + lhsName + "," + indexName +")";
return ret;
}
// Note that we allow loose conversion rules. Like float2 to float3 and vice versa. We follow standard rules for float1 to float2/3/4 conversions,
// but if we float from a float2/3/4 to a different float2/3/4, we shrink or expand with zeroes.
string ConvertStructVariable(ConcreteSlotValueType dstParam, ConcreteSlotValueType srcParam, string paramName, ConcretePrecision precision)
{
// struct conversions have same legality as base conversions
bool isValid = ConvertBaseVariableIsLegal(dstParam,srcParam);
HlslUtil.ParserAssert(isValid);
int index = FloatTypeToIndex(dstParam);
string structName = GetApdStructName(index, precision);
string ret = "<invalid>";
switch(dstParam)
{
case ConcreteSlotValueType.Vector1:
if (srcParam == ConcreteSlotValueType.Vector1)
{
ret = paramName;
}
else
{
m_makeStructDirect[(int)precision][0] = true;
string funcName = "Make" + structName + "Direct";
ret = funcName + "(" + paramName + ".m_val.x,"+ paramName + ".m_ddx.x," + paramName + ".m_ddy.x)";
}
break;
case ConcreteSlotValueType.Vector2:
if (srcParam == ConcreteSlotValueType.Vector2)
{
ret = paramName;
}
else if (srcParam == ConcreteSlotValueType.Vector1)
{
ret = SplatStructFromScalar(ConcreteSlotValueType.Vector2,paramName,precision);
}
else
{
m_makeStructDirect[(int)precision][1] = true;
string funcName = "Make" + structName + "Direct";
ret = funcName + "(" + paramName + ".m_val.xy," + paramName + ".m_ddx.xy," + paramName + ".m_ddy.xy)";
}
break;
case ConcreteSlotValueType.Vector3:
if (srcParam == ConcreteSlotValueType.Vector3)
{
ret = paramName;
}
else if (srcParam == ConcreteSlotValueType.Vector1)
{
ret = SplatStructFromScalar(ConcreteSlotValueType.Vector3,paramName,precision);
}
else
{
m_makeStructDirect[(int)precision][2] = true;
string funcName = "Make" + structName + "Direct";
if (srcParam == ConcreteSlotValueType.Vector2)
{
ret = funcName + "(float3(" + paramName + ".m_val.xy,0),float3(" + paramName + ".m_ddx.xy,0),float3(" + paramName + ".m_ddy.xy,0))";
}
else if (srcParam == ConcreteSlotValueType.Vector4)
{
ret = funcName + "(" + paramName + ".m_val.xyz," + paramName + ".m_ddx.xyz," + paramName + ".m_ddy.xyz)";
}
else
{
HlslUtil.ParserAssert(false);
}
}
break;
case ConcreteSlotValueType.Vector4:
if (srcParam == ConcreteSlotValueType.Vector4)
{
ret = paramName;
}
else if (srcParam == ConcreteSlotValueType.Vector1)
{
ret = SplatStructFromScalar(ConcreteSlotValueType.Vector4,paramName,precision);
}
else
{
m_makeStructDirect[(int)precision][3] = true;
string funcName = "Make" + structName + "Direct";
if (srcParam == ConcreteSlotValueType.Vector2)
{
ret = funcName + "(float4(" + paramName + ".m_val.xy,0,0),float4(" + paramName + ".m_ddx.xy,0,0),float4(" + paramName + ".m_ddy.xy,0,0))";
}
else if (srcParam == ConcreteSlotValueType.Vector3)
{
ret = funcName + "(float4(" + paramName + ".m_val.xyz,0),float4(" + paramName + ".m_ddx.xyz,0),float4(" + paramName + ".m_ddy.xyz,0))";
}
else
{
HlslUtil.ParserAssert(false);
}
}
break;
case ConcreteSlotValueType.SamplerState:
case ConcreteSlotValueType.Matrix4:
case ConcreteSlotValueType.Matrix3:
case ConcreteSlotValueType.Matrix2:
case ConcreteSlotValueType.Texture2D:
case ConcreteSlotValueType.Texture2DArray:
case ConcreteSlotValueType.Texture3D:
case ConcreteSlotValueType.Cubemap:
case ConcreteSlotValueType.Gradient:
case ConcreteSlotValueType.Boolean:
case ConcreteSlotValueType.VirtualTexture:
case ConcreteSlotValueType.PropertyConnectionState:
HlslUtil.ParserAssert(srcParam == dstParam);
ret = paramName;
break;
default:
HlslUtil.ParserAssert(false);
break;
}
return ret;
}
static string ConvertToSinglePrecision(ConcreteSlotValueType paramType, string paramName, ConcretePrecision precision)
{
int index = FloatTypeToIndex(paramType);
string baseName = GetApdBaseName(index, precision);
string dstParam = (precision == ConcretePrecision.Single) ? paramName : ("(" + baseName + ")" + paramName);
return dstParam;
}
string MakeStructFromFpd(ConcreteSlotValueType dstParam, string paramName, ConcretePrecision precision)
{
int index = FloatTypeToIndex(dstParam);
m_makeStructFromFpd[(int)precision][index] = true;
string structName = GetApdStructName(index,precision);
string baseName = GetApdBaseName(index,precision);
string adjName = ConvertToSinglePrecision(dstParam, paramName, precision);
string ret = "Make" + structName + "(" + adjName + ")";
return ret;
}
internal string MakeImplicitCast(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
ConcreteSlotValueType srcParam, ApdStatus srcStatus, ConcretePrecision srcPrecision,
string srcName)
{
bool isVectorSrc = IsVectorType(srcParam);
bool isVectorDst = IsVectorType(dstParam);
int dstApdVal = (dstStatus == ApdStatus.Valid) ? 1 : 0;
int srcApdVal = (srcStatus == ApdStatus.Valid) ? 1 : 0;
bool bothNotApdValid = (dstApdVal == 0 && srcApdVal == 0);
int dstPrecisionVal = (dstPrecision == ConcretePrecision.Half) ? 0 : 1;
int srcPrecisionVal = (srcPrecision == ConcretePrecision.Half) ? 0 : 1;
int dstChanVal = IndexFromParamType(dstParam);
int srcChanVal = IndexFromParamType(srcParam);
string ret = "";
// Several cases
// 1. If dstChanVal < 0, then it's not a vector/scalar so directly convert and hope for the best.
// Cases like float->int or uint->int will be fine, but texture2d->int will not.
// 2. If dstChanVal >= 0
// a) If srcChanVal >= 0, then do a conversion from vector->vector
// b) If srcChanVal < 0, then convert to float hope that it's legal
if (dstChanVal < 0)
{
ret = srcName;
}
else
{
string name = srcName;
if (srcChanVal < 0)
{
srcChanVal = 0;
srcParam = ConcreteSlotValueType.Vector1;
string baseName = (srcPrecision == ConcretePrecision.Single) ? "float" : "half";
name = "((" + baseName + ")" + srcName + ")";
}
if (dstParam == srcParam && dstApdVal == srcApdVal && dstPrecision == srcPrecision)
{
// special case: everything is the same
ret = name;
}
else if (bothNotApdValid && dstChanVal <= srcChanVal)
{
string castPrefix = "";
string castSuffix = "";
if (srcPrecision != dstPrecision)
{
castPrefix = "((" + GetApdBaseName(dstChanVal, dstPrecision) + ")";
castSuffix = ")";
}
if (srcChanVal == 0 || srcChanVal == dstChanVal)
{
// single channel, so a clean implicit conversion, or same so still clean
ret = castPrefix + name + castSuffix;
}
else
{
// more than one channel, so we need a swizzle
string[] chanSwizzleVec = new string[4] { ".x", ".xy", ".xyz", ".xyzw" };
ret = castPrefix + name + chanSwizzleVec[dstChanVal] + castSuffix;
}
}
else if (srcStatus == ApdStatus.Valid && dstStatus != ApdStatus.Valid)
{
// if we are converting from apd to fpd, just grab the m_val member and then implicitly cast
ret = MakeImplicitCast(dstParam, ApdStatus.Invalid, dstPrecision,
srcParam, ApdStatus.Invalid, srcPrecision,
name + ".m_val");
}
else
{
// otherwise, do the case function
m_implicitCast.Set(dstApdVal, srcApdVal, dstPrecisionVal, srcPrecisionVal, dstChanVal, srcChanVal, true);
ret = GetImplicitCastFuncName(dstApdVal, srcApdVal, dstPrecisionVal, srcPrecisionVal, dstChanVal, srcChanVal) + "(" + name + ")";
}
}
return ret;
}
string MakeStructFromFpdFinite(ConcreteSlotValueType dstParam, string paramName, ConcretePrecision precision)
{
int index = FloatTypeToIndex(dstParam);
m_makeStructFromFpdFinite[(int)precision][index] = true;
string structName = GetApdStructName(index, precision);
string baseName = GetApdBaseName(index, precision);
string adjName = ConvertToSinglePrecision(dstParam, paramName, precision);
string ret = "Make" + structName + "Finite(" + adjName + ")";
return ret;
}
internal string MakeStructFromApdDirect(ConcreteSlotValueType dstParam, string paramName, string paramNameDdx, string paramNameDdy, ConcretePrecision precision)
{
int index = FloatTypeToIndex(dstParam);
m_makeStructDirect[(int)precision][index] = true;
string structName = GetApdStructName(index, precision);
string baseName = GetApdBaseName(index, precision);
string adjName = ConvertToSinglePrecision(dstParam, paramName, precision);
string adjNameDdx = ConvertToSinglePrecision(dstParam, paramNameDdx, precision);
string adjNameDdy = ConvertToSinglePrecision(dstParam, paramNameDdy, precision);
string ret = "Make" + structName + "Direct(" + adjName + "," + adjNameDdx + "," + adjNameDdy + ")";
return ret;
}
internal string ConvertVariable(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision, ConcreteSlotValueType srcParam, ApdStatus srcStatus, ConcretePrecision srcPrecision, string name)
{
bool srcStruct = IsApdStruct(srcStatus);
bool dstStruct = IsApdStruct(dstStatus);
string ret;
if (srcStruct == dstStruct)
{
if (srcStruct)
{
// both are Structs
ret = ConvertStructVariable(dstParam,srcParam,name,dstPrecision);
}
else
{
// both are Base
ret = ConvertBaseVariable(dstParam,dstPrecision,srcParam,srcPrecision,name);
}
}
else
{
if (dstStruct)
{
// convert from base to struct
// 1. convert from srcBase to dstBase
string dstBase = ConvertBaseVariable(dstParam,dstPrecision,srcParam,srcPrecision,name);
// 2. convert from base to struct
ret = MakeStructFromFpd(dstParam,dstBase,dstPrecision);
}
else
{
// convert from struct to base
// 1. convert to base
string dstBase = name + ".m_val";
ret = ConvertBaseVariable(dstParam,dstPrecision,srcParam,srcPrecision,dstBase);
}
}
return ret;
}
// Anytime we have a binary function (like add or subtract) we want to convert both the lhs and rhs to the destination type, and then
// apply the operation. The one exception is the matrix multiplication, where we have a special rule to skip the convertion if the
// original type is a matrix.
internal string ConvertVariableUnlessMatrixMul(BinaryFunc func, ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision, ConcreteSlotValueType srcParam, ApdStatus srcStatus, ConcretePrecision srcPrecision, string name)
{
string ret;
bool isSrcMatrix = ShaderTokenUtil.IsMatrixType(srcParam);
if (func == BinaryFunc.Mul && isSrcMatrix)
{
ret = ConvertVariable(srcParam, dstStatus, dstPrecision, srcParam, srcStatus, srcPrecision, name);
}
else
{
ret = ConvertVariable(dstParam, dstStatus, dstPrecision, srcParam, srcStatus, srcPrecision, name);
}
return ret;
}
internal static ConcreteSlotValueType GetFunc1ReturnType(Func1 func, ConcreteSlotValueType lhsParam)
{
ConcreteSlotValueType ret = ConcreteSlotValueType.Vector1;
switch (func)
{
case Func1.Len:
case Func1.LenSqr:
case Func1.InvLen:
case Func1.InvLenSqr:
ret = ConcreteSlotValueType.Vector1;
break;
default:
HlslUtil.ParserAssert(false);
break;
}
return ret;
}
internal static ConcreteSlotValueType GetFunc2ReturnType(Func2 func, ConcreteSlotValueType lhsParam, ConcreteSlotValueType rhsParam)
{
ConcreteSlotValueType ret = ConcreteSlotValueType.Vector1;
switch (func)
{
case Func2.Dot:
ret = ConcreteSlotValueType.Vector1;
break;
case Func2.Cross:
ret = ConcreteSlotValueType.Vector3;
break;
default:
HlslUtil.ParserAssert(false);
break;
}
return ret;
}
internal static ConcreteSlotValueType GetFunc3ReturnType(Func3 func, ConcreteSlotValueType param0, ConcreteSlotValueType param1, ConcreteSlotValueType param2)
{
ConcreteSlotValueType ret = ConcreteSlotValueType.Vector1;
switch (func)
{
case Func3.Lerp:
ret = GetBinaryOpReturnTypeVector(param0,param1);
break;
default:
HlslUtil.ParserAssert(false);
break;
}
return ret;
}
internal static ConcretePrecision GetBinaryOpPrecisionType(ConcretePrecision lhsPrecision, ConcretePrecision rhsPrecision)
{
if (lhsPrecision == ConcretePrecision.Half && rhsPrecision == ConcretePrecision.Half)
{
return ConcretePrecision.Half;
}
return ConcretePrecision.Single;
}
// binary op return types if both lhs and rhs are float1/2/3/4, but not matrices
internal static ConcreteSlotValueType GetBinaryOpReturnTypeVector(ConcreteSlotValueType lhsParam, ConcreteSlotValueType rhsParam)
{
bool isLhsMat = ShaderTokenUtil.IsMatrixType(lhsParam);
bool isRhsMat = ShaderTokenUtil.IsMatrixType(rhsParam);
bool isLhsScalar = (lhsParam == ConcreteSlotValueType.Vector1);
bool isRhsScalar = (rhsParam == ConcreteSlotValueType.Vector1);
// if one is scalar, and one is matrix, then we can convert, otherwise matrix and vector types are illegal
if (isLhsMat && isRhsScalar)
{
return lhsParam;
}
if (isRhsMat && isLhsScalar)
{
return rhsParam;
}
if (!IsFloatTypeNotAny(lhsParam))
{
HlslUtil.ParserAssert(false);
}
if (!IsFloatTypeNotAny(rhsParam))
{
HlslUtil.ParserAssert(false);
}
// both are the same, so arbitrarily choose lhs
if (lhsParam == rhsParam)
{
return lhsParam;
}
// lhs is scalar, rhs is vector, so return rhs
if (lhsParam == ConcreteSlotValueType.Vector1)
{
return rhsParam;
}
// lhs is vector, rhs is scalar, so return lhs
if (rhsParam == ConcreteSlotValueType.Vector1)
{
return lhsParam;
}
// otherwise, not sure what the right answer is. for now, truncate to the smaller type
ConcreteSlotValueType ret = (ConcreteSlotValueType)Math.Min((int)lhsParam, (int)rhsParam);
return ret;
}
// special logic only for multiply nodes to handle matrix multiplication
internal static ConcreteSlotValueType GetBinaryOpReturnTypeMultiply(ConcreteSlotValueType lhsParam, ConcreteSlotValueType rhsParam)
{
bool isLhsVec = ShaderTokenUtil.IsVectorType(lhsParam);
bool isRhsVec = ShaderTokenUtil.IsVectorType(rhsParam);
bool isLhsMat = ShaderTokenUtil.IsMatrixType(lhsParam);
bool isRhsMat = ShaderTokenUtil.IsMatrixType(rhsParam);
bool isLhsScalar = (lhsParam == ConcreteSlotValueType.Vector1);
bool isRhsScalar = (rhsParam == ConcreteSlotValueType.Vector1);
// only valid types are vector and matrix
HlslUtil.ParserAssert(isLhsVec || isLhsMat);
HlslUtil.ParserAssert(isRhsVec || isRhsMat);
ConcreteSlotValueType ret;
if (isLhsVec && isRhsVec)
{
// both are vectors
ret = GetBinaryOpReturnTypeVector(lhsParam, rhsParam);
}
else if (isLhsMat && isRhsMat)
{
// both are matrices, better be the same size
HlslUtil.ParserAssert(lhsParam == rhsParam);
ret = lhsParam;
}
else if (isLhsMat && isRhsScalar)
{
// lhs is mat, rhs is scalar, so we just go with lhs
ret = lhsParam;
}
else if (isRhsMat && isLhsScalar)
{
// rhs is mat, lhs is scalar, so return rhs
ret = rhsParam;
}
else
{
// one is a matrix, other is vector, which is easy since we only allow square matrices
int lhsRows = ShaderTokenUtil.GetTypeNumRows(lhsParam);
int lhsCols = ShaderTokenUtil.GetTypeNumCols(lhsParam);
int rhsRows = ShaderTokenUtil.GetTypeNumRows(rhsParam);
int rhsCols = ShaderTokenUtil.GetTypeNumCols(rhsParam);
int lowDim = Math.Min(Math.Min(lhsRows, lhsCols), Math.Min(rhsRows, rhsCols));
int highDim = Math.Max(Math.Max(lhsRows, lhsCols), Math.Max(rhsRows, rhsCols));
HlslUtil.ParserAssert(lowDim == 1);
HlslUtil.ParserAssert(highDim > 1);
ret = ShaderTokenUtil.GetVectorTypeFromNumCols(highDim);
}
return ret;
}
internal static ConcreteSlotValueType GetBinaryOpReturnTypeAddSub(ConcreteSlotValueType lhsParam, ConcreteSlotValueType rhsParam)
{
bool isLhsVec = ShaderTokenUtil.IsVectorType(lhsParam);
bool isRhsVec = ShaderTokenUtil.IsVectorType(rhsParam);
bool isLhsMat = ShaderTokenUtil.IsMatrixType(lhsParam);
bool isRhsMat = ShaderTokenUtil.IsMatrixType(rhsParam);
// only valid types are vector and matrix
HlslUtil.ParserAssert(isLhsVec || isLhsMat);
HlslUtil.ParserAssert(isRhsVec || isRhsMat);
ConcreteSlotValueType ret;
if (isLhsVec && isRhsVec)
{
// both are vectors
ret = GetBinaryOpReturnTypeVector(lhsParam, rhsParam);
}
else
{
// if one is not a vector, then they must be the same type. we could add logic
// for other cases if we wanted to (like adding a Matrix4 with a scalar constant),
// but it's forbidden for now.
HlslUtil.ParserAssert(lhsParam == rhsParam);
ret = lhsParam;
}
return ret;
}
internal static ConcreteSlotValueType GetBinaryOpReturnType(BinaryFunc func, ConcreteSlotValueType lhsParam, ConcreteSlotValueType rhsParam)
{
ConcreteSlotValueType ret;
if (func == BinaryFunc.Mul)
{
ret = GetBinaryOpReturnTypeMultiply(lhsParam, rhsParam);
}
else
{
ret = GetBinaryOpReturnTypeVector(lhsParam, rhsParam);
}
return ret;
}
internal string MakeBinaryFunc(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
ConcreteSlotValueType lhsParam, ApdStatus lhsStatus, ConcretePrecision lhsPrecision, string lhsName,
ConcreteSlotValueType rhsParam, ApdStatus rhsStatus, ConcretePrecision rhsPrecision, string rhsName,
BinaryFunc func)
{
ConcreteSlotValueType funcParam = dstParam;//GetBinaryOpReturnType(lhsParam,rhsParam);
bool isDstStruct = IsApdStruct(dstStatus);
ConcretePrecision expectedDstPrecision = GetBinaryOpPrecisionType(lhsPrecision, rhsPrecision);
HlslUtil.ParserAssert(expectedDstPrecision == dstPrecision);
string ret;
if (isDstStruct)
{
// apd version
bool isMatrixLhs = ShaderTokenUtil.IsMatrixType(lhsParam);
bool isMatrixRhs = ShaderTokenUtil.IsMatrixType(rhsParam);
int dstIndex = FloatTypeToIndex(dstParam);
if (isMatrixLhs || isMatrixRhs)
{
// matrix operations for analytic derivatives should only happen for mul operations
HlslUtil.ParserAssert(func == BinaryFunc.Mul);
// only one of the two should be a matrix
HlslUtil.ParserAssert(!isMatrixLhs || !isMatrixRhs);
string structName = GetApdStructName(dstIndex, dstPrecision);
if (isMatrixLhs)
{
// matrix is on left side
string rhsVariable = ConvertVariable(funcParam, dstStatus, dstPrecision, rhsParam, rhsStatus, rhsPrecision, rhsName);
m_mulMatVecApd[(int)dstPrecision][dstIndex] = true;
string funcName = "MulMatVec" + structName;
ret = funcName + "(" + lhsName + "," + rhsVariable + ")";
}
else
{
// matrix is on right side
string lhsVariable = ConvertVariable(funcParam, dstStatus, dstPrecision, lhsParam, lhsStatus, lhsPrecision, lhsName);
m_mulVecMatApd[(int)dstPrecision][dstIndex] = true;
string funcName = "MulVecMat" + structName;
ret = funcName + "(" + lhsVariable + "," + rhsName + ")";
}
}
else
{
// get both versions as apd
string lhsVal = ConvertVariable(funcParam, dstStatus, dstPrecision, lhsParam, lhsStatus, lhsPrecision, lhsName);
string rhsVal = ConvertVariable(funcParam, dstStatus, dstPrecision, rhsParam, rhsStatus, rhsPrecision, rhsName);
int funcTypeIndex = FloatTypeToIndex(funcParam);
m_binaryFunc[(int)dstPrecision].Set((int)func, funcTypeIndex, true);
string mergedOp;
switch (func)
{
case BinaryFunc.Add:
mergedOp = "AddApd(" + lhsVal + "," + rhsVal + ")";
break;
case BinaryFunc.Sub:
mergedOp = "SubApd(" + lhsVal + "," + rhsVal + ")";
break;
case BinaryFunc.Mul:
mergedOp = "MulApd(" + lhsVal + "," + rhsVal + ")";
break;
case BinaryFunc.Div:
mergedOp = "DivApd(" + lhsVal + "," + rhsVal + ")";
break;
case BinaryFunc.Min:
mergedOp = "MinApd(" + lhsVal + "," + rhsVal + ")";
break;
case BinaryFunc.Max:
mergedOp = "MaxApd(" + lhsVal + "," + rhsVal + ")";
break;
case BinaryFunc.Pow:
mergedOp = "PowApd(" + lhsVal + "," + rhsVal + ")";
break;
case BinaryFunc.Reflect:
mergedOp = "ReflectApd(" + lhsVal + "," + rhsVal + ")";
break;
default:
mergedOp = "<invalid>";
HlslUtil.ParserAssert(false);
break;
}
ret = ConvertVariable(dstParam, dstStatus, dstPrecision, funcParam, dstStatus, dstPrecision, mergedOp);
}
}
else
{
// first, get both variables as base
string lhsVal = ConvertVariableUnlessMatrixMul(func,funcParam,dstStatus,dstPrecision,lhsParam,lhsStatus, lhsPrecision, lhsName);
string rhsVal = ConvertVariableUnlessMatrixMul(func,funcParam,dstStatus,dstPrecision,rhsParam,rhsStatus,rhsPrecision,rhsName);
string mergedOp;
switch(func)
{
case BinaryFunc.Add:
mergedOp = "(" + lhsVal + "+" + rhsVal + ")";
break;
case BinaryFunc.Sub:
mergedOp = "(" + lhsVal + "-" + rhsVal + ")";
break;
case BinaryFunc.Mul:
{
bool isLhsVec = ShaderTokenUtil.IsVectorType(lhsParam);
bool isRhsVec = ShaderTokenUtil.IsVectorType(rhsParam);
if (isLhsVec && isRhsVec)
{
mergedOp = "(" + lhsVal + "*" + rhsVal + ")";
}
else
{
mergedOp = "mul(" + lhsVal + "," + rhsVal + ")";
}
}
break;
case BinaryFunc.Div:
mergedOp = "(" + lhsVal + "/" + rhsVal + ")";
break;
case BinaryFunc.Min:
mergedOp = "min(" + lhsVal + "," + rhsVal + ")";
break;
case BinaryFunc.Max:
mergedOp = "max(" + lhsVal + "," + rhsVal + ")";
break;
case BinaryFunc.Pow:
mergedOp = "pow(" + lhsVal + "," + rhsVal + ")";
break;
case BinaryFunc.Reflect:
mergedOp = "reflect(" + lhsVal + "," + rhsVal + ")";
break;
default:
mergedOp = "<invalid>";
HlslUtil.ParserAssert(false);
break;
}
ret = ConvertVariable(dstParam,dstStatus,dstPrecision,funcParam,dstStatus, dstPrecision, mergedOp);
}
return ret;
}
internal string MakeSingleFunc(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
ConcreteSlotValueType srcParam, ApdStatus srcStatus, ConcretePrecision srcPrecision, string srcName,
SingleFunc func)
{
ConcreteSlotValueType funcParam = dstParam;
bool isDstStruct = IsApdStruct(dstStatus);
string ret;
if (isDstStruct)
{
// apd version
// get both versions as apd
string srcVal = ConvertVariable(funcParam, dstStatus, dstPrecision, srcParam, srcStatus, srcPrecision, srcName);
int prec = (int)dstPrecision;
int funcTypeIndex = FloatTypeToIndex(funcParam);
m_singleFunc[prec].Set((int)func, funcTypeIndex, true);
string mergedOp;
switch (func)
{
case SingleFunc.Saturate:
mergedOp = "SaturateApd(" + srcVal + ")";
break;
case SingleFunc.Rcp:
mergedOp = "RcpApd(" + srcVal + ")";
break;
case SingleFunc.Sqr:
mergedOp = "SqrApd(" + srcVal + ")";
break;
case SingleFunc.Log:
mergedOp = "LogApd(" + srcVal + ")";
break;
case SingleFunc.Log2:
mergedOp = "Log2Apd(" + srcVal + ")";
break;
case SingleFunc.Log10:
mergedOp = "Log10Apd(" + srcVal + ")";
break;
case SingleFunc.Exp:
mergedOp = "ExpApd(" + srcVal + ")";
break;
case SingleFunc.Exp2:
mergedOp = "Exp2Apd(" + srcVal + ")";
break;
case SingleFunc.Sqrt:
mergedOp = "SqrtApd(" + srcVal + ")";
break;
case SingleFunc.Rsqrt:
m_singleFunc[prec].Set((int)SingleFunc.Sqrt, 0, true);
m_singleFunc[prec].Set((int)SingleFunc.Rcp, 0, true);
mergedOp = "RsqrtApd(" + srcVal + ")";
break;
case SingleFunc.Normalize:
SetLenSqrDependencies(funcTypeIndex, dstPrecision);
m_func1[prec].Set((int)Func1.InvLen, funcTypeIndex, true);
m_singleFunc[prec].Set((int)SingleFunc.Rsqrt, 0,true);
m_singleFunc[prec].Set((int)SingleFunc.Sqrt, 0, true);
m_singleFunc[prec].Set((int)SingleFunc.Rcp, 0, true);
m_splatStructFromScalar[(int)dstPrecision][funcTypeIndex] = true;
m_singleFunc[(int)dstPrecision].Set((int)BinaryFunc.Mul, funcTypeIndex, true);
mergedOp = "NormalizeApd(" + srcVal + ")";
break;
case SingleFunc.Frac:
mergedOp = "FracApd(" + srcVal + ")";
break;
case SingleFunc.Cos:
mergedOp = "CosApd(" + srcVal + ")";
break;
case SingleFunc.CosH:
mergedOp = "CosHApd(" + srcVal + ")";
break;
case SingleFunc.Sin:
mergedOp = "SinApd(" + srcVal + ")";
break;
case SingleFunc.SinH:
mergedOp = "SinHApd(" + srcVal + ")";
break;
case SingleFunc.Tan:
mergedOp = "TanApd(" + srcVal + ")";
break;
case SingleFunc.TanH:
mergedOp = "TanHApd(" + srcVal + ")";
break;
case SingleFunc.Abs:
mergedOp = "AbsApd(" + srcVal + ")";
break;
case SingleFunc.Negate:
mergedOp = "NegateApd(" + srcVal + ")";
break;
case SingleFunc.Floor:
mergedOp = "FloorApd(" + srcVal + ")";
break;
case SingleFunc.Ceil:
mergedOp = "CeilApd(" + srcVal + ")";
break;
default:
mergedOp = "<invalid>";
HlslUtil.ParserAssert(false);
break;
}
ret = ConvertVariable(dstParam, dstStatus, dstPrecision, funcParam, dstStatus, dstPrecision, mergedOp);
}
else
{
// regular fpd version
// first, get both variables as base
string srcVal = ConvertVariable(funcParam, dstStatus, dstPrecision, srcParam, srcStatus, srcPrecision, srcName);
string mergedOp;
switch (func)
{
case SingleFunc.Saturate:
mergedOp = "saturate(" + srcVal + ")";
break;
case SingleFunc.Rcp:
mergedOp = "rcp(" + srcVal + ")";
break;
case SingleFunc.Sqr:
mergedOp = "((" + srcVal + ")*(" + srcVal + "))";
break;
case SingleFunc.Log:
mergedOp = "log(" + srcVal + ")";
break;
case SingleFunc.Log2:
mergedOp = "log2(" + srcVal + ")";
break;
case SingleFunc.Log10:
mergedOp = "log10(" + srcVal + ")";
break;
case SingleFunc.Exp:
mergedOp = "exp(" + srcVal + ")";
break;
case SingleFunc.Exp2:
mergedOp = "exp2(" + srcVal + ")";
break;
case SingleFunc.Sqrt:
mergedOp = "sqrt(" + srcVal + ")";
break;
case SingleFunc.Rsqrt:
mergedOp = "rcp(sqrt(" + srcVal + "))";
break;
case SingleFunc.Normalize:
mergedOp = "normalize(" + srcVal + ")";
break;
case SingleFunc.Frac:
mergedOp = "frac(" + srcVal + ")";
break;
case SingleFunc.Cos:
mergedOp = "cos(" + srcVal + ")";
break;
case SingleFunc.CosH:
mergedOp = "cosh(" + srcVal + ")";
break;
case SingleFunc.Sin:
mergedOp = "sin(" + srcVal + ")";
break;
case SingleFunc.SinH:
mergedOp = "sinh(" + srcVal + ")";
break;
case SingleFunc.Tan:
mergedOp = "tan(" + srcVal + ")";
break;
case SingleFunc.TanH:
mergedOp = "tanh(" + srcVal + ")";
break;
case SingleFunc.Abs:
mergedOp = "abs(" + srcVal + ")";
break;
case SingleFunc.Negate:
mergedOp = "(-(" + srcVal + "))";
break;
case SingleFunc.Floor:
mergedOp = "floor(" + srcVal + ")";
break;
case SingleFunc.Ceil:
mergedOp = "ceil(" + srcVal + ")";
break;
default:
mergedOp = "<invalid>";
HlslUtil.ParserAssert(false);
break;
}
ret = ConvertVariable(dstParam, dstStatus, dstPrecision, funcParam, dstStatus, dstPrecision, mergedOp);
}
return ret;
}
// this is common enough that it needs a helper function
void SetLenSqrDependencies(int funcTypeIndex, ConcretePrecision dstPrecision)
{
int prec = (int)dstPrecision;
m_func1[prec].Set((int)Func1.LenSqr, funcTypeIndex, true);
m_binaryFunc[prec].Set((int)BinaryFunc.Add, 0, true);
m_singleFunc[prec].Set((int)SingleFunc.Sqr, 0, true);
for (int iter = 0; iter <= funcTypeIndex; iter++)
{
m_extractFromApd[prec].Set(funcTypeIndex, iter, true);
}
}
internal string MakeFunc1(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
ConcreteSlotValueType srcParam, ApdStatus srcStatus, ConcretePrecision srcPrecision, string srcName,
Func1 func)
{
ConcreteSlotValueType funcParam = dstParam;
bool isDstStruct = IsApdStruct(dstStatus);
ConcreteSlotValueType expectedDstType = GetFunc1ReturnType(func, srcParam);
HlslUtil.ParserAssert(dstParam == expectedDstType);
string ret;
if (isDstStruct)
{
// apd version
// convert precision and apd but preserve type
string srcVal = ConvertVariable(srcParam, dstStatus, dstPrecision, srcParam, srcStatus, srcPrecision, srcName);
int prec = (int)dstPrecision;
int funcTypeIndex = FloatTypeToIndex(srcParam);
m_func1[prec].Set((int)func, funcTypeIndex, true);
// all of these functions requires LenSqr() and it's dependencies (add, sqr, and extract)
SetLenSqrDependencies(funcTypeIndex,dstPrecision);
string mergedOp;
switch (func)
{
case Func1.LenSqr:
mergedOp = "LenSqrApd(" + srcVal + ")";
break;
case Func1.Len:
m_singleFunc[prec].Set((int)SingleFunc.Sqrt, 0, true);
mergedOp = "LenApd(" + srcVal + ")";
break;
case Func1.InvLen:
m_singleFunc[prec].Set((int)SingleFunc.Sqrt, 0, true);
m_singleFunc[prec].Set((int)SingleFunc.Rcp, 0, true);
m_singleFunc[prec].Set((int)SingleFunc.Rsqrt, 0, true);
mergedOp = "InvLenApd(" + srcVal + ")";
break;
case Func1.InvLenSqr:
m_singleFunc[prec].Set((int)SingleFunc.Rcp, 0, true);
mergedOp = "InvLenSqrApd(" + srcVal + ")";
break;
default:
mergedOp = "<invalid>";
HlslUtil.ParserAssert(false);
break;
}
ret = mergedOp;
}
else
{
// regular fpd version
// first, get both variables as base
string srcVal = ConvertVariable(srcParam, dstStatus, dstPrecision, srcParam, srcStatus, srcPrecision, srcName);
string mergedOp;
switch (func)
{
case Func1.Len:
mergedOp = "length(" + srcVal + ")";
break;
case Func1.LenSqr:
mergedOp = "dot(" + srcVal + "," + srcVal + ")";
break;
case Func1.InvLen:
mergedOp = "rcp(length(" + srcVal + "))";
break;
case Func1.InvLenSqr:
mergedOp = "rcp(dot(" + srcVal + "," + srcVal + "))"; ;
break;
default:
mergedOp = "<invalid>";
HlslUtil.ParserAssert(false);
break;
}
ret = mergedOp;
}
return ret;
}
internal string MakeFunc2(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
ConcreteSlotValueType param0, ApdStatus status0, ConcretePrecision precision0, string name0,
ConcreteSlotValueType param1, ApdStatus status1, ConcretePrecision precision1, string name1,
Func2 func)
{
string ret;
switch (func)
{
case Func2.Dot:
ret = MakeDot(dstParam, dstStatus, dstPrecision,
param0, status0, precision0, name0,
param1, status1, precision1, name1);
break;
case Func2.Cross:
ret = MakeCross(dstParam, dstStatus, dstPrecision,
param0, status0, precision0, name0,
param1, status1, precision1, name1);
break;
default:
HlslUtil.ParserAssert(false);
ret = "<invalid>";
break;
}
return ret;
}
internal string MakeFunc3(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
ConcreteSlotValueType param0, ApdStatus status0, ConcretePrecision precision0, string name0,
ConcreteSlotValueType param1, ApdStatus status1, ConcretePrecision precision1, string name1,
ConcreteSlotValueType param2, ApdStatus status2, ConcretePrecision precision2, string name2,
Func3 func)
{
string ret;
switch (func)
{
case Func3.Lerp:
ret = MakeLerp(dstParam, dstStatus, dstPrecision,
param0, status0, precision0, name0,
param1, status1, precision1, name1,
param2, status2, precision2, name2);
break;
default:
HlslUtil.ParserAssert(false);
ret = "<invalid>";
break;
}
return ret;
}
internal string MakeComparison(
ComparisonType comparison,
ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
ConcreteSlotValueType param0, ApdStatus status0, ConcretePrecision precision0, string name0,
ConcreteSlotValueType param1, ApdStatus status1, ConcretePrecision precision1, string name1)
{
HlslUtil.ParserAssert(dstParam == ConcreteSlotValueType.Boolean);
HlslUtil.ParserAssert(dstStatus == ApdStatus.Zero);
string op = "<invalid>";
switch (comparison)
{
case ComparisonType.Equal:
op = "==";
break;
case ComparisonType.NotEqual:
op = "!=";
break;
case ComparisonType.Less:
op = "<";
break;
case ComparisonType.LessOrEqual:
op = "<=";
break;
case ComparisonType.Greater:
op = ">";
break;
case ComparisonType.GreaterOrEqual:
op = ">=";
break;
default:
HlslUtil.ParserAssert(false);
break;
}
// convert both types to scalars
string lhsName = ConvertVariable(ConcreteSlotValueType.Vector1, ApdStatus.Zero, dstPrecision, param0, status0, precision0, name0);
string rhsName = ConvertVariable(ConcreteSlotValueType.Vector1, ApdStatus.Zero, dstPrecision, param1, status1, precision1, name1);
string ret = "(" + lhsName + " " + op + " " + rhsName + ") ? 1.0f : 0.0f";
return ret;
}
string AsStruct(ConcreteSlotValueType srcParam, ApdStatus srcStatus, ConcretePrecision srcPrecision, string paramName)
{
bool isSrcStruct = IsApdStruct(srcStatus);
string ret = paramName;
if (!isSrcStruct)
{
ret = MakeStructFromFpd(srcParam,paramName,srcPrecision);
}
return ret;
}
string AsBase(ConcreteSlotValueType srcParam, ApdStatus srcStatus, string paramName)
{
bool isSrcStruct = IsApdStruct(srcStatus);
string ret = paramName;
if (isSrcStruct)
{
ret = paramName + ".m_val";
}
return ret;
}
string ExtractIndexApd(ConcreteSlotValueType srcParam, ConcretePrecision prec, int index, string paramName)
{
string dstName;
// early out, if the struct is a float1, and we are returning the first index, just return the source
if (srcParam == ConcreteSlotValueType.Vector1 && index == 0)
{
dstName = paramName;
}
else
{
int typeIndex = FloatTypeToIndex(srcParam);
m_extractFromApd[(int)prec].Set(typeIndex, index, true);
string structName = GetApdStructName(typeIndex, prec);
dstName = "Extract" + structName + "_" + index.ToString() + "(" + paramName + ")";
}
return dstName;
}
string MergeApd2(ConcretePrecision precision, string name0, string name1)
{
string precUpper = GetPrecUpper((int)precision);
m_mergeToApd[(int)precision][1] = true;
string ret = "Merge" + precUpper + "Apd2(" + name0 + "," + name1 + ")";
return ret;
}
string MergeApd3(ConcretePrecision precision, string name0, string name1, string name2)
{
string precUpper = GetPrecUpper((int)precision);
m_mergeToApd[(int)precision][2] = true;
string ret = "Merge" + precUpper + "Apd3(" + name0 + "," + name1 + "," + name2 + ")";
return ret;
}
string MergeApd4(ConcretePrecision precision, string name0, string name1, string name2, string name3)
{
string precUpper = GetPrecUpper((int)precision);
m_mergeToApd[(int)precision][3] = true;
string ret = "Merge" + precUpper + "Apd4(" + name0 + "," + name1 + "," + name2 + "," + name3 + ")";
return ret;
}
string NormalizeApd(ConcreteSlotValueType param, ConcretePrecision precision, string name)
{
int index = FloatTypeToIndex(param);
m_singleFunc[(int)precision].Set((int)SingleFunc.Normalize, index, true);
SetLenSqrDependencies(index, precision);
m_singleFunc[(int)precision].Set((int)SingleFunc.Rsqrt, 0, true);
m_func1[(int)precision].Set((int)Func1.InvLen,index,true);
m_splatStructFromScalar[(int)precision][index] = true;
m_singleFunc[(int)precision].Set((int)BinaryFunc.Mul,index,true);
string ret = "NormalizeApd(" + name + ")";
return ret;
}
string DotApd(ConcreteSlotValueType param, ConcretePrecision prec, string lhsName, string rhsName)
{
int index = FloatTypeToIndex(param);
m_func2[(int)prec].Set((int)Func2.Dot,index,true);
m_binaryFunc[(int)prec].Set((int)BinaryFunc.Add,0,true);
m_binaryFunc[(int)prec].Set((int)BinaryFunc.Mul,0,true);
for (int iter = 0; iter <= index; iter++)
{
m_extractFromApd[(int)prec].Set(index,iter,true);
}
string ret = "DotApd(" + lhsName + "," + rhsName + ")";
return ret;
}
string CrossApd(ConcreteSlotValueType param, ConcretePrecision prec, string lhsName, string rhsName)
{
int index = FloatTypeToIndex(param);
HlslUtil.ParserAssert(index == 2); // only valid for vec3 data
m_func2[(int)prec].Set((int)Func2.Cross,index,true);
m_binaryFunc[(int)prec].Set((int)BinaryFunc.Add,0,true);
m_binaryFunc[(int)prec].Set((int)BinaryFunc.Mul,0,true);
m_binaryFunc[(int)prec].Set((int)BinaryFunc.Sub,0,true);
for (int iter = 0; iter < 3; iter++)
{
m_extractFromApd[(int)prec].Set((int)2,iter,true);
}
m_mergeToApd[(int)prec][2] = true;
string ret = "CrossApd(" + lhsName + "," + rhsName + ")";
return ret;
}
string ReflectApd(ConcreteSlotValueType param, ConcretePrecision prec, string lhsName, string rhsName)
{
int index = FloatTypeToIndex(param);
//HlslUtil.ParserAssert(index == 2); // only valid for vec3 data
m_func2[(int)prec].Set((int)BinaryFunc.Reflect,index,true);
m_func2[(int)prec].Set((int)Func2.Dot, index, true);
m_binaryFunc[(int)prec].Set((int)BinaryFunc.Add,0,true);
m_binaryFunc[(int)prec].Set((int)BinaryFunc.Mul,0,true);
m_binaryFunc[(int)prec].Set((int)BinaryFunc.Sub,0,true);
m_mergeToApd[(int)prec][index] = true;
m_splatStructFromScalar[(int)prec][index] = true;
string ret = "ReflectApd(" + lhsName + "," + rhsName + ")";
return ret;
}
string LerpApd(ConcreteSlotValueType param, ConcretePrecision prec, string lhsName, string rhsName, string tName)
{
int index = FloatTypeToIndex(param);
m_func3[(int)prec].Set((int)Func3.Lerp,index,true);
m_binaryFunc[(int)prec].Set((int)BinaryFunc.Add,index,true);
m_binaryFunc[(int)prec].Set((int)BinaryFunc.Mul,index,true);
m_binaryFunc[(int)prec].Set((int)BinaryFunc.Sub,index,true);
m_splatStructFromScalar[(int)prec][index] = true;
m_makeStructFromFpd[(int)prec][index] = true;
string ret = "LerpApd(" + lhsName + "," + rhsName + "," + tName + ")";
return ret;
}
internal string MakeMerge2(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
ConcreteSlotValueType param0, ApdStatus status0, ConcretePrecision precision0, string name0,
ConcreteSlotValueType param1, ApdStatus status1, ConcretePrecision precision1, string name1)
{
bool isDstStruct = IsApdStruct(dstStatus);
string ret;
if (isDstStruct)
{
string val0 = ConvertVariable(param0, dstStatus,dstPrecision,param0,status0,precision0,name0);
string val1 = ConvertVariable(param1, dstStatus, dstPrecision, param1,status1,precision1,name1);
string scalar0 = ExtractIndexApd(param0, precision0,0,val0);
string scalar1 = ExtractIndexApd(param1, precision1,0,val1);
ret = MergeApd2(dstPrecision,scalar0,scalar1);
}
else
{
string precName = GetPrecisionName(dstPrecision);
string suffix0 = (param0 == ConcreteSlotValueType.Vector1) ? "" : ".x";
string suffix1 = (param1 == ConcreteSlotValueType.Vector1) ? "" : ".x";
ret = precName + "2(" + name0 + suffix0 + "," + name1 + suffix1 + ")";
}
return ret;
}
internal string MakeMerge3(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
ConcreteSlotValueType param0, ApdStatus status0, ConcretePrecision precision0, string name0,
ConcreteSlotValueType param1, ApdStatus status1, ConcretePrecision precision1, string name1,
ConcreteSlotValueType param2, ApdStatus status2, ConcretePrecision precision2, string name2)
{
bool isDstStruct = IsApdStruct(dstStatus);
string ret;
if (isDstStruct)
{
string val0 = ConvertVariable(param0, dstStatus,dstPrecision,param0,status0,precision0,name0);
string val1 = ConvertVariable(param1, dstStatus, dstPrecision, param1,status1,precision1,name1);
string val2 = ConvertVariable(param2, dstStatus, dstPrecision, param2,status2,precision2,name2);
string scalar0 = ExtractIndexApd(param0,precision0,0,val0);
string scalar1 = ExtractIndexApd(param1,precision1,0,val1);
string scalar2 = ExtractIndexApd(param2,precision2,0,val2);
ret = MergeApd3(dstPrecision,scalar0,scalar1,scalar2);
}
else
{
string precName = GetPrecisionName(dstPrecision);
string suffix0 = (param0 == ConcreteSlotValueType.Vector1) ? "" : ".x";
string suffix1 = (param1 == ConcreteSlotValueType.Vector1) ? "" : ".x";
string suffix2 = (param2 == ConcreteSlotValueType.Vector1) ? "" : ".x";
ret = precName + "3(" + name0 + suffix0 + "," + name1 + suffix1 + "," + name2 + suffix2 + ")";
}
return ret;
}
internal string MakeMerge4(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
ConcreteSlotValueType param0, ApdStatus status0, ConcretePrecision precision0, string name0,
ConcreteSlotValueType param1, ApdStatus status1, ConcretePrecision precision1, string name1,
ConcreteSlotValueType param2, ApdStatus status2, ConcretePrecision precision2, string name2,
ConcreteSlotValueType param3, ApdStatus status3, ConcretePrecision precision3, string name3)
{
bool isDstStruct = IsApdStruct(dstStatus);
string ret;
if (isDstStruct)
{
// does this work correctly for mixed precision? probably not?
string val0 = ConvertVariable(param0, dstStatus, dstPrecision, param0,status0, precision0, name0);
string val1 = ConvertVariable(param1, dstStatus,dstPrecision,param1,status1, precision1, name1);
string val2 = ConvertVariable(param2, dstStatus, dstPrecision, param2,status2, precision2, name2);
string val3 = ConvertVariable(param3, dstStatus, dstPrecision, param3,status3, precision3, name3);
string scalar0 = ExtractIndexApd(param0,precision0, 0,val0);
string scalar1 = ExtractIndexApd(param1,precision1,0,val1);
string scalar2 = ExtractIndexApd(param2,precision2,0,val2);
string scalar3 = ExtractIndexApd(param3,precision3,0,val3);
ret = MergeApd4(dstPrecision,scalar0,scalar1,scalar2,scalar3);
}
else
{
string precName = GetPrecisionName(dstPrecision);
string suffix0 = (param0 == ConcreteSlotValueType.Vector1) ? "" : ".x";
string suffix1 = (param1 == ConcreteSlotValueType.Vector1) ? "" : ".x";
string suffix2 = (param2 == ConcreteSlotValueType.Vector1) ? "" : ".x";
string suffix3 = (param3 == ConcreteSlotValueType.Vector1) ? "" : ".x";
ret = precName + "4(" + name0 + suffix0 + "," + name1 + suffix1 + "," + name2 + suffix2 + "," + name3 + suffix3 + ")";
}
return ret;
}
internal string MakeMergeMatrix(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
ConcreteSlotValueType[] paramVec, ApdStatus[] statusVec, ConcretePrecision[] precisionVec, string[] nameVec,
int dim)
{
bool isDstStruct = IsApdStruct(dstStatus);
HlslUtil.ParserAssert(!isDstStruct);
HlslUtil.ParserAssert(paramVec.Length == dim*dim);
HlslUtil.ParserAssert(statusVec.Length == dim * dim);
HlslUtil.ParserAssert(precisionVec.Length == dim * dim);
HlslUtil.ParserAssert(nameVec.Length == dim * dim);
string[] vals = new string[dim * dim];
for (int i = 0; i < dim * dim; i++)
{
vals[i] = ConvertVariable(ConcreteSlotValueType.Vector1, ApdStatus.Zero, dstPrecision, paramVec[i], statusVec[i], precisionVec[i], nameVec[i]);
}
string precName = GetPrecisionName(dstPrecision);
string ret = precName + dim.ToString() + "x" + dim.ToString() + "(";
for (int i = 0; i < dim*dim; i++)
{
ret += vals[i];
if (i < dim*dim-1)
{
ret += ",";
}
}
ret += ")";
return ret;
}
internal string MakeScalarZero(ApdStatus dstStatus, ConcretePrecision dstPrecision)
{
string ret;
bool isDstStruct = IsApdStruct(dstStatus);
if (isDstStruct)
{
ret = MakeStructFromFpd(ConcreteSlotValueType.Vector1, "0", dstPrecision);
}
else
{
ret = "0";
}
return ret;
}
internal string MakeSplit(int dstIndex,
ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
ConcreteSlotValueType param, ApdStatus status, ConcretePrecision precision, string name)
{
int srcTypeIndex = FloatTypeToIndex(param);
bool isDstStruct = IsApdStruct(dstStatus);
bool needsPrecisionChange = (dstPrecision != precision);
string dstPrecisionCast = needsPrecisionChange ? "(" + GetPrecisionName(dstPrecision) + ")" : "";
string ret;
if (dstIndex > srcTypeIndex)
{
ret = MakeScalarZero(dstStatus, dstPrecision);
}
else
{
if (isDstStruct)
{
string srcApd = AsStruct(param, status, precision, name);
ret = ExtractIndexApd(param, precision, dstIndex, srcApd);
}
else
{
string srcFpd = AsBase(param, status, name);
ret = dstPrecisionCast + srcFpd + "." + GetSuffixLower()[dstIndex];
}
}
return ret;
}
// only valid on non-struct parameters
internal static string GetPrecisionCast(ConcreteSlotValueType paramType, ConcretePrecision dstPrecision, ConcretePrecision srcPrecision)
{
string ret = "";
if (dstPrecision != srcPrecision)
{
int index = FloatTypeToIndex(paramType);
string baseName = GetApdBaseName(index,dstPrecision);
ret = "(" + baseName + ")";
}
return ret;
}
internal string MakeDot(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
ConcreteSlotValueType lhsParam, ApdStatus lhsStatus, ConcretePrecision lhsPrecision, string lhsName,
ConcreteSlotValueType rhsParam, ApdStatus rhsStatus, ConcretePrecision rhsPrecision, string rhsName)
{
bool isDstStruct = IsApdStruct(dstStatus);
//HlslUtil.ParserAssert(lhsParam == rhsParam);
ConcretePrecision binaryPrecision = GetBinaryOpPrecisionType(lhsPrecision, rhsPrecision);
ConcreteSlotValueType binaryParam = GetBinaryOpReturnTypeVector(lhsParam, rhsParam);
string ret;
if (isDstStruct)
{
string lhsApd = ConvertVariable(binaryParam, dstStatus, dstPrecision, lhsParam,lhsStatus,lhsPrecision,lhsName);
string rhsApd = ConvertVariable(binaryParam, dstStatus, dstPrecision, rhsParam,rhsStatus,rhsPrecision,rhsName);
ret = DotApd(lhsParam,binaryPrecision,lhsApd, rhsApd);
}
else
{
string lhsFpd = AsBase(binaryParam, lhsStatus,lhsName);
string rhsFpd = AsBase(binaryParam, rhsStatus,rhsName);
ret = GetPrecisionCast(dstParam, dstPrecision, binaryPrecision) + "dot(" + lhsFpd + "," + rhsFpd + ")";
}
return ret;
}
internal string MakeBranch(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
ConcreteSlotValueType predicateParam, ApdStatus predicateStatus, ConcretePrecision predicatePrecision, string predicateName,
ConcreteSlotValueType lhsParam, ApdStatus lhsStatus, ConcretePrecision lhsPrecision, string lhsName,
ConcreteSlotValueType rhsParam, ApdStatus rhsStatus, ConcretePrecision rhsPrecision, string rhsName)
{
// basic function:
// return predicate ? lhs : rhs;
bool isDstStruct = IsApdStruct(dstStatus);
// Predicate apd status should NEVER be valid. Since it's a bool, it is known to be zero, so it will always be known zero, not
// needed, or invalid.
HlslUtil.ParserAssert(!IsApdStruct(predicateStatus));
// precision is based on lhs and rhs, predicate is irrelevant for precision
ConcretePrecision binaryPrecision = GetBinaryOpPrecisionType(lhsPrecision, rhsPrecision);
// convert lhs and rhs to the preferred type
string lhsVariable = ConvertVariable(dstParam, dstStatus, dstPrecision, lhsParam, lhsStatus, lhsPrecision, lhsName);
string rhsVariable = ConvertVariable(dstParam, dstStatus, dstPrecision, rhsParam, rhsStatus, rhsPrecision, rhsName);
string ret;
if (isDstStruct)
{
int dstIndex = FloatTypeToIndex(dstParam);
m_selectApd[(int)dstPrecision][dstIndex] = true;
string structName = GetApdStructName(dstIndex, dstPrecision);
string baseName = GetApdBaseName(dstIndex, dstPrecision);
string funcName = "Make" + structName + "Select";
ret = funcName + "(" + predicateName + "," + lhsVariable + "," + rhsVariable + ")";
}
else
{
ret = predicateName + " ? " + lhsVariable + " : " + rhsVariable;
}
return ret;
}
internal string MakeCross(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
ConcreteSlotValueType lhsParam, ApdStatus lhsStatus, ConcretePrecision lhsPrecision, string lhsName,
ConcreteSlotValueType rhsParam, ApdStatus rhsStatus, ConcretePrecision rhsPrecision, string rhsName)
{
bool isDstStruct = IsApdStruct(dstStatus);
HlslUtil.ParserAssert(lhsParam == ConcreteSlotValueType.Vector3);
HlslUtil.ParserAssert(rhsParam == ConcreteSlotValueType.Vector3);
ConcretePrecision binaryPrecision = GetBinaryOpPrecisionType(lhsPrecision, rhsPrecision);
string ret;
if (isDstStruct)
{
string lhsApd = ConvertVariable(dstParam, dstStatus, dstPrecision, lhsParam, lhsStatus,lhsPrecision,lhsName);
string rhsApd = ConvertVariable(dstParam, dstStatus, dstPrecision, rhsParam, rhsStatus,rhsPrecision,rhsName);
ret = CrossApd(lhsParam,binaryPrecision,lhsApd,rhsApd);
}
else
{
string lhsFpd = AsBase(lhsParam,lhsStatus,lhsName);
string rhsFpd = AsBase(rhsParam,rhsStatus,rhsName);
ret = GetPrecisionCast(dstParam, dstPrecision, binaryPrecision) + "cross(" + lhsFpd + "," + rhsFpd + ")";
}
return ret;
}
internal string MakeReflect(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
ConcreteSlotValueType lhsParam, ApdStatus lhsStatus, ConcretePrecision lhsPrecision, string lhsName,
ConcreteSlotValueType rhsParam, ApdStatus rhsStatus, ConcretePrecision rhsPrecision, string rhsName)
{
bool isDstStruct = IsApdStruct(dstStatus);
HlslUtil.ParserAssert(lhsParam == rhsParam);
ConcretePrecision binaryPrecision = GetBinaryOpPrecisionType(lhsPrecision, rhsPrecision);
string ret;
if (isDstStruct)
{
string lhsApd = ConvertVariable(dstParam, dstStatus, dstPrecision, lhsParam, lhsStatus,lhsPrecision,lhsName);
string rhsApd = ConvertVariable(dstParam, dstStatus, dstPrecision, rhsParam, rhsStatus,rhsPrecision,rhsName);
ret = ReflectApd(dstParam,dstPrecision,lhsApd,rhsApd);
}
else
{
string lhsFpd = AsBase(lhsParam,lhsStatus,lhsName);
string rhsFpd = AsBase(rhsParam,rhsStatus,rhsName);
ret = GetPrecisionCast(dstParam, dstPrecision, binaryPrecision) + "reflect(" + lhsFpd + "," + rhsFpd + ")";
}
return ret;
}
internal string MakeLerp(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
ConcreteSlotValueType lhsParam, ApdStatus lhsStatus, ConcretePrecision lhsPrecision, string lhsName,
ConcreteSlotValueType rhsParam, ApdStatus rhsStatus, ConcretePrecision rhsPrecision, string rhsName,
ConcreteSlotValueType tParam, ApdStatus tStatus, ConcretePrecision tPrecision, string tName)
{
ConcreteSlotValueType funcParam = GetBinaryOpReturnTypeVector(lhsParam,rhsParam);
ConcretePrecision tripletPrecision = GetBinaryOpPrecisionType(tPrecision,GetBinaryOpPrecisionType(lhsPrecision, rhsPrecision));
bool isDstStruct = IsApdStruct(dstStatus);
string ret;
if (isDstStruct)
{
string lhsV = ConvertVariable(funcParam,dstStatus,dstPrecision,lhsParam,lhsStatus, lhsPrecision, lhsName);
string rhsV = ConvertVariable(funcParam,dstStatus,dstPrecision,rhsParam,rhsStatus,rhsPrecision,rhsName);
string tV = ConvertVariable(funcParam,dstStatus,dstPrecision,tParam,tStatus, tPrecision, tName);
ret = LerpApd(funcParam,dstPrecision,lhsV,rhsV,tV);
}
else
{
string lhsV = ConvertVariable(funcParam,dstStatus,dstPrecision,lhsParam,lhsStatus, lhsPrecision, lhsName);
string rhsV = ConvertVariable(funcParam,dstStatus,dstPrecision,rhsParam,rhsStatus,rhsPrecision,rhsName);
string tV = ConvertVariable(funcParam,dstStatus,dstPrecision,tParam,tStatus, tPrecision, tName);
ret = GetPrecisionCast(dstParam, dstPrecision, tripletPrecision) + "lerp(" + lhsV + "," + rhsV + "," + tV + ")";
}
return ret;
}
// maybe we should merge these 5 funcs?
internal string MakeTextureSample2d(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
string texName,
string samplerName,
ConcreteSlotValueType uvParamSrc, ApdStatus uvStatus, ConcretePrecision uvPrecision, string srcName,
bool useApd,
bool isPixelShader)
{
HlslUtil.ParserAssert(dstParam == ConcreteSlotValueType.Vector4);
// for now uv, will always be float precision, but we could add a variation later
string castedName = MakeImplicitCast(ConcreteSlotValueType.Vector2, uvStatus, ConcretePrecision.Single, uvParamSrc, uvStatus, uvPrecision, srcName);
string ret;
string precUpper = GetPrecUpper((int)dstPrecision);
if (!useApd)
{
m_texSample2d[(int)dstPrecision][(int)TexSampleType.Fpd] = true;
ret = GetPrecisionCast(dstParam, dstPrecision, uvPrecision) + "TextureSample2d" + precUpper + "Fpd(" + texName + "," + samplerName + "," + castedName + ")";
}
else
{
if (uvStatus != ApdStatus.Valid)
{
// In this case, we don't know the derivative. If it's a pixel shader, we can fall back to APD, hope for the best and
// live with artifacts along edges. However, if it's a CS, we have no choice but to fall back to level 0.
string uvFpd = AsBase(ConcreteSlotValueType.Vector2, uvStatus, castedName);
if (isPixelShader)
{
m_texSample2d[(int)dstPrecision][(int)TexSampleType.Fpd] = true;
ret = "TextureSample2d" + precUpper + "Fpd(" + texName + "," + samplerName + "," + uvFpd + ")";
}
else
{
m_texSample2d[(int)dstPrecision][(int)TexSampleType.Lod0] = true;
ret = "TextureSample2d" + precUpper + "Lod0(" + texName + "," + samplerName + "," + uvFpd + ")";
}
bool isDstStruct = IsApdStruct(dstStatus);
if (isDstStruct)
{
ret = SplatStructFromScalar(ConcreteSlotValueType.Vector4, ret, uvPrecision);
}
}
else
{
bool isDstStruct = IsApdStruct(dstStatus);
string uvApd = AsStruct(ConcreteSlotValueType.Vector2, uvStatus, uvPrecision, castedName);
if (!isDstStruct)
{
m_texSample2d[(int)dstPrecision][(int)TexSampleType.Apd] = true;
ret = "TextureSample2d" + precUpper + "Apd(" + texName + "," + samplerName + "," + uvApd + ")";
}
else
{
m_texSample2d[(int)dstPrecision][(int)TexSampleType.Apd_3x] = true;
ret = "TextureSample2d" + precUpper + "Apd3x(" + texName + "," + samplerName + "," + uvApd + ")";
}
}
}
return ret;
}
internal string MakeTextureSample2dArray(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
string texName,
string samplerName,
ConcreteSlotValueType uvParamSrc, ApdStatus uvStatus, ConcretePrecision uvPrecision, string srcName,
bool useApd,
bool isPixelShader)
{
HlslUtil.ParserAssert(dstParam == ConcreteSlotValueType.Vector4);
// for now uv, will always be float precision, but we could add a variation later
string castedName = MakeImplicitCast(ConcreteSlotValueType.Vector3, uvStatus, ConcretePrecision.Single, uvParamSrc, uvStatus, uvPrecision, srcName);
string ret;
string precUpper = GetPrecUpper((int)dstPrecision);
if (!useApd)
{
m_texSample2dArray[(int)dstPrecision][(int)TexSampleType.Fpd] = true;
ret = GetPrecisionCast(dstParam, dstPrecision, uvPrecision) + "TextureSample2dArray" + precUpper + "Fpd(" + texName + "," + samplerName + "," + castedName + ")";
}
else
{
//HlslUtil.ParserAssert(uvStatus != ApdStatus.Unknown);
if (uvStatus != ApdStatus.Valid)
{
// In this case, we don't know the derivative. If it's a pixel shader, we can fall back to APD, hope for the best and
// live with artifacts along edges. However, if it's a CS, we have no choice but to fall back to level 0.
string uvFpd = AsBase(ConcreteSlotValueType.Vector3, uvStatus, castedName);
if (isPixelShader)
{
m_texSample2dArray[(int)dstPrecision][(int)TexSampleType.Fpd] = true;
ret = "TextureSample2dArray" + precUpper + "Fpd(" + texName + "," + samplerName + "," + uvFpd + ")";
}
else
{
m_texSample2dArray[(int)dstPrecision][(int)TexSampleType.Lod0] = true;
ret = "TextureSample2dArray" + precUpper + "Lod0(" + texName + "," + samplerName + "," + uvFpd + ")";
}
bool isDstStruct = IsApdStruct(dstStatus);
if (isDstStruct)
{
ret = SplatStructFromScalar(ConcreteSlotValueType.Vector4, ret, uvPrecision);
}
}
else
{
bool isDstStruct = IsApdStruct(dstStatus);
string uvApd = AsStruct(ConcreteSlotValueType.Vector3, uvStatus, uvPrecision, castedName);
if (!isDstStruct)
{
m_texSample2dArray[(int)dstPrecision][(int)TexSampleType.Apd] = true;
ret = "TextureSample2dArray" + precUpper + "Apd(" + texName + "," + samplerName + "," + uvApd + ")";
}
else
{
m_texSample2dArray[(int)dstPrecision][(int)TexSampleType.Apd_3x] = true;
ret = "TextureSample2dArray" + precUpper + "Apd3x(" + texName + "," + samplerName + "," + uvApd + ")";
}
}
}
return ret;
}
internal string MakeTextureSampleCube(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
string texName,
string samplerName,
ConcreteSlotValueType uvParamSrc, ApdStatus uvStatus, ConcretePrecision uvPrecision, string srcName,
bool useApd,
bool isPixelShader)
{
HlslUtil.ParserAssert(dstParam == ConcreteSlotValueType.Vector4);
// for now uv, will always be float precision, but we could add a variation later
string castedName = MakeImplicitCast(ConcreteSlotValueType.Vector3, uvStatus, ConcretePrecision.Single, uvParamSrc, uvStatus, uvPrecision, srcName);
string ret;
string precUpper = GetPrecUpper((int)dstPrecision);
if (!useApd)
{
m_texSampleCube[(int)dstPrecision][(int)TexSampleType.Fpd] = true;
ret = GetPrecisionCast(dstParam, dstPrecision, uvPrecision) + "TextureSampleCube" + precUpper + "Fpd(" + texName + "," + samplerName + "," + castedName + ")";
}
else
{
if (uvStatus != ApdStatus.Valid)
{
// In this case, we don't know the derivative. If it's a pixel shader, we can fall back to APD, hope for the best and
// live with artifacts along edges. However, if it's a CS, we have no choice but to fall back to level 0.
string uvFpd = AsBase(ConcreteSlotValueType.Vector3, uvStatus, castedName);
if (isPixelShader)
{
m_texSampleCube[(int)dstPrecision][(int)TexSampleType.Fpd] = true;
ret = "TextureSampleCube" + precUpper + "Fpd(" + texName + "," + samplerName + "," + uvFpd + ")";
}
else
{
m_texSampleCube[(int)dstPrecision][(int)TexSampleType.Lod0] = true;
ret = "TextureSampleCube" + precUpper + "Lod0(" + texName + "," + samplerName + "," + uvFpd + ")";
}
bool isDstStruct = IsApdStruct(dstStatus);
if (isDstStruct)
{
ret = SplatStructFromScalar(ConcreteSlotValueType.Vector4, ret, uvPrecision);
}
}
else
{
bool isDstStruct = IsApdStruct(dstStatus);
string uvApd = AsStruct(ConcreteSlotValueType.Vector3, uvStatus, uvPrecision, castedName);
if (!isDstStruct)
{
m_texSampleCube[(int)dstPrecision][(int)TexSampleType.Apd] = true;
ret = "TextureSampleCube" + precUpper + "Apd(" + texName + "," + samplerName + "," + uvApd + ")";
}
else
{
m_texSampleCube[(int)dstPrecision][(int)TexSampleType.Apd_3x] = true;
ret = "TextureSampleCube" + precUpper + "Apd3x(" + texName + "," + samplerName + "," + uvApd + ")";
}
}
}
return ret;
}
internal string MakeTextureSampleCubeArray(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
string texName,
string samplerName,
ConcreteSlotValueType uvParamSrc, ApdStatus uvStatus, ConcretePrecision uvPrecision, string srcName,
bool useApd,
bool isPixelShader)
{
HlslUtil.ParserAssert(dstParam == ConcreteSlotValueType.Vector4);
// for now uv, will always be float precision, but we could add a variation later
string castedName = MakeImplicitCast(ConcreteSlotValueType.Vector4, uvStatus, ConcretePrecision.Single, uvParamSrc, uvStatus, uvPrecision, srcName);
string ret;
string precUpper = GetPrecUpper((int)dstPrecision);
if (!useApd)
{
m_texSampleCubeArray[(int)dstPrecision][(int)TexSampleType.Fpd] = true;
ret = GetPrecisionCast(dstParam, dstPrecision, uvPrecision) + "TextureSampleCubeArray" + precUpper + "Fpd(" + texName + "," + samplerName + "," + castedName + ")";
}
else
{
if (uvStatus != ApdStatus.Valid)
{
// In this case, we don't know the derivative. If it's a pixel shader, we can fall back to APD, hope for the best and
// live with artifacts along edges. However, if it's a CS, we have no choice but to fall back to level 0.
string uvFpd = AsBase(ConcreteSlotValueType.Vector4, uvStatus, castedName);
if (isPixelShader)
{
m_texSampleCubeArray[(int)dstPrecision][(int)TexSampleType.Fpd] = true;
ret = "TextureSampleCubeArray" + precUpper + "Fpd(" + texName + "," + samplerName + "," + uvFpd + ")";
}
else
{
m_texSampleCubeArray[(int)dstPrecision][(int)TexSampleType.Lod0] = true;
ret = "TextureSampleCubeArray" + precUpper + "Lod0(" + texName + "," + samplerName + "," + uvFpd + ")";
}
bool isDstStruct = IsApdStruct(dstStatus);
if (isDstStruct)
{
ret = SplatStructFromScalar(ConcreteSlotValueType.Vector4, ret, uvPrecision);
}
}
else
{
bool isDstStruct = IsApdStruct(dstStatus);
string uvApd = AsStruct(ConcreteSlotValueType.Vector4, uvStatus, uvPrecision, castedName);
if (!isDstStruct)
{
m_texSampleCubeArray[(int)dstPrecision][(int)TexSampleType.Apd] = true;
ret = "TextureSampleCubeArray" + precUpper + "Apd(" + texName + "," + samplerName + "," + uvApd + ")";
}
else
{
m_texSampleCubeArray[(int)dstPrecision][(int)TexSampleType.Apd_3x] = true;
ret = "TextureSampleCubeArray" + precUpper + "Apd3x(" + texName + "," + samplerName + "," + uvApd + ")";
}
}
}
return ret;
}
internal string MakeTextureSample3d(ConcreteSlotValueType dstParam, ApdStatus dstStatus, ConcretePrecision dstPrecision,
string texName,
string samplerName,
ConcreteSlotValueType uvParamSrc, ApdStatus uvStatus, ConcretePrecision uvPrecision, string srcName,
bool useApd,
bool isPixelShader)
{
HlslUtil.ParserAssert(dstParam == ConcreteSlotValueType.Vector4);
// for now uv, will always be float precision, but we could add a variation later
string castedName = MakeImplicitCast(ConcreteSlotValueType.Vector3, uvStatus, ConcretePrecision.Single, uvParamSrc, uvStatus, uvPrecision, srcName);
string ret;
string precUpper = GetPrecUpper((int)dstPrecision);
if (!useApd)
{
m_texSample3d[(int)dstPrecision][(int)TexSampleType.Fpd] = true;
ret = GetPrecisionCast(dstParam, dstPrecision, uvPrecision) + "TextureSample3d" + precUpper + "Fpd(" + texName + "," + samplerName + "," + castedName + ")";
}
else
{
if (uvStatus != ApdStatus.Valid)
{
// In this case, we don't know the derivative. If it's a pixel shader, we can fall back to APD, hope for the best and
// live with artifacts along edges. However, if it's a CS, we have no choice but to fall back to level 0.
string uvFpd = AsBase(ConcreteSlotValueType.Vector3, uvStatus, castedName);
if (isPixelShader)
{
m_texSample3d[(int)dstPrecision][(int)TexSampleType.Fpd] = true;
ret = "TextureSample3d" + precUpper + "Fpd(" + texName + "," + samplerName + "," + uvFpd + ")";
}
else
{
m_texSample3d[(int)dstPrecision][(int)TexSampleType.Lod0] = true;
ret = "TextureSample3d" + precUpper + "Lod0(" + texName + "," + samplerName + "," + uvFpd + ")";
}
bool isDstStruct = IsApdStruct(dstStatus);
if (isDstStruct)
{
ret = SplatStructFromScalar(ConcreteSlotValueType.Vector4, ret, uvPrecision);
}
}
else
{
bool isDstStruct = IsApdStruct(dstStatus);
string uvApd = AsStruct(ConcreteSlotValueType.Vector3, uvStatus, uvPrecision, castedName);
if (!isDstStruct)
{
m_texSample3d[(int)dstPrecision][(int)TexSampleType.Apd] = true;
ret = "TextureSample3d" + precUpper + "Apd(" + texName + "," + samplerName + "," + uvApd + ")";
}
else
{
m_texSample3d[(int)dstPrecision][(int)TexSampleType.Apd_3x] = true;
ret = "TextureSample3d" + precUpper + "Apd3x(" + texName + "," + samplerName + "," + uvApd + ")";
}
}
}
return ret;
}
internal string MakeSwizzleApd(ConcreteSlotValueType paramType, ConcretePrecision prec, string srcName,
int numChars,
int i0,
int i1,
int i2,
int i3)
{
int srcTypeIndex = FloatTypeToIndex(paramType);
HlslUtil.ParserAssert(0 <= srcTypeIndex && srcTypeIndex < 4);
HlslUtil.ParserAssert(1 <= numChars && numChars <= 4);
HlslUtil.ParserAssert(0 <= i0 && i0 < 4);
HlslUtil.ParserAssert(0 <= i1 && i1 < 4);
HlslUtil.ParserAssert(0 <= i2 && i2 < 4);
HlslUtil.ParserAssert(0 <= i3 && i3 < 4);
m_swizzles[(int)prec].Set(srcTypeIndex,numChars-1,i0,i1,i2,i3,true);
string swizzle = GetSwizzleName(numChars,i0,i1,i2,i3,true);
string srcStructName = GetApdStructName(srcTypeIndex,prec);
string ret = "Swizzle" + srcStructName + "_" + swizzle + "(" + srcName + ")";
return ret;
}
internal string MakeSwizzleAssignApd(ConcreteSlotValueType paramType, ConcretePrecision prec, ApdStatus apdStatus, string lhsName,
string rhsName,
int numChars,
int i0,
int i1,
int i2,
int i3)
{
int srcTypeIndex = FloatTypeToIndex(paramType);
HlslUtil.ParserAssert(0 <= srcTypeIndex && srcTypeIndex < 4);
HlslUtil.ParserAssert(1 <= numChars && numChars <= 4);
HlslUtil.ParserAssert(0 <= i0 && i0 < 4);
HlslUtil.ParserAssert(0 <= i1 && i1 < 4);
HlslUtil.ParserAssert(0 <= i2 && i2 < 4);
HlslUtil.ParserAssert(0 <= i3 && i3 < 4);
HlslUtil.ParserAssert(i0 <= srcTypeIndex);
HlslUtil.ParserAssert(i1 <= srcTypeIndex);
HlslUtil.ParserAssert(i2 <= srcTypeIndex);
HlslUtil.ParserAssert(i3 <= srcTypeIndex);
string ret = "";
if (apdStatus == ApdStatus.Valid)
{
m_swizzlesAssign[(int)prec].Set(srcTypeIndex, numChars - 1, i0, i1, i2, i3, true);
string swizzle = GetSwizzleName(numChars, i0, i1, i2, i3, true);
string srcStructName = GetApdStructName(srcTypeIndex, prec);
ret = "SwizzleAssign" + srcStructName + "_" + swizzle + "(" + lhsName + "," + rhsName + ")";
}
else
{
string swizzle = GetSwizzleName(numChars, i0, i1, i2, i3, false);
ret = "(" + lhsName + "." + swizzle + " = " + rhsName + ")";
}
return ret;
}
internal string MakeUv(ApdStatus status, ConcretePrecision prec, int index)
{
HlslUtil.ParserAssert(0 <= index);
HlslUtil.ParserAssert(index < 4); // really should have a limit of 8 (as in vs streams) but it's 4 for now because of the shader struct
bool isDstStruct = IsApdStruct(status);
string ret;
if (isDstStruct)
{
m_fetchUv[(int)prec].Set(index,1,true);
m_makeStructDirect[(int)prec][3] = true;
string attrib = "IN.uv" + index.ToString();
string attribDdx = "IN.uv" + index.ToString() + "Ddx";
string attribDdy = "IN.uv" + index.ToString() + "Ddy";
string val = MakeStructFromApdDirect(ConcreteSlotValueType.Vector4, attrib, attribDdx, attribDdy, ConcretePrecision.Single);
ret = ConvertVariable(ConcreteSlotValueType.Vector4, status, prec, ConcreteSlotValueType.Vector4, ApdStatus.Valid, ConcretePrecision.Single, val);
}
else
{
m_fetchUv[(int)prec].Set(index,0,true);
string val = "IN.uv" + index.ToString();
ret = ConvertVariable(ConcreteSlotValueType.Vector4, status, prec, ConcreteSlotValueType.Vector4, ApdStatus.Zero, ConcretePrecision.Single, val);
}
return ret;
}
internal string MakeFloatData(ConcreteSlotValueType type, ConcretePrecision precision, float[] data)
{
string ret = "";
string baseName = precision == ConcretePrecision.Single ? "float" : "half";
switch (type)
{
case ConcreteSlotValueType.Vector1:
HlslUtil.ParserAssert(data.Length == 1);
ret = data[0].ToString();
break;
case ConcreteSlotValueType.Vector2:
HlslUtil.ParserAssert(data.Length == 2);
ret = baseName + "2(" + data[0].ToString() + "," + data[1].ToString() + ")";
break;
case ConcreteSlotValueType.Vector3:
HlslUtil.ParserAssert(data.Length == 3);
ret = baseName + "3(" + data[0].ToString() + "," + data[1].ToString() + "," + data[2].ToString() + ")";
break;
case ConcreteSlotValueType.Vector4:
HlslUtil.ParserAssert(data.Length == 4);
ret = baseName + "4(" + data[0].ToString() + "," + data[1].ToString() + "," + data[2].ToString() + "," + data[3].ToString() + ")";
break;
case ConcreteSlotValueType.Matrix2:
HlslUtil.ParserAssert(data.Length == 4);
ret = baseName + "2x2("
+ data[2 * 0 + 0].ToString() + "," + data[2 * 0 + 1].ToString() + ","
+ data[2 * 1 + 0].ToString() + "," + data[2 * 1 + 1].ToString() + ")";
break;
case ConcreteSlotValueType.Matrix3:
HlslUtil.ParserAssert(data.Length == 9);
ret = baseName + "3x3("
+ data[3 * 0 + 0].ToString() + "," + data[3 * 0 + 1].ToString() + "," + data[3 * 0 + 2].ToString() + ","
+ data[3 * 1 + 0].ToString() + "," + data[3 * 1 + 1].ToString() + "," + data[3 * 1 + 2].ToString() + ","
+ data[3 * 2 + 0].ToString() + "," + data[3 * 2 + 1].ToString() + "," + data[3 * 2 + 2].ToString() + ")";
break;
case ConcreteSlotValueType.Matrix4:
HlslUtil.ParserAssert(data.Length == 16);
ret = baseName + "4x4("
+ data[4 * 0 + 0].ToString() + "," + data[4 * 0 + 1].ToString() + "," + data[4 * 0 + 2].ToString() + "," + data[4 * 0 + 3].ToString() + ","
+ data[4 * 1 + 0].ToString() + "," + data[4 * 1 + 1].ToString() + "," + data[4 * 1 + 2].ToString() + "," + data[4 * 1 + 3].ToString() + ","
+ data[4 * 2 + 0].ToString() + "," + data[4 * 2 + 1].ToString() + "," + data[4 * 2 + 2].ToString() + "," + data[4 * 2 + 3].ToString() + ","
+ data[4 * 3 + 0].ToString() + "," + data[4 * 3 + 1].ToString() + "," + data[4 * 3 + 2].ToString() + "," + data[4 * 3 + 3].ToString() + ")";
break;
default:
HlslUtil.ParserAssert(false);
break;
}
return ret;
}
internal string AdaptNodeOutputForPreview(ConcreteSlotValueType paramType, ApdStatus apdType, ConcretePrecision precision, string variableName)
{
string ret = "half4(0, 0, 0, 0)";
// preview is always dimension 4
switch (paramType)
{
case ConcreteSlotValueType.Vector1:
{
string adjName = MakeImplicitCast(ConcreteSlotValueType.Vector1, ApdStatus.Zero, ConcretePrecision.Half,
paramType, apdType, precision, variableName);
ret = string.Format("half4({0}, {0}, {0}, 1.0)", adjName);
break;
}
case ConcreteSlotValueType.Vector2:
{
string adjName = MakeImplicitCast(ConcreteSlotValueType.Vector2, ApdStatus.Zero, ConcretePrecision.Half,
paramType, apdType, precision, variableName);
ret = string.Format("half4({0}.x, {0}.y, 0.0, 1.0)", adjName);
break;
}
case ConcreteSlotValueType.Vector3:
{
string adjName = MakeImplicitCast(ConcreteSlotValueType.Vector3, ApdStatus.Zero, ConcretePrecision.Half,
paramType, apdType, precision, variableName);
ret = string.Format("half4({0}.x, {0}.y, {0}.z, 1.0)", adjName);
break;
}
case ConcreteSlotValueType.Vector4:
{
string adjName = MakeImplicitCast(ConcreteSlotValueType.Vector4, ApdStatus.Zero, ConcretePrecision.Half,
paramType, apdType, precision, variableName);
ret = string.Format("half4({0}.x, {0}.y, {0}.z, 1.0)", adjName);
break;
}
case ConcreteSlotValueType.Boolean:
{
string adjName = MakeImplicitCast(ConcreteSlotValueType.Boolean, ApdStatus.Zero, ConcretePrecision.Half,
paramType, apdType, precision, variableName);
// a boolean is really an int
ret = string.Format("half4({0}, {0}, {0}, 1.0)", variableName);
break;
}
default:
// invalid type, return default
break;
}
return ret;
}
// making this a separate struct, for now it is implemented as a vector of bools
// but we have the option to change it to a bitfield
struct BoolDim2
{
internal BoolDim2(int dim0, int dim1)
{
m_Dim0 = dim0;
m_Dim1 = dim1;
m_Vec = new bool[dim0 * dim1];
System.Array.Fill(m_Vec, false);
}
internal void Set(int idx0, int idx1, bool val)
{
int vecIdx = idx0 * m_Dim1 + idx1;
m_Vec[vecIdx] = val;
}
internal bool Get(int idx0, int idx1)
{
int vecIdx = idx0 * m_Dim1 + idx1;
bool ret = m_Vec[vecIdx];
return ret;
}
int m_Dim0;
int m_Dim1;
bool[] m_Vec;
}
// might change this to a bitfield too
struct BoolDim6
{
internal BoolDim6(int dim0, int dim1, int dim2, int dim3, int dim4, int dim5)
{
m_Dim0 = dim0;
m_Dim1 = dim1;
m_Dim2 = dim2;
m_Dim3 = dim3;
m_Dim4 = dim4;
m_Dim5 = dim5;
m_Vec = new bool[dim0 * dim1 * dim2 * dim3 * dim4 * dim5];
System.Array.Fill(m_Vec, false);
}
private int GetIndex(int idx0, int idx1, int idx2, int idx3, int idx4, int idx5)
{
int idx = 0;
idx += idx0 * (m_Dim1 * m_Dim2 * m_Dim3 * m_Dim4 * m_Dim5);
idx += idx1 * (m_Dim1 * m_Dim2 * m_Dim3 * m_Dim4);
idx += idx2 * (m_Dim1 * m_Dim2 * m_Dim3);
idx += idx3 * (m_Dim1 * m_Dim2);
idx += idx4 * (m_Dim1);
idx += idx5;
return idx;
}
internal void Set(int idx0, int idx1, int idx2, int idx3, int idx4, int idx5, bool val)
{
int vecIdx = GetIndex(idx0, idx1, idx2, idx3, idx4, idx5);
m_Vec[vecIdx] = val;
}
internal bool Get(int idx0, int idx1, int idx2, int idx3, int idx4, int idx5)
{
int vecIdx = GetIndex(idx0, idx1, idx2, idx3, idx4, idx5);
bool ret = m_Vec[vecIdx];
return ret;
}
int m_Dim0;
int m_Dim1;
int m_Dim2;
int m_Dim3;
int m_Dim4;
int m_Dim5;
bool[] m_Vec;
}
BoolDim2[] m_extractFromApd;
// src is Apd, dst is Apd, src is float, dst is float, src len, dst len
BoolDim6 m_implicitCast;
bool[][] m_mergeToApd;
bool[][] m_makeStructFromFpd;
bool[][] m_makeStructFromFpdFinite;
bool[][] m_splatStructFromScalar;
bool[][] m_extractIndexApd;
bool[][] m_insertIndexApd;
// We have separate functions for Tex2D, Tex2DArray, TexCube, TexCubeArray, and Tex3D.
// I tried to find an algorithmic way to merge these together and reduce the code
// but trying to merge them caused so much subtle complexity and corner cases that
// it wasn't worth it.
bool[][] m_texSample2d;
bool[][] m_texSample2dArray;
bool[][] m_texSampleCube;
bool[][] m_texSampleCubeArray;
bool[][] m_texSample3d;
bool[][] m_makeStructDirect;
bool[][] m_selectApd;
bool[][] m_mulMatVecApd;
bool[][] m_mulVecMatApd;
BoolDim2[] m_binaryFunc;
BoolDim2[] m_singleFunc;
BoolDim2[] m_fetchUv;
BoolDim2[] m_fetchColor;
BoolDim2[] m_func1;
BoolDim2[] m_func2;
BoolDim2[] m_func3;
// 6-dimentional, but array total size is only 4096
// type, swizzle length, 0, 1, 2, 3,
BoolDim6[] m_swizzles;
// 6-dimentional, but array total size is only 4096
// type, swizzle length , 0, 1, 2, 3,
BoolDim6[] m_swizzlesAssign;
}
}