Skip to content
Permalink
Browse files
Integrate changes from The Witness
- Add support for tex*size intrinsics.
- Add support for tex2Dgather intrinsic.
- Add support for interpolation modifiers in HLSL generator.
- Fix support for multiple chained assignments.
- Fix handling of -- operator.
- In progress: support for stage blocks and inline input/output
declarations.
  • Loading branch information
castano committed Dec 5, 2014
1 parent f6fbb0c commit 6d8eef7867d3de6e290092796e1027ed4f406a9a
Showing with 229 additions and 56 deletions.
  1. +1 −1 src/GLSLGenerator.cpp
  2. +74 −7 src/HLSLGenerator.cpp
  3. +4 −0 src/HLSLGenerator.h
  4. +64 −8 src/HLSLParser.cpp
  5. +1 −1 src/HLSLParser.h
  6. +1 −1 src/HLSLTokenizer.cpp
  7. +64 −38 src/HLSLTree.cpp
  8. +20 −0 src/HLSLTree.h
@@ -393,7 +393,7 @@ void GLSLGenerator::OutputExpression(HLSLExpression* expression, const HLSLType*
case HLSLUnaryOp_Positive: op = "+"; break;
case HLSLUnaryOp_Not: op = "!"; dstType = &unaryExpression->expressionType; break;
case HLSLUnaryOp_PreIncrement: op = "++"; break;
case HLSLUnaryOp_PreDecrement: op = "++"; break;
case HLSLUnaryOp_PreDecrement: op = "--"; break;
case HLSLUnaryOp_PostIncrement: op = "++"; pre = false; break;
case HLSLUnaryOp_PostDecrement: op = "--"; pre = false; break;
}
@@ -92,6 +92,7 @@ HLSLGenerator::HLSLGenerator(Allocator* allocator) :
m_tex2DBiasFunction[0] = 0;
m_tex2DGradFunction[0] = 0;
m_tex2DGatherFunction[0] = 0;
m_tex2DSizeFunction[0] = 0;
m_tex2DCmpFunction[0] = 0;
m_tex2DMSFetchFunction[0] = 0;
m_tex3DFunction[0] = 0;
@@ -242,14 +243,18 @@ bool HLSLGenerator::Generate(HLSLTree* tree, Target target, const char* entryNam
ChooseUniqueName("tex2Dbias", m_tex2DBiasFunction, sizeof(m_tex2DBiasFunction));
ChooseUniqueName("tex2Dgrad", m_tex2DGradFunction, sizeof(m_tex2DGradFunction));
ChooseUniqueName("tex2Dgather", m_tex2DGatherFunction, sizeof(m_tex2DGatherFunction));
ChooseUniqueName("tex2Dsize", m_tex2DSizeFunction, sizeof(m_tex2DSizeFunction));
ChooseUniqueName("tex2Dcmp", m_tex2DCmpFunction, sizeof(m_tex2DCmpFunction));
ChooseUniqueName("tex2DMSfetch", m_tex2DMSFetchFunction, sizeof(m_tex2DMSFetchFunction));
ChooseUniqueName("tex2DMSsize", m_tex2DMSSizeFunction, sizeof(m_tex2DMSSizeFunction));
ChooseUniqueName("tex3D", m_tex3DFunction, sizeof(m_tex3DFunction));
ChooseUniqueName("tex3Dlod", m_tex3DLodFunction, sizeof(m_tex3DLodFunction));
ChooseUniqueName("tex3Dbias", m_tex3DBiasFunction, sizeof(m_tex3DBiasFunction));
ChooseUniqueName("tex3Dsize", m_tex3DSizeFunction, sizeof(m_tex3DSizeFunction));
ChooseUniqueName("texCUBE", m_texCubeFunction, sizeof(m_texCubeFunction));
ChooseUniqueName("texCUBElod", m_texCubeLodFunction, sizeof(m_texCubeLodFunction));
ChooseUniqueName("texCUBEbias", m_texCubeBiasFunction, sizeof(m_texCubeBiasFunction));
ChooseUniqueName("texCUBEsize", m_texCubeSizeFunction, sizeof(m_texCubeSizeFunction));

if (!m_legacy)
{
@@ -329,6 +334,21 @@ bool HLSLGenerator::Generate(HLSLTree* tree, Target target, const char* entryNam
m_writer.WriteLine(1, "return ts.t.SampleGrad(ts.s, texCoord.xy, ddx, ddy);");
m_writer.WriteLine(0, "}");
}
if (m_tree->GetContainsString("tex2Dgather"))
{
m_writer.WriteLine(0, "float4 %s(%s ts, float2 texCoord, int component, int2 offset=0) {", m_tex2DGatherFunction, m_textureSampler2DStruct);
m_writer.WriteLine(1, "if(component == 0) return ts.t.GatherRed(ts.s, texCoord, offset);");
m_writer.WriteLine(1, "if(component == 1) return ts.t.GatherGreen(ts.s, texCoord, offset);");
m_writer.WriteLine(1, "if(component == 2) return ts.t.GatherBlue(ts.s, texCoord, offset);");
m_writer.WriteLine(1, "return ts.t.GatherAlpha(ts.s, texCoord, offset);");
m_writer.WriteLine(0, "}");
}
if (m_tree->GetContainsString("tex2Dsize"))
{
m_writer.WriteLine(0, "int2 %s(%s ts) {", m_tex2DSizeFunction, m_textureSampler2DStruct);
m_writer.WriteLine(1, "int2 size; ts.t.GetDimensions(size.x, size.y); return size;");
m_writer.WriteLine(0, "}");
}
if (m_tree->GetContainsString("tex2Dcmp"))
{
m_writer.WriteLine(0, "float4 %s(%s ts, float4 texCoord) {", m_tex2DCmpFunction, m_textureSampler2DShadowStruct);
@@ -341,13 +361,10 @@ bool HLSLGenerator::Generate(HLSLTree* tree, Target target, const char* entryNam
m_writer.WriteLine(1, "return t.Load(texCoord, sample);");
m_writer.WriteLine(0, "}");
}
if (m_tree->GetContainsString("tex2Dgather"))
if (m_tree->GetContainsString("tex2DMSsize"))
{
m_writer.WriteLine(0, "float4 %s(%s ts, float2 texCoord, int component, int2 offset=0) {", m_tex2DGatherFunction, m_textureSampler2DStruct);
m_writer.WriteLine(1, "if(component == 0) return ts.t.GatherRed(ts.s, texCoord, offset);");
m_writer.WriteLine(1, "if(component == 1) return ts.t.GatherGreen(ts.s, texCoord, offset);");
m_writer.WriteLine(1, "if(component == 2) return ts.t.GatherBlue(ts.s, texCoord, offset);");
m_writer.WriteLine(1, "if(component == 3) return ts.t.GatherAlpha(ts.s, texCoord, offset);");
m_writer.WriteLine(0, "int3 %s(Texture2DMS<float4> t) {", m_tex2DMSSizeFunction);
m_writer.WriteLine(1, "int3 size; t.GetDimensions(size.x, size.y, size.z); return size;"); // @@ Not tested, does this return the number of samples in the third argument?
m_writer.WriteLine(0, "}");
}
if (m_tree->GetContainsString("tex3D"))
@@ -368,6 +385,12 @@ bool HLSLGenerator::Generate(HLSLTree* tree, Target target, const char* entryNam
m_writer.WriteLine(1, "return ts.t.SampleBias(ts.s, texCoord.xyz, texCoord.w);");
m_writer.WriteLine(0, "}");
}
if (m_tree->GetContainsString("tex3Dsize"))
{
m_writer.WriteLine(0, "int3 %s(%s ts) {", m_tex3DSizeFunction, m_textureSampler3DStruct);
m_writer.WriteLine(1, "int3 size; ts.t.GetDimensions(size.x, size.y, size.z); return size;");
m_writer.WriteLine(0, "}");
}
if (m_tree->GetContainsString("texCUBE"))
{
m_writer.WriteLine(0, "float4 %s(%s ts, float3 texCoord) {", m_texCubeFunction, m_textureSamplerCubeStruct);
@@ -386,6 +409,12 @@ bool HLSLGenerator::Generate(HLSLTree* tree, Target target, const char* entryNam
m_writer.WriteLine(1, "return ts.t.SampleBias(ts.s, texCoord.xyz, texCoord.w);");
m_writer.WriteLine(0, "}");
}
if (m_tree->GetContainsString("texCUBEsize"))
{
m_writer.WriteLine(0, "int %s(%s ts) {", m_texCubeSizeFunction, m_textureSamplerCubeStruct);
m_writer.WriteLine(1, "int size; ts.t.GetDimensions(size); return size;"); // @@ Not tested, does this return a single value?
m_writer.WriteLine(0, "}");
}
}

HLSLRoot* root = m_tree->GetRoot();
@@ -502,7 +531,7 @@ void HLSLGenerator::OutputExpression(HLSLExpression* expression)
case HLSLUnaryOp_Positive: op = "+"; break;
case HLSLUnaryOp_Not: op = "!"; break;
case HLSLUnaryOp_PreIncrement: op = "++"; break;
case HLSLUnaryOp_PreDecrement: op = "++"; break;
case HLSLUnaryOp_PreDecrement: op = "--"; break;
case HLSLUnaryOp_PostIncrement: op = "++"; pre = false; break;
case HLSLUnaryOp_PostDecrement: op = "--"; pre = false; break;
}
@@ -607,6 +636,10 @@ void HLSLGenerator::OutputExpression(HLSLExpression* expression)
{
name = m_tex2DGatherFunction;
}
else if (String_Equal(name, "tex2Dsize"))
{
name = m_tex2DSizeFunction;
}
else if (String_Equal(name, "tex2Dcmp"))
{
name = m_tex2DCmpFunction;
@@ -615,6 +648,10 @@ void HLSLGenerator::OutputExpression(HLSLExpression* expression)
{
name = m_tex2DMSFetchFunction;
}
else if (String_Equal(name, "tex2DMSsize"))
{
name = m_tex2DMSSizeFunction;
}
else if (String_Equal(name, "tex3D"))
{
name = m_tex3DFunction;
@@ -627,6 +664,10 @@ void HLSLGenerator::OutputExpression(HLSLExpression* expression)
{
name = m_tex3DBiasFunction;
}
else if (String_Equal(name, "tex3Dsize"))
{
name = m_tex3DSizeFunction;
}
else if (String_Equal(name, "texCUBE"))
{
name = m_texCubeFunction;
@@ -639,6 +680,10 @@ void HLSLGenerator::OutputExpression(HLSLExpression* expression)
{
name = m_texCubeBiasFunction;
}
else if (String_Equal(name, "texCUBEsize"))
{
name = m_texCubeSizeFunction;
}
}
m_writer.Write("%s(", name);
OutputExpressionList(functionCall->argument);
@@ -1016,6 +1061,28 @@ void HLSLGenerator::OutputDeclarationType(const HLSLType& type)
m_writer.Write("static ");
}

// Interpolation modifiers.
if (type.flags & HLSLTypeFlag_Centroid)
{
m_writer.Write("centroid ");
}
if (type.flags & HLSLTypeFlag_Linear)
{
m_writer.Write("linear ");
}
if (type.flags & HLSLTypeFlag_NoInterpolation)
{
m_writer.Write("nointerpolation ");
}
if (type.flags & HLSLTypeFlag_NoPerspective)
{
m_writer.Write("noperspective ");
}
if (type.flags & HLSLTypeFlag_Sample) // @@ Only in shader model >= 4.1
{
m_writer.Write("sample ");
}

m_writer.Write("%s ", typeName);
}

@@ -80,14 +80,18 @@ class HLSLGenerator
char m_tex2DBiasFunction[64];
char m_tex2DGradFunction[64];
char m_tex2DGatherFunction[64];
char m_tex2DSizeFunction[64];
char m_tex2DCmpFunction[64];
char m_tex2DMSFetchFunction[64];
char m_tex2DMSSizeFunction[64];
char m_tex3DFunction[64];
char m_tex3DLodFunction[64];
char m_tex3DBiasFunction[64];
char m_tex3DSizeFunction[64];
char m_texCubeFunction[64];
char m_texCubeLodFunction[64];
char m_texCubeBiasFunction[64];
char m_texCubeSizeFunction[64];
};

} // M4
@@ -526,21 +526,22 @@ const Intrinsic _intrinsic[] =
Intrinsic("tex2Dgrad", HLSLBaseType_Float4, HLSLBaseType_Sampler2D, HLSLBaseType_Float2, HLSLBaseType_Float2, HLSLBaseType_Float2),
Intrinsic("tex2Dgather", HLSLBaseType_Float4, HLSLBaseType_Sampler2D, HLSLBaseType_Float2, HLSLBaseType_Int),
Intrinsic("tex2Dgather", HLSLBaseType_Float4, HLSLBaseType_Sampler2D, HLSLBaseType_Float2, HLSLBaseType_Int2, HLSLBaseType_Int), // With offset.
//Intrinsic("tex2Dsize", HLSLBaseType_Int2, HLSLBaseType_Sampler2D, HLSLBaseType_Int),
Intrinsic("tex2Dsize", HLSLBaseType_Int2, HLSLBaseType_Sampler2D),

Intrinsic("tex2Dcmp", HLSLBaseType_Float4, HLSLBaseType_Sampler2DShadow, HLSLBaseType_Float4), // @@ IC: This really takes a float3 (uvz) and returns a float.

Intrinsic("tex2DMSfetch", HLSLBaseType_Float4, HLSLBaseType_Sampler2DMS, HLSLBaseType_Int2, HLSLBaseType_Int),
//Intrinsic("tex2DMSsize", HLSLBaseType_Int3, HLSLBaseType_Sampler2DMS),
Intrinsic("tex2DMSsize", HLSLBaseType_Int3, HLSLBaseType_Sampler2DMS),

Intrinsic("tex3D", HLSLBaseType_Float4, HLSLBaseType_Sampler3D, HLSLBaseType_Float3),
Intrinsic("tex3Dlod", HLSLBaseType_Float4, HLSLBaseType_Sampler3D, HLSLBaseType_Float4),
Intrinsic("tex3Dbias", HLSLBaseType_Float4, HLSLBaseType_Sampler3D, HLSLBaseType_Float4),
//Intrinsic("tex3Dsize", HLSLBaseType_Int3, HLSLBaseType_Sampler3D),
Intrinsic("tex3Dsize", HLSLBaseType_Int3, HLSLBaseType_Sampler3D),

Intrinsic("texCUBE", HLSLBaseType_Float4, HLSLBaseType_SamplerCube, HLSLBaseType_Float3),
Intrinsic("texCUBElod", HLSLBaseType_Float4, HLSLBaseType_SamplerCube, HLSLBaseType_Float4),
Intrinsic("texCUBEbias", HLSLBaseType_Float4, HLSLBaseType_SamplerCube, HLSLBaseType_Float4),
Intrinsic("texCUBEsize", HLSLBaseType_Int, HLSLBaseType_SamplerCube),

Intrinsic( "sincos", HLSLBaseType_Void, HLSLBaseType_Float, HLSLBaseType_Float, HLSLBaseType_Float ),
Intrinsic( "sincos", HLSLBaseType_Void, HLSLBaseType_Float2, HLSLBaseType_Float, HLSLBaseType_Float2 ),
@@ -1040,6 +1041,7 @@ HLSLParser::HLSLParser(Allocator* allocator, const char* fileName, const char* b
m_functions(allocator)
{
m_numGlobals = 0;
m_tree = NULL;
}

bool HLSLParser::Accept(int token)
@@ -1352,6 +1354,9 @@ bool HLSLParser::ParseTopLevel(HLSLStatement*& statement)
else if (ParsePipeline(statement)) {
doesNotExpectSemicolon = true;
}
else if (ParseStage(statement)) {
doesNotExpectSemicolon = true;
}

if (statement != NULL) {
statement->attributes = attributes;
@@ -1558,12 +1563,13 @@ bool HLSLParser::ParseStatement(HLSLStatement*& statement, const HLSLType& retur


// IC: This is only used in block statements, or within control flow statements. So, it doesn't support semantics or layout modifiers.
// @@ We should add suport for semantics for inline input/output declarations.
bool HLSLParser::ParseDeclaration(HLSLDeclaration*& declaration)
{
const char* fileName = GetFileName();
int line = GetLineNumber();

HLSLType type;
HLSLType type;
if (!AcceptType(/*allowVoid=*/false, type.baseType, type.typeName, &type.flags))
{
return false;
@@ -1707,16 +1713,17 @@ bool HLSLParser::ParseExpression(HLSLExpression*& expression)
{
return false;
}

HLSLBinaryOp assignOp;
while (AcceptAssign(assignOp))
if (AcceptAssign(assignOp))
{
HLSLExpression* expression2 = NULL;
if (!ParseBinaryExpression(0, expression2))
if (!ParseExpression(expression2))
{
return false;
}
HLSLBinaryExpression* binaryExpression = m_tree->AddNode<HLSLBinaryExpression>(expression->fileName, expression->line);
binaryExpression->binaryOp = assignOp;
binaryExpression->binaryOp = assignOp;
binaryExpression->expression1 = expression;
binaryExpression->expression2 = expression2;
// This type is not strictly correct, since the type should be a reference.
@@ -1733,6 +1740,7 @@ bool HLSLParser::ParseExpression(HLSLExpression*& expression)

expression = binaryExpression;
}

return true;
}

@@ -2470,7 +2478,7 @@ bool HLSLParser::ParsePipeline(HLSLStatement*& statement)
return false;
}

// Optional pass name.
// Optional pipeline name.
const char* pipelineName = NULL;
AcceptIdentifier(pipelineName);

@@ -2796,6 +2804,44 @@ bool HLSLParser::ParseAttributeBlock(HLSLAttribute*& attribute)
return true;
}

bool HLSLParser::ParseStage(HLSLStatement*& statement)
{
if (!Accept("stage"))
{
return false;
}

// Required stage name.
const char* stageName = NULL;
if (!ExpectIdentifier(stageName))
{
return false;
}

if (!Expect('{'))
{
return false;
}

HLSLStage* stage = m_tree->AddNode<HLSLStage>(GetFileName(), GetLineNumber());
stage->name = stageName;

BeginScope();

HLSLType voidType(HLSLBaseType_Void);
if (!Expect('{') || !ParseBlock(stage->statement, voidType))
{
return false;
}

EndScope();

// @@ To finish the stage definition we should traverse the statements recursively (including function calls) and find all the input/output declarations.

statement = stage;
return true;
}




@@ -2852,6 +2898,16 @@ bool HLSLParser::AcceptTypeModifier(int& flags)
//flags |= HLSLTypeFlag_Uniform; // @@ Ignored. In HLSL all functions are inline.
return true;
}
/*else if (Accept("in"))
{
flags |= HLSLTypeFlag_Input;
return true;
}
else if (Accept("out"))
{
flags |= HLSLTypeFlag_Output;
return true;
}*/

// Not an usage keyword.
return false;
@@ -86,6 +86,7 @@ class HLSLParser
bool ParseTechnique(HLSLStatement*& statement);
bool ParsePass(HLSLPass*& pass);
bool ParsePipeline(HLSLStatement*& pipeline);
bool ParseStage(HLSLStatement*& stage);

bool ParseAttributeList(HLSLAttribute*& attribute);
bool ParseAttributeBlock(HLSLAttribute*& attribute);
@@ -132,7 +133,6 @@ class HLSLParser
int m_numGlobals;

HLSLTree* m_tree;

};

}
@@ -517,7 +517,7 @@ void HLSLTokenizer::Error(const char* format, ...)
int result = vsnprintf(buffer, sizeof(buffer) - 1, format, args);
va_end(args);

Log_Error("%s(%d) : %s", m_fileName, m_lineNumber, buffer);
Log_Error("%s(%d) : %s\n", m_fileName, m_lineNumber, buffer);
}

void HLSLTokenizer::GetTokenName(char buffer[s_maxIdentifier]) const

0 comments on commit 6d8eef7

Please sign in to comment.