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;
......
......@@ -527,6 +527,22 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
mD3DUniforms.push_back(d3dUniform);
}
const unsigned int blockCount = stream->readInt<unsigned int>();
if (stream->error())
{
infoLog << "Invalid program binary.";
return LinkResult(false, gl::Error(GL_NO_ERROR));
}
ASSERT(mD3DUniformBlocks.empty());
for (unsigned int blockIndex = 0; blockIndex < blockCount; ++blockIndex)
{
D3DUniformBlock uniformBlock;
stream->readInt(&uniformBlock.psRegisterIndex);
stream->readInt(&uniformBlock.vsRegisterIndex);
mD3DUniformBlocks.push_back(uniformBlock);
}
const unsigned int transformFeedbackVaryingCount = stream->readInt<unsigned int>();
mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount);
for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++)
......@@ -697,15 +713,20 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
stream->writeInt(mUsedPixelSamplerRange);
stream->writeInt(mD3DUniforms.size());
for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
for (const D3DUniform *uniform : mD3DUniforms)
{
const D3DUniform &uniform = *mD3DUniforms[uniformIndex];
// Type, name and arraySize are redundant, so aren't stored in the binary.
stream->writeInt(uniform.psRegisterIndex);
stream->writeInt(uniform.vsRegisterIndex);
stream->writeInt(uniform.registerCount);
stream->writeInt(uniform.registerElement);
stream->writeInt(uniform->psRegisterIndex);
stream->writeInt(uniform->vsRegisterIndex);
stream->writeInt(uniform->registerCount);
stream->writeInt(uniform->registerElement);
}
stream->writeInt(mD3DUniformBlocks.size());
for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks)
{
stream->writeInt(uniformBlock.psRegisterIndex);
stream->writeInt(uniformBlock.vsRegisterIndex);
}
stream->writeInt(mTransformFeedbackLinkedVaryings.size());
......@@ -1047,6 +1068,8 @@ LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
return result;
}
initUniformBlockInfo();
return LinkResult(true, gl::Error(GL_NO_ERROR));
}
......@@ -1056,24 +1079,20 @@ GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLo
return GL_TRUE;
}
void ProgramD3D::gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
std::vector<gl::LinkedUniform> *uniforms)
void ProgramD3D::initUniformBlockInfo()
{
const gl::Shader *vertexShader = mData.getAttachedVertexShader();
BlockInfoMap blockInfo;
std::map<std::string, size_t> blockDataSizes;
for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
{
if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
continue;
if (blockDataSizes.count(vertexBlock.name) > 0)
if (mBlockDataSizes.count(vertexBlock.name) > 0)
continue;
size_t dataSize = defineUniformBlock(vertexBlock, &blockInfo);
blockDataSizes[vertexBlock.name] = dataSize;
size_t dataSize = getUniformBlockInfo(vertexBlock);
mBlockDataSizes[vertexBlock.name] = dataSize;
}
const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
......@@ -1083,48 +1102,43 @@ void ProgramD3D::gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBl
if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
continue;
if (blockDataSizes.count(fragmentBlock.name) > 0)
if (mBlockDataSizes.count(fragmentBlock.name) > 0)
continue;
size_t dataSize = defineUniformBlock(fragmentBlock, &blockInfo);
blockDataSizes[fragmentBlock.name] = dataSize;
size_t dataSize = getUniformBlockInfo(fragmentBlock);
mBlockDataSizes[fragmentBlock.name] = dataSize;
}
}
// Copy block info out to uniforms.
for (gl::LinkedUniform &linkedUniform : *uniforms)
{
const auto &infoEntry = blockInfo.find(linkedUniform.name);
if (infoEntry != blockInfo.end())
{
linkedUniform.blockInfo = infoEntry->second;
}
}
void ProgramD3D::assignUniformBlockRegisters()
{
mD3DUniformBlocks.clear();
// Assign registers and update sizes.
const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
for (gl::UniformBlock &uniformBlock : *uniformBlocks)
for (const gl::UniformBlock &uniformBlock : mData.getUniformBlocks())
{
unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
D3DUniformBlock d3dUniformBlock;
if (uniformBlock.vertexStaticUse)
{
unsigned int baseRegister =
vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
uniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
d3dUniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
}
if (uniformBlock.fragmentStaticUse)
{
unsigned int baseRegister =
fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
uniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
d3dUniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
}
ASSERT(blockDataSizes.count(uniformBlock.name) == 1);
uniformBlock.dataSize = static_cast<unsigned int>(blockDataSizes[uniformBlock.name]);
mD3DUniformBlocks.push_back(d3dUniformBlock);
}
}
......@@ -1174,26 +1188,36 @@ gl::Error ProgramD3D::applyUniforms()
gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
{
if (mData.getUniformBlocks().empty())
{
return gl::Error(GL_NO_ERROR);
}
// Lazy init.
if (mD3DUniformBlocks.empty())
{
assignUniformBlockRegisters();
}
mVertexUBOCache.clear();
mFragmentUBOCache.clear();
const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
const auto &uniformBlocks = mData.getUniformBlocks();
for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlocks.size();
for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
uniformBlockIndex++)
{
const gl::UniformBlock &uniformBlock = uniformBlocks[uniformBlockIndex];
GLuint blockBinding = mData.getUniformBlockBinding(uniformBlockIndex);
const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
GLuint blockBinding = mData.getUniformBlockBinding(uniformBlockIndex);
// Unnecessary to apply an unreferenced standard or shared UBO
if (!uniformBlock.vertexStaticUse && !uniformBlock.fragmentStaticUse)
if (!uniformBlock.vertexStaticUse() && !uniformBlock.fragmentStaticUse())
{
continue;
}
if (uniformBlock.vertexStaticUse)
if (uniformBlock.vertexStaticUse())
{
unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS;
ASSERT(registerIndex < data.caps->maxVertexUniformBlocks);
......@@ -1207,7 +1231,7 @@ gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
mVertexUBOCache[registerIndex] = blockBinding;
}
if (uniformBlock.fragmentStaticUse)
if (uniformBlock.fragmentStaticUse())
{
unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS;
ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks);
......@@ -1338,7 +1362,8 @@ void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
}
void ProgramD3D::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/,
GLuint /*uniformBlockBinding*/)
{
}
......@@ -1677,8 +1702,7 @@ void ProgramD3D::setUniformMatrixfv(GLint location,
}
}
size_t ProgramD3D::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock,
BlockInfoMap *blockInfoOut)
size_t ProgramD3D::getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock)
{
ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
......@@ -1697,7 +1721,7 @@ size_t ProgramD3D::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock,
}
GetUniformBlockInfo(interfaceBlock.fields, "", encoder, interfaceBlock.isRowMajorLayout,
blockInfoOut);
&mBlockInfo);
return encoder->getBlockSize();
}
......@@ -1769,6 +1793,7 @@ void ProgramD3D::reset()
mUsesPointSize = false;
SafeDeleteContainer(mD3DUniforms);
mD3DUniformBlocks.clear();
SafeDelete(mVertexUniformStorage);
SafeDelete(mFragmentUniformStorage);
......@@ -1884,4 +1909,34 @@ D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
{
return mD3DUniforms[mData.getUniformLocations()[location].index];
}
bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
{
std::string baseName = blockName;
gl::ParseAndStripArrayIndex(&baseName);
auto sizeIter = mBlockDataSizes.find(baseName);
if (sizeIter == mBlockDataSizes.end())
{
*sizeOut = 0;
return false;
}
*sizeOut = sizeIter->second;
return true;
}
bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName,
sh::BlockMemberInfo *memberInfoOut) const
{
auto infoIter = mBlockInfo.find(memberUniformName);
if (infoIter == mBlockInfo.end())
{
*memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
return false;
}
*memberInfoOut = infoIter->second;
return true;
}
}
......@@ -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