Commit 97d82b72 by Geoff Lang

Support UBOs in RendererGL and ProgramGL.

BUG=angleproject:882 BUG=angleproject:883 Change-Id: I36f8ef42d87e289658a6ba4899380bc72b9bcebf Reviewed-on: https://chromium-review.googlesource.com/299871Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent f6ade2ec
......@@ -1520,6 +1520,7 @@ const UniformBlock &Program::getUniformBlockByIndex(GLuint index) const
void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
{
mData.mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding;
mProgram->setUniformBlockBinding(uniformBlockIndex, uniformBlockBinding);
}
GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
......@@ -1533,6 +1534,7 @@ void Program::resetUniformBlockBindings()
{
mData.mUniformBlockBindings[blockId] = 0;
}
mData.mActiveUniformBlockBindings.reset();
}
void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode)
......
......@@ -182,6 +182,10 @@ class Program : angle::NonCopyable
ASSERT(uniformBlockIndex < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS);
return mUniformBlockBindings[uniformBlockIndex];
}
const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const
{
return mActiveUniformBlockBindings;
}
const std::vector<sh::Attribute> &getAttributes() const { return mAttributes; }
const AttributesMask &getActiveAttribLocationsMask() const
{
......@@ -213,6 +217,7 @@ class Program : angle::NonCopyable
GLenum mTransformFeedbackBufferMode;
GLuint mUniformBlockBindings[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS];
UniformBlockBindingMask mActiveUniformBlockBindings;
std::vector<sh::Attribute> mAttributes;
std::bitset<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
......
......@@ -995,32 +995,10 @@ void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintpt
mUniformBuffers[index].set(buffer, offset, size);
}
GLuint State::getIndexedUniformBufferId(GLuint index) const
const OffsetBindingPointer<Buffer> &State::getIndexedUniformBuffer(size_t index) const
{
ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
return mUniformBuffers[index].id();
}
Buffer *State::getIndexedUniformBuffer(GLuint index) const
{
ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
return mUniformBuffers[index].get();
}
GLintptr State::getIndexedUniformBufferOffset(GLuint index) const
{
ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
return mUniformBuffers[index].getOffset();
}
GLsizeiptr State::getIndexedUniformBufferSize(GLuint index) const
{
ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
return mUniformBuffers[index].getSize();
return mUniformBuffers[index];
}
void State::setCopyReadBufferBinding(Buffer *buffer)
......
......@@ -203,10 +203,7 @@ class State : angle::NonCopyable
// GL_UNIFORM_BUFFER - Both indexed and generic targets
void setGenericUniformBufferBinding(Buffer *buffer);
void setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size);
GLuint getIndexedUniformBufferId(GLuint index) const;
Buffer *getIndexedUniformBuffer(GLuint index) const;
GLintptr getIndexedUniformBufferOffset(GLuint index) const;
GLsizeiptr getIndexedUniformBufferSize(GLuint index) const;
const OffsetBindingPointer<Buffer> &getIndexedUniformBuffer(size_t index) const;
// GL_COPY_[READ/WRITE]_BUFFER
void setCopyReadBufferBinding(Buffer *buffer);
......
......@@ -273,6 +273,9 @@ struct PixelPackState
// Used in Program and VertexArray.
typedef std::bitset<MAX_VERTEX_ATTRIBS> AttributesMask;
// Use in Program
typedef std::bitset<IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS> UniformBlockBindingMask;
}
namespace rx
......
......@@ -66,6 +66,9 @@ class ProgramImpl : angle::NonCopyable
virtual void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
virtual void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
// 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;
......
......@@ -1344,6 +1344,10 @@ 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::defineUniformsAndAssignRegisters()
{
D3DUniformMap uniformMap;
......
......@@ -131,6 +131,8 @@ class ProgramD3D : public ProgramImpl
void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
const UniformStorageD3D &getVertexUniformStorage() const { return *mVertexUniformStorage; }
const UniformStorageD3D &getFragmentUniformStorage() const { return *mFragmentUniformStorage; }
......
......@@ -1008,13 +1008,14 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data,
continue;
}
gl::Buffer *uniformBuffer = data.state->getIndexedUniformBuffer(binding);
GLintptr uniformBufferOffset = data.state->getIndexedUniformBufferOffset(binding);
GLsizeiptr uniformBufferSize = data.state->getIndexedUniformBufferSize(binding);
const OffsetBindingPointer<gl::Buffer> &uniformBuffer =
data.state->getIndexedUniformBuffer(binding);
GLintptr uniformBufferOffset = uniformBuffer.getOffset();
GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
if (uniformBuffer)
if (uniformBuffer.get() != nullptr)
{
Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer);
Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get());
ID3D11Buffer *constantBuffer;
if (mRenderer11DeviceCaps.supportsConstantBufferOffsets)
......@@ -1068,13 +1069,14 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data,
continue;
}
gl::Buffer *uniformBuffer = data.state->getIndexedUniformBuffer(binding);
GLintptr uniformBufferOffset = data.state->getIndexedUniformBufferOffset(binding);
GLsizeiptr uniformBufferSize = data.state->getIndexedUniformBufferSize(binding);
const OffsetBindingPointer<gl::Buffer> &uniformBuffer =
data.state->getIndexedUniformBuffer(binding);
GLintptr uniformBufferOffset = uniformBuffer.getOffset();
GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
if (uniformBuffer)
if (uniformBuffer.get() != nullptr)
{
Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer);
Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get());
ID3D11Buffer *constantBuffer;
if (mRenderer11DeviceCaps.supportsConstantBufferOffsets)
......
......@@ -299,6 +299,12 @@ void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean t
mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
}
void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
{
mFunctions->uniformBlockBinding(mProgramID, mUniformBlockRealLocationMap[uniformBlockIndex],
uniformBlockBinding);
}
void ProgramGL::reset()
{
mUniformRealLocationMap.clear();
......@@ -316,9 +322,104 @@ const std::vector<SamplerBindingGL> &ProgramGL::getAppliedSamplerUniforms() cons
return mSamplerBindings;
}
void ProgramGL::gatherUniformBlockInfo(std::vector<gl::UniformBlock> * /*uniformBlocks*/,
std::vector<gl::LinkedUniform> * /*uniforms*/)
void ProgramGL::gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
std::vector<gl::LinkedUniform> *uniforms)
{
// TODO(jmadill): Gather uniform block layout info, and data sizes.
mUniformBlockRealLocationMap.resize(uniformBlocks->size(), 0);
for (int i = 0; i < uniformBlocks->size(); i++)
{
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--;
}
}
for (int uniformIdx = 0; uniformIdx < uniforms->size(); uniformIdx++)
{
auto &uniform = uniforms->at(uniformIdx);
if (uniform.isInDefaultBlock())
{
continue;
}
const GLchar *uniformName = uniform.name.c_str();
GLuint uniformIndex = 0;
mFunctions->getUniformIndices(mProgramID, 1, &uniformName, &uniformIndex);
if (uniformIndex == -1)
{
// 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 < 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;
}
}
}
}
......@@ -62,6 +62,8 @@ class ProgramGL : public ProgramImpl
void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override;
void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) override;
void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
void gatherUniformBlockInfo(std::vector<gl::UniformBlock> *uniformBlocks,
std::vector<gl::LinkedUniform> *uniforms) override;
......@@ -78,6 +80,7 @@ class ProgramGL : public ProgramImpl
StateManagerGL *mStateManager;
std::vector<GLint> mUniformRealLocationMap;
std::vector<GLuint> mUniformBlockRealLocationMap;
// An array of the samplers that are used by the program
std::vector<SamplerBindingGL> mSamplerBindings;
......
......@@ -22,12 +22,18 @@
namespace rx
{
StateManagerGL::IndexedBufferBinding::IndexedBufferBinding() : offset(0), size(0), buffer(0)
{
}
StateManagerGL::StateManagerGL(const FunctionsGL *functions, const gl::Caps &rendererCaps)
: mFunctions(functions),
mProgram(0),
mVAO(0),
mVertexAttribCurrentValues(rendererCaps.maxVertexAttributes),
mBuffers(),
mIndexedBuffers(),
mTextureUnitIndex(0),
mTextures(),
mSamplers(rendererCaps.maxCombinedTextureImageUnits, 0),
......@@ -103,6 +109,8 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, const gl::Caps &ren
mTextures[GL_TEXTURE_2D_ARRAY].resize(rendererCaps.maxCombinedTextureImageUnits);
mTextures[GL_TEXTURE_3D].resize(rendererCaps.maxCombinedTextureImageUnits);
mIndexedBuffers[GL_UNIFORM_BUFFER].resize(rendererCaps.maxCombinedUniformBlocks);
// Initialize point sprite state for desktop GL
if (mFunctions->standard == STANDARD_GL_DESKTOP)
{
......@@ -193,6 +201,17 @@ void StateManagerGL::deleteBuffer(GLuint buffer)
}
}
for (const auto &bufferTypeIter : mIndexedBuffers)
{
for (size_t bindIndex = 0; bindIndex < bufferTypeIter.second.size(); bindIndex++)
{
if (bufferTypeIter.second[bindIndex].buffer == buffer)
{
bindBufferBase(bufferTypeIter.first, bindIndex, 0);
}
}
}
mFunctions->deleteBuffers(1, &buffer);
}
}
......@@ -255,6 +274,35 @@ void StateManagerGL::bindBuffer(GLenum type, GLuint buffer)
}
}
void StateManagerGL::bindBufferBase(GLenum type, size_t index, GLuint buffer)
{
auto &binding = mIndexedBuffers[type][index];
if (binding.buffer != buffer || binding.offset != static_cast<size_t>(-1) ||
binding.size != static_cast<size_t>(-1))
{
binding.buffer = buffer;
binding.offset = static_cast<size_t>(-1);
binding.size = static_cast<size_t>(-1);
mFunctions->bindBufferBase(type, static_cast<GLuint>(index), buffer);
}
}
void StateManagerGL::bindBufferRange(GLenum type,
size_t index,
GLuint buffer,
size_t offset,
size_t size)
{
auto &binding = mIndexedBuffers[type][index];
if (binding.buffer != buffer || binding.offset != offset || binding.size != size)
{
binding.buffer = buffer;
binding.offset = offset;
binding.size = size;
mFunctions->bindBufferRange(type, static_cast<GLuint>(index), buffer, offset, size);
}
}
void StateManagerGL::activeTexture(size_t unit)
{
if (mTextureUnitIndex != unit)
......@@ -498,6 +546,30 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data)
const ProgramGL *programGL = GetImplAs<ProgramGL>(program);
useProgram(programGL->getProgramID());
for (size_t uniformBlockIndex = 0;
uniformBlockIndex < gl::IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS;
uniformBlockIndex++)
{
GLuint binding = program->getUniformBlockBinding(static_cast<GLuint>(uniformBlockIndex));
const OffsetBindingPointer<gl::Buffer> &uniformBuffer =
data.state->getIndexedUniformBuffer(binding);
if (uniformBuffer.get() != nullptr)
{
BufferGL *bufferGL = GetImplAs<BufferGL>(uniformBuffer.get());
if (uniformBuffer.getSize() == 0)
{
bindBufferBase(GL_UNIFORM_BUFFER, binding, bufferGL->getBufferID());
}
else
{
bindBufferRange(GL_UNIFORM_BUFFER, binding, bufferGL->getBufferID(),
uniformBuffer.getOffset(), uniformBuffer.getSize());
}
}
}
const std::vector<SamplerBindingGL> &appliedSamplerUniforms = programGL->getAppliedSamplerUniforms();
for (const SamplerBindingGL &samplerUniform : appliedSamplerUniforms)
{
......
......@@ -45,6 +45,8 @@ class StateManagerGL final : angle::NonCopyable
void useProgram(GLuint program);
void bindVertexArray(GLuint vao, GLuint elementArrayBuffer);
void bindBuffer(GLenum type, GLuint buffer);
void bindBufferBase(GLenum type, size_t index, GLuint buffer);
void bindBufferRange(GLenum type, size_t index, GLuint buffer, size_t offset, size_t size);
void activeTexture(size_t unit);
void bindTexture(GLenum type, GLuint texture);
void bindSampler(size_t unit, GLuint sampler);
......@@ -140,6 +142,16 @@ class StateManagerGL final : angle::NonCopyable
std::map<GLenum, GLuint> mBuffers;
struct IndexedBufferBinding
{
IndexedBufferBinding();
size_t offset;
size_t size;
GLuint buffer;
};
std::map<GLenum, std::vector<IndexedBufferBinding>> mIndexedBuffers;
size_t mTextureUnitIndex;
std::map<GLenum, std::vector<GLuint>> mTextures;
std::vector<GLuint> mSamplers;
......
......@@ -1531,17 +1531,17 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz
{
const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
const gl::Buffer *uniformBuffer = state.getIndexedUniformBuffer(blockBinding);
const OffsetBindingPointer<Buffer> &uniformBuffer =
state.getIndexedUniformBuffer(blockBinding);
if (!uniformBuffer)
if (uniformBuffer.get() == nullptr)
{
// undefined behaviour
context->recordError(Error(GL_INVALID_OPERATION, "It is undefined behaviour to have a used but unbound uniform buffer."));
return false;
}
size_t uniformBufferSize = state.getIndexedUniformBufferSize(blockBinding);
size_t uniformBufferSize = uniformBuffer.getSize();
if (uniformBufferSize == 0)
{
// Bind the whole buffer.
......
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