Added transform feedback shader generation.
BUG=angle:495
Change-Id: I41a0177fd3eb43c9f4ab9e54faeadac3eb483c2c
Reviewed-on: https://chromium-review.googlesource.com/185035
Reviewed-by: Shannon Woods <shannonwoods@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libGLESv2/DynamicHLSL.cpp b/src/libGLESv2/DynamicHLSL.cpp
index 585c015..06e95ac 100644
--- a/src/libGLESv2/DynamicHLSL.cpp
+++ b/src/libGLESv2/DynamicHLSL.cpp
@@ -90,33 +90,58 @@
{
}
-// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
-// Returns the number of used varying registers, or -1 if unsuccesful
-int DynamicHLSL::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader)
+static bool packVarying(sh::Varying *varying, const int maxVaryingVectors, const sh::ShaderVariable *packing[][4])
{
- const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
+ GLenum transposedType = TransposeMatrixType(varying->type);
- fragmentShader->resetVaryingsRegisterAssignment();
+ // matrices within varying structs are not transposed
+ int registers = (varying->isStruct() ? sh::HLSLVariableRegisterCount(*varying) : gl::VariableRowCount(transposedType)) * varying->elementCount();
+ int elements = (varying->isStruct() ? 4 : VariableColumnCount(transposedType));
+ bool success = false;
- for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
+ if (elements == 2 || elements == 3 || elements == 4)
{
- sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
- GLenum transposedType = TransposeMatrixType(varying->type);
-
- // matrices within varying structs are not transposed
- int registers = (varying->isStruct() ? sh::HLSLVariableRegisterCount(*varying) : gl::VariableRowCount(transposedType)) * varying->elementCount();
- int elements = (varying->isStruct() ? 4 : VariableColumnCount(transposedType));
- bool success = false;
-
- if (elements == 2 || elements == 3 || elements == 4)
+ for (int r = 0; r <= maxVaryingVectors - registers && !success; r++)
{
- for (int r = 0; r <= maxVaryingVectors - registers && !success; r++)
+ bool available = true;
+
+ for (int y = 0; y < registers && available; y++)
+ {
+ for (int x = 0; x < elements && available; x++)
+ {
+ if (packing[r + y][x])
+ {
+ available = false;
+ }
+ }
+ }
+
+ if (available)
+ {
+ varying->registerIndex = r;
+ varying->elementIndex = 0;
+
+ for (int y = 0; y < registers; y++)
+ {
+ for (int x = 0; x < elements; x++)
+ {
+ packing[r + y][x] = &*varying;
+ }
+ }
+
+ success = true;
+ }
+ }
+
+ if (!success && elements == 2)
+ {
+ for (int r = maxVaryingVectors - registers; r >= 0 && !success; r--)
{
bool available = true;
for (int y = 0; y < registers && available; y++)
{
- for (int x = 0; x < elements && available; x++)
+ for (int x = 2; x < 4 && available; x++)
{
if (packing[r + y][x])
{
@@ -128,11 +153,11 @@
if (available)
{
varying->registerIndex = r;
- varying->elementIndex = 0;
+ varying->elementIndex = 2;
for (int y = 0; y < registers; y++)
{
- for (int x = 0; x < elements; x++)
+ for (int x = 2; x < 4; x++)
{
packing[r + y][x] = &*varying;
}
@@ -141,96 +166,113 @@
success = true;
}
}
-
- if (!success && elements == 2)
- {
- for (int r = maxVaryingVectors - registers; r >= 0 && !success; r--)
- {
- bool available = true;
-
- for (int y = 0; y < registers && available; y++)
- {
- for (int x = 2; x < 4 && available; x++)
- {
- if (packing[r + y][x])
- {
- available = false;
- }
- }
- }
-
- if (available)
- {
- varying->registerIndex = r;
- varying->elementIndex = 2;
-
- for (int y = 0; y < registers; y++)
- {
- for (int x = 2; x < 4; x++)
- {
- packing[r + y][x] = &*varying;
- }
- }
-
- success = true;
- }
- }
- }
}
- else if (elements == 1)
+ }
+ else if (elements == 1)
+ {
+ int space[4] = { 0 };
+
+ for (int y = 0; y < maxVaryingVectors; y++)
{
- int space[4] = {0};
-
- for (int y = 0; y < maxVaryingVectors; y++)
- {
- for (int x = 0; x < 4; x++)
- {
- space[x] += packing[y][x] ? 0 : 1;
- }
- }
-
- int column = 0;
-
for (int x = 0; x < 4; x++)
{
- if (space[x] >= registers && space[x] < space[column])
- {
- column = x;
- }
- }
-
- if (space[column] >= registers)
- {
- for (int r = 0; r < maxVaryingVectors; r++)
- {
- if (!packing[r][column])
- {
- varying->registerIndex = r;
-
- for (int y = r; y < r + registers; y++)
- {
- packing[y][column] = &*varying;
- }
-
- break;
- }
- }
-
- varying->elementIndex = column;
-
- success = true;
+ space[x] += packing[y][x] ? 0 : 1;
}
}
- else UNREACHABLE();
- if (!success)
+ int column = 0;
+
+ for (int x = 0; x < 4; x++)
+ {
+ if (space[x] >= registers && space[x] < space[column])
+ {
+ column = x;
+ }
+ }
+
+ if (space[column] >= registers)
+ {
+ for (int r = 0; r < maxVaryingVectors; r++)
+ {
+ if (!packing[r][column])
+ {
+ varying->registerIndex = r;
+
+ for (int y = r; y < r + registers; y++)
+ {
+ packing[y][column] = &*varying;
+ }
+
+ break;
+ }
+ }
+
+ varying->elementIndex = column;
+
+ success = true;
+ }
+ }
+ else UNREACHABLE();
+
+ return success;
+}
+
+// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
+// Returns the number of used varying registers, or -1 if unsuccesful
+int DynamicHLSL::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader,
+ VertexShader *vertexShader, const std::vector<std::string>& transformFeedbackVaryings)
+{
+ const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
+
+ vertexShader->resetVaryingsRegisterAssignment();
+ fragmentShader->resetVaryingsRegisterAssignment();
+
+ std::set<std::string> packedVaryings;
+
+ for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
+ {
+ sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
+ if (packVarying(varying, maxVaryingVectors, packing))
+ {
+ packedVaryings.insert(varying->name);
+ }
+ else
{
infoLog.append("Could not pack varying %s", varying->name.c_str());
-
return -1;
}
}
+ for (unsigned int feedbackVaryingIndex = 0; feedbackVaryingIndex < transformFeedbackVaryings.size(); feedbackVaryingIndex++)
+ {
+ const std::string &transformFeedbackVarying = transformFeedbackVaryings[feedbackVaryingIndex];
+ if (packedVaryings.find(transformFeedbackVarying) == packedVaryings.end())
+ {
+ bool found = false;
+ for (unsigned int varyingIndex = 0; varyingIndex < vertexShader->mVaryings.size(); varyingIndex++)
+ {
+ sh::Varying *varying = &vertexShader->mVaryings[varyingIndex];
+ if (transformFeedbackVarying == varying->name)
+ {
+ if (!packVarying(varying, maxVaryingVectors, packing))
+ {
+ infoLog.append("Could not pack varying %s", varying->name.c_str());
+ return -1;
+ }
+
+ found = true;
+ break;
+ }
+ }
+
+ if (!found && transformFeedbackVarying != "gl_Position" && transformFeedbackVarying != "gl_PointSize")
+ {
+ infoLog.append("Transform feedback varying %s does not exist in the vertex shader.", transformFeedbackVarying.c_str());
+ return -1;
+ }
+ }
+ }
+
// Return the number of used registers
int registers = 0;
@@ -245,19 +287,21 @@
return registers;
}
-std::string DynamicHLSL::generateVaryingHLSL(FragmentShader *fragmentShader, const std::string &varyingSemantic) const
+std::string DynamicHLSL::generateVaryingHLSL(VertexShader *shader, const std::string &varyingSemantic,
+ std::vector<LinkedVarying> *linkedVaryings) const
{
std::string varyingHLSL;
- for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
+ for (unsigned int varyingIndex = 0; varyingIndex < shader->mVaryings.size(); varyingIndex++)
{
- sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
+ sh::Varying *varying = &shader->mVaryings[varyingIndex];
if (varying->registerAssigned())
{
+ GLenum transposedType = TransposeMatrixType(varying->type);
+ int variableRows = (varying->isStruct() ? 1 : VariableRowCount(transposedType));
+
for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++)
{
- GLenum transposedType = TransposeMatrixType(varying->type);
- int variableRows = (varying->isStruct() ? 1 : VariableRowCount(transposedType));
for (int row = 0; row < variableRows; row++)
{
switch (varying->interpolation)
@@ -268,7 +312,8 @@
default: UNREACHABLE();
}
- std::string n = Str(varying->registerIndex + elementIndex * variableRows + row);
+ unsigned int semanticIndex = elementIndex * variableRows + varying->registerIndex + row;
+ std::string n = Str(semanticIndex);
std::string typeString;
@@ -287,8 +332,14 @@
varyingHLSL += typeString + " v" + n + " : " + varyingSemantic + n + ";\n";
}
}
+
+ if (linkedVaryings)
+ {
+ linkedVaryings->push_back(LinkedVarying(varying->name, varying->type, varying->elementCount(),
+ varyingSemantic, varying->registerIndex,
+ variableRows * varying->elementCount()));
+ }
}
- else UNREACHABLE();
}
return varyingHLSL;
@@ -361,6 +412,8 @@
bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const sh::ShaderVariable *packing[][4],
std::string& pixelHLSL, std::string& vertexHLSL,
FragmentShader *fragmentShader, VertexShader *vertexShader,
+ const std::vector<std::string>& transformFeedbackVaryings,
+ std::vector<LinkedVarying> *linkedVaryings,
std::map<int, VariableLocation> *programOutputVars) const
{
if (pixelHLSL.empty() || vertexHLSL.empty())
@@ -400,32 +453,40 @@
std::string varyingSemantic = (vertexShader->mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD";
std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR";
- std::string positionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION";
+ std::string dxPositionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION";
std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
- std::string varyingHLSL = generateVaryingHLSL(fragmentShader, varyingSemantic);
+ std::string varyingHLSL = generateVaryingHLSL(vertexShader, varyingSemantic, linkedVaryings);
// special varyings that use reserved registers
int reservedRegisterIndex = registers;
- std::string fragCoordSemantic;
- std::string pointCoordSemantic;
+ unsigned int glPositionSemanticIndex = reservedRegisterIndex++;
+ std::string glPositionSemantic = varyingSemantic;
+
+ std::string fragCoordSemantic;
+ unsigned int fragCoordSemanticIndex = 0;
if (fragmentShader->mUsesFragCoord)
{
- fragCoordSemantic = varyingSemantic + Str(reservedRegisterIndex++);
+ fragCoordSemanticIndex = reservedRegisterIndex++;
+ fragCoordSemantic = varyingSemantic;
}
+ std::string pointCoordSemantic;
+ unsigned int pointCoordSemanticIndex = 0;
if (fragmentShader->mUsesPointCoord)
{
// Shader model 3 uses a special TEXCOORD semantic for point sprite texcoords.
// In DX11 we compute this in the GS.
if (shaderModel == 3)
{
+ pointCoordSemanticIndex = 0;
pointCoordSemantic = "TEXCOORD0";
}
else if (shaderModel >= 4)
{
- pointCoordSemantic = varyingSemantic + Str(reservedRegisterIndex++);
+ pointCoordSemanticIndex = reservedRegisterIndex++;
+ pointCoordSemantic = varyingSemantic;
}
}
@@ -437,24 +498,31 @@
if (shaderModel < 4)
{
- vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n";
+ vertexHLSL += " float4 _dx_Position : " + dxPositionSemantic + ";\n";
+ vertexHLSL += " float4 gl_Position : " + glPositionSemantic + Str(glPositionSemanticIndex) + ";\n";
+ linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, glPositionSemantic, glPositionSemanticIndex, 1));
+
}
vertexHLSL += varyingHLSL;
if (fragmentShader->mUsesFragCoord)
{
- vertexHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
+ vertexHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + Str(fragCoordSemanticIndex) + ";\n";
+ linkedVaryings->push_back(LinkedVarying("gl_FragCoord", GL_FLOAT_VEC4, 1, fragCoordSemantic, fragCoordSemanticIndex, 1));
}
if (vertexShader->mUsesPointSize && shaderModel >= 3)
{
vertexHLSL += " float gl_PointSize : PSIZE;\n";
+ linkedVaryings->push_back(LinkedVarying("gl_PointSize", GL_FLOAT, 1, "PSIZE", 0, 1));
}
if (shaderModel >= 4)
{
- vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n";
+ vertexHLSL += " float4 _dx_Position : " + dxPositionSemantic + ";\n";
+ vertexHLSL += " float4 gl_Position : " + glPositionSemantic + Str(glPositionSemanticIndex) + ";\n";
+ linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, glPositionSemantic, glPositionSemanticIndex, 1));
}
vertexHLSL += "};\n"
@@ -469,10 +537,11 @@
" gl_main();\n"
"\n"
" VS_OUTPUT output;\n"
- " output.gl_Position.x = gl_Position.x;\n"
- " output.gl_Position.y = -gl_Position.y;\n"
- " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
- " output.gl_Position.w = gl_Position.w;\n";
+ " output.gl_Position = gl_Position;\n"
+ " output._dx_Position.x = gl_Position.x;\n"
+ " output._dx_Position.y = -gl_Position.y;\n"
+ " output._dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
+ " output._dx_Position.w = gl_Position.w;\n";
}
else
{
@@ -480,10 +549,11 @@
" gl_main();\n"
"\n"
" VS_OUTPUT output;\n"
- " output.gl_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n"
- " output.gl_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n"
- " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
- " output.gl_Position.w = gl_Position.w;\n";
+ " output.gl_Position = gl_Position;\n"
+ " output._dx_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n"
+ " output._dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n"
+ " output._dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
+ " output._dx_Position.w = gl_Position.w;\n";
}
if (vertexShader->mUsesPointSize && shaderModel >= 3)
@@ -574,7 +644,7 @@
if (fragmentShader->mUsesPointCoord && shaderModel >= 3)
{
- pixelHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n";
+ pixelHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + Str(pointCoordSemanticIndex) + ";\n";
}
// Must consume the PSIZE element if the geometry shader is not active
@@ -842,7 +912,7 @@
"struct GS_INPUT\n"
"{\n";
- std::string varyingHLSL = generateVaryingHLSL(fragmentShader, varyingSemantic);
+ std::string varyingHLSL = generateVaryingHLSL(vertexShader, varyingSemantic, NULL);
geomHLSL += varyingHLSL;