ES31: Add glGetProgramResourceIndex API
Add API entry and validation checks(GLES 3.1 section 7.3).
Add the first 2 interfaces(PROGRAM_INPUT and PROGRAM_OUTPUT) implementation.
BUG=angleproject:1920
Change-Id: Ib2dedded9fd79b315e9f38de7c27a5e4ec4c6066
Reviewed-on: https://chromium-review.googlesource.com/453085
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp
index 4770a8d..396d8c6 100644
--- a/src/libANGLE/Program.cpp
+++ b/src/libANGLE/Program.cpp
@@ -132,6 +132,33 @@
return gl::CompareShaderVar(*x.varying, *y.varying);
}
+template <typename VarT>
+GLuint GetResourceIndexFromName(const std::vector<VarT> &list, const std::string &name)
+{
+ size_t subscript = GL_INVALID_INDEX;
+ std::string baseName = ParseResourceName(name, &subscript);
+
+ // The app is not allowed to specify array indices other than 0 for arrays of basic types
+ if (subscript != 0 && subscript != GL_INVALID_INDEX)
+ {
+ return GL_INVALID_INDEX;
+ }
+
+ for (size_t index = 0; index < list.size(); index++)
+ {
+ const VarT &resource = list[index];
+ if (resource.name == baseName)
+ {
+ if (resource.isArray() || subscript == GL_INVALID_INDEX)
+ {
+ return static_cast<GLuint>(index);
+ }
+ }
+ }
+
+ return GL_INVALID_INDEX;
+}
+
} // anonymous namespace
const char *const g_fakepath = "C:\\fakepath";
@@ -255,7 +282,7 @@
GLint ProgramState::getUniformLocation(const std::string &name) const
{
size_t subscript = GL_INVALID_INDEX;
- std::string baseName = ParseUniformName(name, &subscript);
+ std::string baseName = ParseResourceName(name, &subscript);
for (size_t location = 0; location < mUniformLocations.size(); ++location)
{
@@ -292,28 +319,7 @@
GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
{
- size_t subscript = GL_INVALID_INDEX;
- std::string baseName = ParseUniformName(name, &subscript);
-
- // The app is not allowed to specify array indices other than 0 for arrays of basic types
- if (subscript != 0 && subscript != GL_INVALID_INDEX)
- {
- return GL_INVALID_INDEX;
- }
-
- for (size_t index = 0; index < mUniforms.size(); index++)
- {
- const LinkedUniform &uniform = mUniforms[index];
- if (uniform.name == baseName)
- {
- if (uniform.isArray() || subscript == GL_INVALID_INDEX)
- {
- return static_cast<GLuint>(index);
- }
- }
- }
-
- return GL_INVALID_INDEX;
+ return GetResourceIndexFromName(mUniforms, name);
}
GLuint ProgramState::getUniformIndexFromLocation(GLint location) const
@@ -487,7 +493,7 @@
void Program::bindUniformLocation(GLuint index, const char *name)
{
// Bind the base uniform name only since array indices other than 0 cannot be bound
- mUniformLocationBindings.bindLocation(index, ParseUniformName(name, nullptr));
+ mUniformLocationBindings.bindLocation(index, ParseResourceName(name, nullptr));
}
void Program::bindFragmentInputLocation(GLint index, const char *name)
@@ -720,6 +726,7 @@
mState.mUniformLocations.clear();
mState.mUniformBlocks.clear();
mState.mOutputVariables.clear();
+ mState.mOutputLocations.clear();
mState.mComputeShaderLocalSize.fill(1);
mState.mSamplerBindings.clear();
@@ -865,6 +872,16 @@
stream.readInt(&mState.mTransformFeedbackBufferMode);
+ unsigned int outputCount = stream.readInt<unsigned int>();
+ ASSERT(mState.mOutputVariables.empty());
+ for (unsigned int outputIndex = 0; outputIndex < outputCount; ++outputIndex)
+ {
+ sh::OutputVariable output;
+ LoadShaderVar(&stream, &output);
+ output.location = stream.readInt<int>();
+ mState.mOutputVariables.push_back(output);
+ }
+
unsigned int outputVarCount = stream.readInt<unsigned int>();
for (unsigned int outputIndex = 0; outputIndex < outputVarCount; ++outputIndex)
{
@@ -873,7 +890,7 @@
stream.readInt(&locationData.element);
stream.readInt(&locationData.index);
stream.readString(&locationData.name);
- mState.mOutputVariables[locationIndex] = locationData;
+ mState.mOutputLocations[locationIndex] = locationData;
}
stream.readInt(&mState.mSamplerUniformRange.start);
@@ -991,7 +1008,14 @@
stream.writeInt(mState.mTransformFeedbackBufferMode);
stream.writeInt(mState.mOutputVariables.size());
- for (const auto &outputPair : mState.mOutputVariables)
+ for (const sh::OutputVariable &output : mState.mOutputVariables)
+ {
+ WriteShaderVar(&stream, output);
+ stream.writeInt(output.location);
+ }
+
+ stream.writeInt(mState.mOutputLocations.size());
+ for (const auto &outputPair : mState.mOutputLocations)
{
stream.writeInt(outputPair.first);
stream.writeIntOrNegOne(outputPair.second.element);
@@ -1222,11 +1246,29 @@
return static_cast<GLint>(maxLength);
}
+GLuint Program::getInputResourceIndex(const GLchar *name) const
+{
+ for (GLuint attributeIndex = 0; attributeIndex < mState.mAttributes.size(); ++attributeIndex)
+ {
+ const sh::Attribute &attribute = mState.mAttributes[attributeIndex];
+ if (attribute.name == name)
+ {
+ return attributeIndex;
+ }
+ }
+ return GL_INVALID_INDEX;
+}
+
+GLuint Program::getOutputResourceIndex(const GLchar *name) const
+{
+ return GetResourceIndexFromName(mState.mOutputVariables, std::string(name));
+}
+
GLint Program::getFragDataLocation(const std::string &name) const
{
std::string baseName(name);
unsigned int arrayIndex = ParseAndStripArrayIndex(&baseName);
- for (auto outputPair : mState.mOutputVariables)
+ for (auto outputPair : mState.mOutputLocations)
{
const VariableLocation &outputVariable = outputPair.second;
if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element))
@@ -1679,7 +1721,7 @@
GLuint Program::getUniformBlockIndex(const std::string &name) const
{
size_t subscript = GL_INVALID_INDEX;
- std::string baseName = ParseUniformName(name, &subscript);
+ std::string baseName = ParseResourceName(name, &subscript);
unsigned int numUniformBlocks = static_cast<unsigned int>(mState.mUniformBlocks.size());
for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
@@ -2505,14 +2547,13 @@
if (fragmentShader->getShaderVersion() == 100)
return;
- const auto &shaderOutputVars = fragmentShader->getActiveOutputVariables();
-
+ mState.mOutputVariables = fragmentShader->getActiveOutputVariables();
// TODO(jmadill): any caps validation here?
- for (unsigned int outputVariableIndex = 0; outputVariableIndex < shaderOutputVars.size();
+ for (unsigned int outputVariableIndex = 0; outputVariableIndex < mState.mOutputVariables.size();
outputVariableIndex++)
{
- const sh::OutputVariable &outputVariable = shaderOutputVars[outputVariableIndex];
+ const sh::OutputVariable &outputVariable = mState.mOutputVariables[outputVariableIndex];
// Don't store outputs for gl_FragDepth, gl_FragColor, etc.
if (outputVariable.isBuiltIn())
@@ -2525,9 +2566,9 @@
elementIndex++)
{
const int location = baseLocation + elementIndex;
- ASSERT(mState.mOutputVariables.count(location) == 0);
+ ASSERT(mState.mOutputLocations.count(location) == 0);
unsigned int element = outputVariable.isArray() ? elementIndex : GL_INVALID_INDEX;
- mState.mOutputVariables[location] =
+ mState.mOutputLocations[location] =
VariableLocation(outputVariable.name, element, outputVariableIndex);
}
}