Commit 4a3c2341 by Jamie Madill

Program: Clean up UBO info gathering.

The data size & block member info was getting messy, so clean up how we query this from the Impl layer. Also remove the register information from gl::UniformBlock, moving it into the D3D-only world. BUG=angleproject:1172 Change-Id: I40af658ebbd6b7c1a4251906a387ebcbb621cf77 Reviewed-on: https://chromium-review.googlesource.com/304150Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Tryjob-Request: Jamie Madill <jmadill@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org>
parent e826b9f7
......@@ -639,8 +639,24 @@ std::string ParseUniformName(const std::string &name, size_t *outSubscript)
return name.substr(0, open);
}
unsigned int ParseAndStripArrayIndex(std::string *name)
{
unsigned int subscript = GL_INVALID_INDEX;
// Strip any trailing array operator and retrieve the subscript
size_t open = name->find_last_of('[');
size_t close = name->find_last_of(']');
if (open != std::string::npos && close == name->length() - 1)
{
subscript = atoi(name->c_str() + open + 1);
name->erase(open);
}
return subscript;
}
} // namespace gl
namespace egl
{
static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 1,
......
......@@ -68,7 +68,9 @@ bool IsTriangleMode(GLenum drawMode);
template <typename outT> outT iround(GLfloat value) { return static_cast<outT>(value > 0.0f ? floor(value + 0.5f) : ceil(value - 0.5f)); }
template <typename outT> outT uiround(GLfloat value) { return static_cast<outT>(value + 0.5f); }
}
unsigned int ParseAndStripArrayIndex(std::string *name);
} // namespace gl
namespace egl
{
......
......@@ -26,27 +26,10 @@
namespace gl
{
const char * const g_fakepath = "C:\\fakepath";
namespace
{
unsigned int ParseAndStripArrayIndex(std::string* name)
{
unsigned int subscript = GL_INVALID_INDEX;
// Strip any trailing array operator and retrieve the subscript
size_t open = name->find_last_of('[');
size_t close = name->find_last_of(']');
if (open != std::string::npos && close == name->length() - 1)
{
subscript = atoi(name->substr(open + 1).c_str());
name->erase(open);
}
return subscript;
}
void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
{
stream->writeInt(var.type);
......@@ -70,40 +53,6 @@ void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var)
var->structName = stream->readString();
}
template <typename VarT>
void DefineUniformBlockMembers(const std::vector<VarT> &fields,
const std::string &prefix,
int blockIndex,
std::vector<LinkedUniform> *uniformsOut)
{
for (const VarT &field : fields)
{
const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
if (field.isStruct())
{
for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
{
const std::string uniformElementName =
fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
DefineUniformBlockMembers(field.fields, uniformElementName, blockIndex,
uniformsOut);
}
}
else
{
// TODO(jmadill): record row-majorness?
// Block layout is recorded in the Impl.
LinkedUniform newUniform(field.type, field.precision, fieldName, field.arraySize,
blockIndex, sh::BlockMemberInfo::getDefaultBlockInfo());
// Since block uniforms have no location, we don't need to store them in the uniform
// locations list.
uniformsOut->push_back(newUniform);
}
}
}
// This simplified cast function doesn't need to worry about advanced concepts like
// depth range values, or casting to bool.
template <typename DestT, typename SrcT>
......@@ -187,6 +136,8 @@ bool UniformInList(const std::vector<LinkedUniform> &list, const std::string &na
} // anonymous namespace
const char *const g_fakepath = "C:\\fakepath";
AttributeBindings::AttributeBindings()
{
}
......@@ -521,7 +472,7 @@ Error Program::link(const gl::Data &data)
}
gatherTransformFeedbackVaryings(mergedVaryings);
mProgram->gatherUniformBlockInfo(&mData.mUniformBlocks, &mData.mUniforms);
gatherInterfaceBlockInfo();
mLinked = true;
return gl::Error(GL_NO_ERROR);
......@@ -670,10 +621,6 @@ Error Program::loadBinary(GLenum binaryFormat, const void *binary, GLsizei lengt
uniformBlock.memberUniformIndexes.push_back(stream.readInt<unsigned int>());
}
// TODO(jmadill): Make D3D-only
stream.readInt(&uniformBlock.psRegisterIndex);
stream.readInt(&uniformBlock.vsRegisterIndex);
mData.mUniformBlocks.push_back(uniformBlock);
}
......@@ -764,10 +711,6 @@ Error Program::saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, G
{
stream.writeInt(memberUniformIndex);
}
// TODO(jmadill): make D3D-only
stream.writeInt(uniformBlock.psRegisterIndex);
stream.writeInt(uniformBlock.vsRegisterIndex);
}
stream.writeInt(mData.mTransformFeedbackBufferMode);
......@@ -1894,8 +1837,6 @@ bool Program::linkUniformBlocks(InfoLog &infoLog, const Caps &caps)
}
}
gatherInterfaceBlockInfo();
return true;
}
......@@ -2334,11 +2275,58 @@ void Program::gatherInterfaceBlockInfo()
}
}
template <typename VarT>
void Program::defineUniformBlockMembers(const std::vector<VarT> &fields,
const std::string &prefix,
int blockIndex)
{
for (const VarT &field : fields)
{
const std::string &fullName = (prefix.empty() ? field.name : prefix + "." + field.name);
if (field.isStruct())
{
for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
{
const std::string uniformElementName =
fullName + (field.isArray() ? ArrayString(arrayElement) : "");
defineUniformBlockMembers(field.fields, uniformElementName, blockIndex);
}
}
else
{
// If getBlockMemberInfo returns false, the uniform is optimized out.
sh::BlockMemberInfo memberInfo;
if (!mProgram->getUniformBlockMemberInfo(fullName, &memberInfo))
{
continue;
}
LinkedUniform newUniform(field.type, field.precision, fullName, field.arraySize,
blockIndex, memberInfo);
// Since block uniforms have no location, we don't need to store them in the uniform
// locations list.
mData.mUniforms.push_back(newUniform);
}
}
}
void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType)
{
int blockIndex = static_cast<int>(mData.mUniformBlocks.size());
int blockIndex = static_cast<int>(mData.mUniformBlocks.size());
size_t blockSize = 0;
// Don't define this block at all if it's not active in the implementation.
if (!mProgram->getUniformBlockSize(interfaceBlock.name, &blockSize))
{
return;
}
// Track the first and last uniform index to determine the range of active uniforms in the
// block.
size_t firstBlockUniformIndex = mData.mUniforms.size();
DefineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, &mData.mUniforms);
defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex);
size_t lastBlockUniformIndex = mData.mUniforms.size();
std::vector<unsigned int> blockUniformIndexes;
......@@ -2365,6 +2353,15 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu
block.fragmentStaticUse = interfaceBlock.staticUse;
}
// TODO(jmadill): Determine if we can ever have an inactive array element block.
size_t blockElementSize = 0;
if (!mProgram->getUniformBlockSize(block.nameWithArrayIndex(), &blockElementSize))
{
continue;
}
ASSERT(blockElementSize == blockSize);
block.dataSize = static_cast<unsigned int>(blockElementSize);
mData.mUniformBlocks.push_back(block);
}
}
......@@ -2383,6 +2380,7 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu
block.fragmentStaticUse = interfaceBlock.staticUse;
}
block.dataSize = static_cast<unsigned int>(blockSize);
mData.mUniformBlocks.push_back(block);
}
}
......
......@@ -405,6 +405,11 @@ class Program : angle::NonCopyable
std::vector<LinkedUniform> *samplerUniforms);
void gatherInterfaceBlockInfo();
template <typename VarT>
void defineUniformBlockMembers(const std::vector<VarT> &fields,
const std::string &prefix,
int blockIndex);
void defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType);
template <typename T>
......
......@@ -121,13 +121,7 @@ const uint8_t *LinkedUniform::getDataPtrToElement(size_t elementIndex) const
}
UniformBlock::UniformBlock()
: isArray(false),
arrayElement(0),
dataSize(0),
vertexStaticUse(false),
fragmentStaticUse(false),
psRegisterIndex(GL_INVALID_INDEX),
vsRegisterIndex(GL_INVALID_INDEX)
: isArray(false), arrayElement(0), dataSize(0), vertexStaticUse(false), fragmentStaticUse(false)
{
}
......@@ -137,10 +131,19 @@ UniformBlock::UniformBlock(const std::string &nameIn, bool isArrayIn, unsigned i
arrayElement(arrayElementIn),
dataSize(0),
vertexStaticUse(false),
fragmentStaticUse(false),
psRegisterIndex(GL_INVALID_INDEX),
vsRegisterIndex(GL_INVALID_INDEX)
fragmentStaticUse(false)
{
}
std::string UniformBlock::nameWithArrayIndex() const
{
std::stringstream fullNameStr;
fullNameStr << name;
if (isArray)
{
fullNameStr << "[" << arrayElement << "]";
}
return fullNameStr.str();
}
}
......@@ -54,6 +54,8 @@ struct UniformBlock
UniformBlock(const UniformBlock &other) = default;
UniformBlock &operator=(const UniformBlock &other) = default;
std::string nameWithArrayIndex() const;
std::string name;
bool isArray;
unsigned int arrayElement;
......@@ -63,10 +65,6 @@ struct UniformBlock
bool fragmentStaticUse;
std::vector<unsigned int> memberUniformIndexes;
// TODO(jmadill): Make D3D-only.
unsigned int psRegisterIndex;
unsigned int vsRegisterIndex;
};
}
......
......@@ -66,9 +66,14 @@ class ProgramImpl : angle::NonCopyable
// TODO: synchronize in syncState when dirty bits exist.
virtual void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) = 0;
// Gather uniform block active uniform indices, and uniform block offset info.
virtual void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
std::vector<gl::LinkedUniform> *uniforms) = 0;
// May only be called after a successful link operation.
// Return false for inactive blocks.
virtual bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const = 0;
// May only be called after a successful link operation.
// Returns false for inactive members.
virtual bool getUniformBlockMemberInfo(const std::string &memberUniformName,
sh::BlockMemberInfo *memberInfoOut) const = 0;
protected:
const gl::Program::Data &mData;
......
......@@ -68,6 +68,18 @@ struct D3DUniform : angle::NonCopyable
unsigned int registerElement;
};
struct D3DUniformBlock
{
D3DUniformBlock() : vsRegisterIndex(GL_INVALID_INDEX), psRegisterIndex(GL_INVALID_INDEX) {}
bool vertexStaticUse() const { return vsRegisterIndex != GL_INVALID_INDEX; }
bool fragmentStaticUse() const { return psRegisterIndex != GL_INVALID_INDEX; }
unsigned int vsRegisterIndex;
unsigned int psRegisterIndex;
};
class ProgramD3D : public ProgramImpl
{
public:
......@@ -99,8 +111,9 @@ class ProgramD3D : public ProgramImpl
LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override;
GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
std::vector<gl::LinkedUniform> *uniforms) override;
bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override;
bool getUniformBlockMemberInfo(const std::string &memberUniformName,
sh::BlockMemberInfo *memberInfoOut) const override;
void initializeUniformStorage();
gl::Error applyUniforms();
......@@ -197,7 +210,6 @@ class ProgramD3D : public ProgramImpl
};
typedef std::map<std::string, D3DUniform *> D3DUniformMap;
typedef std::map<std::string, sh::BlockMemberInfo> BlockInfoMap;
void defineUniformsAndAssignRegisters();
void defineUniformBase(const gl::Shader *shader,
......@@ -217,8 +229,6 @@ class ProgramD3D : public ProgramImpl
std::vector<Sampler> &outSamplers,
GLuint *outUsedRange);
size_t defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, BlockInfoMap *blockInfoOut);
template <typename T>
void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType);
......@@ -237,6 +247,10 @@ class ProgramD3D : public ProgramImpl
void initAttributesByLayout();
void reset();
void assignUniformBlockRegisters();
void initUniformBlockInfo();
size_t getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock);
RendererD3D *mRenderer;
DynamicHLSL *mDynamicHLSL;
......@@ -279,6 +293,10 @@ class ProgramD3D : public ProgramImpl
std::vector<gl::LinkedVarying> mTransformFeedbackLinkedVaryings;
std::vector<D3DUniform *> mD3DUniforms;
std::vector<D3DUniformBlock> mD3DUniformBlocks;
std::map<std::string, sh::BlockMemberInfo> mBlockInfo;
std::map<std::string, size_t> mBlockDataSizes;
static unsigned int issueSerial();
static unsigned int mCurrentSerial;
......
......@@ -289,13 +289,29 @@ void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean t
void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
{
mFunctions->uniformBlockBinding(mProgramID, mUniformBlockRealLocationMap[uniformBlockIndex],
uniformBlockBinding);
// Lazy init
if (mUniformBlockRealLocationMap.empty())
{
mUniformBlockRealLocationMap.reserve(mData.getUniformBlocks().size());
for (const gl::UniformBlock &uniformBlock : mData.getUniformBlocks())
{
const std::string &nameWithIndex = uniformBlock.nameWithArrayIndex();
GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, nameWithIndex.c_str());
mUniformBlockRealLocationMap.push_back(blockIndex);
}
}
GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
if (realBlockIndex != GL_INVALID_INDEX)
{
mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
}
}
void ProgramGL::reset()
{
mUniformRealLocationMap.clear();
mUniformBlockRealLocationMap.clear();
mSamplerBindings.clear();
mUniformIndexToSamplerIndex.clear();
}
......@@ -310,105 +326,50 @@ const std::vector<SamplerBindingGL> &ProgramGL::getAppliedSamplerUniforms() cons
return mSamplerBindings;
}
void ProgramGL::gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
std::vector<gl::LinkedUniform> *uniforms)
bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
{
mUniformBlockRealLocationMap.resize(uniformBlocks->size(), 0);
ASSERT(mProgramID != 0u);
for (int i = 0; i < static_cast<int>(uniformBlocks->size()); i++)
GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockName.c_str());
if (blockIndex == GL_INVALID_INDEX)
{
auto &uniformBlock = uniformBlocks->at(i);
std::stringstream fullNameStr;
fullNameStr << uniformBlock.name;
if (uniformBlock.isArray)
{
fullNameStr << "[" << uniformBlock.arrayElement << "]";
}
GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, fullNameStr.str().c_str());
if (blockIndex != GL_INVALID_INDEX)
{
mUniformBlockRealLocationMap[i] = blockIndex;
GLint dataSize = 0;
mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
&dataSize);
uniformBlock.dataSize = dataSize;
}
else
{
// Remove this uniform block
uniformBlocks->erase(uniformBlocks->begin() + i);
i--;
}
*sizeOut = 0;
return false;
}
for (int uniformIdx = 0; uniformIdx < static_cast<int>(uniforms->size()); uniformIdx++)
{
auto &uniform = uniforms->at(uniformIdx);
if (uniform.isInDefaultBlock())
{
continue;
}
GLint dataSize = 0;
mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
&dataSize);
*sizeOut = static_cast<size_t>(dataSize);
return true;
}
const GLchar *uniformName = uniform.name.c_str();
GLuint uniformIndex = 0;
mFunctions->getUniformIndices(mProgramID, 1, &uniformName, &uniformIndex);
bool ProgramGL::getUniformBlockMemberInfo(const std::string &memberUniformName,
sh::BlockMemberInfo *memberInfoOut) const
{
GLuint uniformIndex;
const GLchar *memberNameGLStr = memberUniformName.c_str();
mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
if (uniformIndex == GL_INVALID_INDEX)
{
// Uniform member has been optimized out, remove it from the list
// TODO: Clean this up by using a class to wrap around the uniforms so manual removal is
// not needed.
for (size_t uniformBlockIdx = 0; uniformBlockIdx < uniformBlocks->size();
uniformBlockIdx++)
{
auto &uniformBlock = uniformBlocks->at(uniformBlockIdx);
for (int memberIndex = 0;
memberIndex < static_cast<int>(uniformBlock.memberUniformIndexes.size());
memberIndex++)
{
if (uniformBlock.memberUniformIndexes[memberIndex] ==
static_cast<unsigned int>(uniformIdx))
{
uniformBlock.memberUniformIndexes.erase(
uniformBlock.memberUniformIndexes.begin() + memberIndex);
memberIndex--;
}
else if (uniformBlock.memberUniformIndexes[memberIndex] >
static_cast<unsigned int>(uniformIdx))
{
uniformBlock.memberUniformIndexes[memberIndex]--;
}
}
}
uniforms->erase(uniforms->begin() + uniformIdx);
uniformIdx--;
}
else
{
GLint offset = 0;
mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
&offset);
uniform.blockInfo.offset = offset;
GLint arrayStride = 0;
mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
&arrayStride);
uniform.blockInfo.arrayStride = arrayStride;
GLint matrixStride = 0;
mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
&matrixStride);
uniform.blockInfo.matrixStride = matrixStride;
// TODO: determine this at the gl::Program level.
GLint isRowMajorMatrix = 0;
mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
&isRowMajorMatrix);
uniform.blockInfo.isRowMajorMatrix = isRowMajorMatrix != GL_FALSE;
}
if (uniformIndex == GL_INVALID_INDEX)
{
*memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
return false;
}
mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
&memberInfoOut->offset);
mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
&memberInfoOut->arrayStride);
mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
&memberInfoOut->matrixStride);
// TODO(jmadill): possibly determine this at the gl::Program level.
GLint isRowMajorMatrix = 0;
mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
&isRowMajorMatrix);
memberInfoOut->isRowMajorMatrix = isRowMajorMatrix != GL_FALSE;
return true;
}
}
} // namespace rx
......@@ -61,8 +61,9 @@ class ProgramGL : public ProgramImpl
void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
std::vector<gl::LinkedUniform> *uniforms) override;
bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override;
bool getUniformBlockMemberInfo(const std::string &memberUniformName,
sh::BlockMemberInfo *memberInfoOut) const override;
GLuint getProgramID() const;
const std::vector<SamplerBindingGL> &getAppliedSamplerUniforms() const;
......
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