Commit 31b65a76 by Alexis Hetu Committed by Alexis Hétu

Transform feedback varying validation code

Proper validation of varyings used for transform feedback was added. Simple types, as well as arrays and array elements are allowed. Change-Id: I83ceb5eb19bf5691264ab0e142c3cc6a7debda4c Reviewed-on: https://swiftshader-review.googlesource.com/5058Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent 2cfadc68
...@@ -141,8 +141,8 @@ namespace es2 ...@@ -141,8 +141,8 @@ namespace es2
{ {
} }
LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size) LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, int reg, int col)
: name(name), type(type), size(size) : name(name), type(type), size(size), reg(reg), col(col)
{ {
} }
...@@ -156,6 +156,7 @@ namespace es2 ...@@ -156,6 +156,7 @@ namespace es2
vertexBinary = 0; vertexBinary = 0;
transformFeedbackBufferMode = GL_INTERLEAVED_ATTRIBS; transformFeedbackBufferMode = GL_INTERLEAVED_ATTRIBS;
totalLinkedVaryingsComponents = 0;
infoLog = 0; infoLog = 0;
validated = false; validated = false;
...@@ -1268,19 +1269,71 @@ namespace es2 ...@@ -1268,19 +1269,71 @@ namespace es2
return true; return true;
} }
bool Program::gatherTransformFeedbackLinkedVaryings() bool Program::linkTransformFeedback()
{ {
// Varyings have already been validated in linkVaryings() size_t totalComponents = 0;
glsl::VaryingList &vsVaryings = vertexShader->varyings; totalLinkedVaryingsComponents = 0;
std::set<std::string> uniqueNames;
for(std::vector<std::string>::iterator trVar = transformFeedbackVaryings.begin(); trVar != transformFeedbackVaryings.end(); ++trVar) for(const std::string &indexedTfVaryingName : transformFeedbackVaryings)
{ {
size_t subscript = GL_INVALID_INDEX;
std::string tfVaryingName = es2::ParseUniformName(indexedTfVaryingName, &subscript);
bool hasSubscript = (subscript != GL_INVALID_INDEX);
if(tfVaryingName.find('[') != std::string::npos)
{
appendToInfoLog("Capture of array sub-elements is undefined and not supported.");
return false;
}
bool found = false; bool found = false;
for(glsl::VaryingList::iterator var = vsVaryings.begin(); var != vsVaryings.end(); ++var) for(const glsl::Varying varying : vertexShader->varyings)
{ {
if(var->name == (*trVar)) if(tfVaryingName == varying.name)
{ {
transformFeedbackLinkedVaryings.push_back(LinkedVarying(var->name, var->type, var->size())); if(uniqueNames.count(indexedTfVaryingName) > 0)
{
appendToInfoLog("Two transform feedback varyings specify the same output variable (%s)", indexedTfVaryingName.c_str());
return false;
}
uniqueNames.insert(indexedTfVaryingName);
if(hasSubscript && ((static_cast<int>(subscript)) >= varying.size()))
{
appendToInfoLog("Specified transform feedback varying index out of bounds (%s)", indexedTfVaryingName.c_str());
return false;
}
size_t size = hasSubscript ? 1 : varying.size();
size_t rowCount = VariableRowCount(varying.type);
size_t colCount = VariableColumnCount(varying.type);
size_t componentCount = rowCount * colCount * size;
if(transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
componentCount > sw::MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS)
{
appendToInfoLog("Transform feedback varying's %s components (%d) exceed the maximum separate components (%d).",
varying.name.c_str(), componentCount, sw::MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS);
return false;
}
totalComponents += componentCount;
int reg = varying.reg;
if(hasSubscript)
{
reg += rowCount > 1 ? colCount * subscript : subscript;
}
int col = varying.col;
if(tfVaryingName == "gl_PointSize")
{
// Point size is stored in the y element of the vector, not the x element
col = 1; // FIXME: varying.col could already contain this information
}
transformFeedbackLinkedVaryings.push_back(LinkedVarying(varying.name, varying.type, size, reg, col));
found = true; found = true;
break; break;
} }
...@@ -1288,10 +1341,21 @@ namespace es2 ...@@ -1288,10 +1341,21 @@ namespace es2
if(!found) if(!found)
{ {
appendToInfoLog("Transform feedback varying %s does not exist in the vertex shader.", tfVaryingName.c_str());
return false; return false;
} }
} }
if(transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
totalComponents > sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS)
{
appendToInfoLog("Transform feedback varying total components (%d) exceed the maximum separate components (%d).",
totalComponents, sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS);
return false;
}
totalLinkedVaryingsComponents = totalComponents;
return true; return true;
} }
...@@ -1343,7 +1407,7 @@ namespace es2 ...@@ -1343,7 +1407,7 @@ namespace es2
return; return;
} }
if(!gatherTransformFeedbackLinkedVaryings()) if(!linkTransformFeedback())
{ {
return; return;
} }
......
...@@ -102,13 +102,16 @@ namespace es2 ...@@ -102,13 +102,16 @@ namespace es2
struct LinkedVarying struct LinkedVarying
{ {
LinkedVarying(); LinkedVarying();
LinkedVarying(const std::string &name, GLenum type, GLsizei size); LinkedVarying(const std::string &name, GLenum type, GLsizei size, int reg, int col);
// Original GL name // Original GL name
std::string name; std::string name;
GLenum type; GLenum type;
GLsizei size; GLsizei size;
int reg; // First varying register, assigned during link
int col; // First register element, assigned during link
}; };
class Program class Program
...@@ -215,7 +218,7 @@ namespace es2 ...@@ -215,7 +218,7 @@ namespace es2
void resetUniformBlockBindings(); void resetUniformBlockBindings();
bool linkVaryings(); bool linkVaryings();
bool gatherTransformFeedbackLinkedVaryings(); bool linkTransformFeedback();
bool linkAttributes(); bool linkAttributes();
int getAttributeBinding(const glsl::Attribute &attribute); int getAttributeBinding(const glsl::Attribute &attribute);
...@@ -278,6 +281,7 @@ namespace es2 ...@@ -278,6 +281,7 @@ namespace es2
std::vector<std::string> transformFeedbackVaryings; std::vector<std::string> transformFeedbackVaryings;
GLenum transformFeedbackBufferMode; GLenum transformFeedbackBufferMode;
size_t totalLinkedVaryingsComponents;
struct Sampler struct Sampler
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment