Commit dde78e8c by Shao Committed by Commit Bot

ES31: Implement Vertex Attrib Binding on OpenGL

This patch intends to implement Vertex Attrib Binding on OpenGL back-ends: 1. Add supports for updating vertex attributes by Vertex Attrib Binding APIs. 2. Refactor the process of updating vertex attribtues in class VertexArray to make it easier to implement this feature. BUG=angleproject:1593 TEST=dEQP-GLES31.functional.vertex_attribute_binding.* Change-Id: I800e61518c552b94b84c415895ad31668b0a84b2 Reviewed-on: https://chromium-review.googlesource.com/510251 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent ffb35f64
...@@ -2410,7 +2410,7 @@ void Context::detachSampler(GLuint sampler) ...@@ -2410,7 +2410,7 @@ void Context::detachSampler(GLuint sampler)
void Context::setVertexAttribDivisor(GLuint index, GLuint divisor) void Context::setVertexAttribDivisor(GLuint index, GLuint divisor)
{ {
mGLState.setVertexAttribDivisor(index, divisor); mGLState.setVertexAttribDivisor(this, index, divisor);
} }
void Context::samplerParameteri(GLuint sampler, GLenum pname, GLint param) void Context::samplerParameteri(GLuint sampler, GLenum pname, GLint param)
...@@ -3757,8 +3757,8 @@ void Context::vertexAttribPointer(GLuint index, ...@@ -3757,8 +3757,8 @@ void Context::vertexAttribPointer(GLuint index,
GLsizei stride, GLsizei stride,
const void *ptr) const void *ptr)
{ {
mGLState.setVertexAttribState(this, index, mGLState.getTargetBuffer(GL_ARRAY_BUFFER), size, mGLState.setVertexAttribPointer(this, index, mGLState.getTargetBuffer(GL_ARRAY_BUFFER), size,
type, normalized == GL_TRUE, false, stride, ptr); type, normalized == GL_TRUE, false, stride, ptr);
} }
void Context::vertexAttribFormat(GLuint attribIndex, void Context::vertexAttribFormat(GLuint attribIndex,
...@@ -3781,7 +3781,7 @@ void Context::vertexAttribIFormat(GLuint attribIndex, ...@@ -3781,7 +3781,7 @@ void Context::vertexAttribIFormat(GLuint attribIndex,
void Context::vertexAttribBinding(GLuint attribIndex, GLuint bindingIndex) void Context::vertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
{ {
mGLState.setVertexAttribBinding(attribIndex, bindingIndex); mGLState.setVertexAttribBinding(this, attribIndex, bindingIndex);
} }
void Context::setVertexBindingDivisor(GLuint bindingIndex, GLuint divisor) void Context::setVertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
...@@ -3800,8 +3800,8 @@ void Context::vertexAttribIPointer(GLuint index, ...@@ -3800,8 +3800,8 @@ void Context::vertexAttribIPointer(GLuint index,
GLsizei stride, GLsizei stride,
const void *pointer) const void *pointer)
{ {
mGLState.setVertexAttribState(this, index, mGLState.getTargetBuffer(GL_ARRAY_BUFFER), size, mGLState.setVertexAttribPointer(this, index, mGLState.getTargetBuffer(GL_ARRAY_BUFFER), size,
type, false, true, stride, pointer); type, false, true, stride, pointer);
} }
void Context::vertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w) void Context::vertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
......
...@@ -1063,9 +1063,9 @@ void State::bindVertexBuffer(const Context *context, ...@@ -1063,9 +1063,9 @@ void State::bindVertexBuffer(const Context *context,
mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
} }
void State::setVertexAttribBinding(GLuint attribIndex, GLuint bindingIndex) void State::setVertexAttribBinding(const Context *context, GLuint attribIndex, GLuint bindingIndex)
{ {
getVertexArray()->setVertexAttribBinding(attribIndex, bindingIndex); getVertexArray()->setVertexAttribBinding(context, attribIndex, bindingIndex);
mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
} }
...@@ -1360,24 +1360,24 @@ void State::setVertexAttribi(GLuint index, const GLint values[4]) ...@@ -1360,24 +1360,24 @@ void State::setVertexAttribi(GLuint index, const GLint values[4])
mDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_0 + index); mDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_0 + index);
} }
void State::setVertexAttribState(const Context *context, void State::setVertexAttribPointer(const Context *context,
unsigned int attribNum, unsigned int attribNum,
Buffer *boundBuffer, Buffer *boundBuffer,
GLint size, GLint size,
GLenum type, GLenum type,
bool normalized, bool normalized,
bool pureInteger, bool pureInteger,
GLsizei stride, GLsizei stride,
const void *pointer) const void *pointer)
{ {
getVertexArray()->setAttributeState(context, attribNum, boundBuffer, size, type, normalized, getVertexArray()->setVertexAttribPointer(context, attribNum, boundBuffer, size, type,
pureInteger, stride, pointer); normalized, pureInteger, stride, pointer);
mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
} }
void State::setVertexAttribDivisor(GLuint index, GLuint divisor) void State::setVertexAttribDivisor(const Context *context, GLuint index, GLuint divisor)
{ {
getVertexArray()->setVertexAttribDivisor(index, divisor); getVertexArray()->setVertexAttribDivisor(context, index, divisor);
mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
} }
......
...@@ -273,16 +273,16 @@ class State : angle::NonCopyable ...@@ -273,16 +273,16 @@ class State : angle::NonCopyable
void setVertexAttribf(GLuint index, const GLfloat values[4]); void setVertexAttribf(GLuint index, const GLfloat values[4]);
void setVertexAttribu(GLuint index, const GLuint values[4]); void setVertexAttribu(GLuint index, const GLuint values[4]);
void setVertexAttribi(GLuint index, const GLint values[4]); void setVertexAttribi(GLuint index, const GLint values[4]);
void setVertexAttribState(const Context *context, void setVertexAttribPointer(const Context *context,
unsigned int attribNum, unsigned int attribNum,
Buffer *boundBuffer, Buffer *boundBuffer,
GLint size, GLint size,
GLenum type, GLenum type,
bool normalized, bool normalized,
bool pureInteger, bool pureInteger,
GLsizei stride, GLsizei stride,
const void *pointer); const void *pointer);
void setVertexAttribDivisor(GLuint index, GLuint divisor); void setVertexAttribDivisor(const Context *context, GLuint index, GLuint divisor);
const VertexAttribCurrentValueData &getVertexAttribCurrentValue(size_t attribNum) const; const VertexAttribCurrentValueData &getVertexAttribCurrentValue(size_t attribNum) const;
const void *getVertexAttribPointer(unsigned int attribNum) const; const void *getVertexAttribPointer(unsigned int attribNum) const;
void bindVertexBuffer(const Context *context, void bindVertexBuffer(const Context *context,
...@@ -296,7 +296,7 @@ class State : angle::NonCopyable ...@@ -296,7 +296,7 @@ class State : angle::NonCopyable
bool normalized, bool normalized,
bool pureInteger, bool pureInteger,
GLuint relativeOffset); GLuint relativeOffset);
void setVertexAttribBinding(GLuint attribIndex, GLuint bindingIndex); void setVertexAttribBinding(const Context *context, GLuint attribIndex, GLuint bindingIndex);
void setVertexBindingDivisor(GLuint bindingIndex, GLuint divisor); void setVertexBindingDivisor(GLuint bindingIndex, GLuint divisor);
// Pixel pack state manipulation // Pixel pack state manipulation
......
...@@ -100,7 +100,7 @@ const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const ...@@ -100,7 +100,7 @@ const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const
return mState.mVertexBindings[bindingIndex]; return mState.mVertexBindings[bindingIndex];
} }
size_t VertexArray::GetAttribIndex(size_t dirtyBit) size_t VertexArray::GetVertexIndexFromDirtyBit(size_t dirtyBit)
{ {
static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS, static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
"The stride of vertex attributes should equal to that of vertex bindings."); "The stride of vertex attributes should equal to that of vertex bindings.");
...@@ -108,11 +108,11 @@ size_t VertexArray::GetAttribIndex(size_t dirtyBit) ...@@ -108,11 +108,11 @@ size_t VertexArray::GetAttribIndex(size_t dirtyBit)
return (dirtyBit - DIRTY_BIT_ATTRIB_0_ENABLED) % gl::MAX_VERTEX_ATTRIBS; return (dirtyBit - DIRTY_BIT_ATTRIB_0_ENABLED) % gl::MAX_VERTEX_ATTRIBS;
} }
void VertexArray::bindVertexBuffer(const Context *context, void VertexArray::bindVertexBufferImpl(const Context *context,
size_t bindingIndex, size_t bindingIndex,
Buffer *boundBuffer, Buffer *boundBuffer,
GLintptr offset, GLintptr offset,
GLsizei stride) GLsizei stride)
{ {
ASSERT(bindingIndex < getMaxBindings()); ASSERT(bindingIndex < getMaxBindings());
...@@ -121,15 +121,33 @@ void VertexArray::bindVertexBuffer(const Context *context, ...@@ -121,15 +121,33 @@ void VertexArray::bindVertexBuffer(const Context *context,
binding->setBuffer(context, boundBuffer); binding->setBuffer(context, boundBuffer);
binding->setOffset(offset); binding->setOffset(offset);
binding->setStride(stride); binding->setStride(stride);
}
void VertexArray::bindVertexBuffer(const Context *context,
size_t bindingIndex,
Buffer *boundBuffer,
GLintptr offset,
GLsizei stride)
{
bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride);
mDirtyBits.set(DIRTY_BIT_BINDING_0_BUFFER + bindingIndex); mDirtyBits.set(DIRTY_BIT_BINDING_0_BUFFER + bindingIndex);
} }
void VertexArray::setVertexAttribBinding(size_t attribIndex, size_t bindingIndex) void VertexArray::setVertexAttribBinding(const Context *context,
size_t attribIndex,
GLuint bindingIndex)
{ {
ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings()); ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings());
mState.mVertexAttributes[attribIndex].bindingIndex = static_cast<GLuint>(bindingIndex); if (mState.mVertexAttributes[attribIndex].bindingIndex != bindingIndex)
mDirtyBits.set(DIRTY_BIT_ATTRIB_0_BINDING + attribIndex); {
// In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable.
ASSERT(context->getClientVersion() >= ES_3_1);
mState.mVertexAttributes[attribIndex].bindingIndex = bindingIndex;
mDirtyBits.set(DIRTY_BIT_ATTRIB_0_BINDING + attribIndex);
}
} }
void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor) void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
...@@ -137,15 +155,16 @@ void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor) ...@@ -137,15 +155,16 @@ void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
ASSERT(bindingIndex < getMaxBindings()); ASSERT(bindingIndex < getMaxBindings());
mState.mVertexBindings[bindingIndex].setDivisor(divisor); mState.mVertexBindings[bindingIndex].setDivisor(divisor);
mDirtyBits.set(DIRTY_BIT_BINDING_0_DIVISOR + bindingIndex); mDirtyBits.set(DIRTY_BIT_BINDING_0_DIVISOR + bindingIndex);
} }
void VertexArray::setVertexAttribFormat(size_t attribIndex, void VertexArray::setVertexAttribFormatImpl(size_t attribIndex,
GLint size, GLint size,
GLenum type, GLenum type,
bool normalized, bool normalized,
bool pureInteger, bool pureInteger,
GLintptr relativeOffset) GLuint relativeOffset)
{ {
ASSERT(attribIndex < getMaxAttribs()); ASSERT(attribIndex < getMaxAttribs());
...@@ -156,15 +175,26 @@ void VertexArray::setVertexAttribFormat(size_t attribIndex, ...@@ -156,15 +175,26 @@ void VertexArray::setVertexAttribFormat(size_t attribIndex,
attrib->normalized = normalized; attrib->normalized = normalized;
attrib->pureInteger = pureInteger; attrib->pureInteger = pureInteger;
attrib->relativeOffset = relativeOffset; attrib->relativeOffset = relativeOffset;
}
void VertexArray::setVertexAttribFormat(size_t attribIndex,
GLint size,
GLenum type,
bool normalized,
bool pureInteger,
GLuint relativeOffset)
{
setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, relativeOffset);
mDirtyBits.set(DIRTY_BIT_ATTRIB_0_FORMAT + attribIndex); mDirtyBits.set(DIRTY_BIT_ATTRIB_0_FORMAT + attribIndex);
} }
void VertexArray::setVertexAttribDivisor(size_t index, GLuint divisor) void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor)
{ {
ASSERT(index < getMaxAttribs()); ASSERT(attribIndex < getMaxAttribs());
setVertexAttribBinding(index, index); setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
setVertexBindingDivisor(index, divisor); setVertexBindingDivisor(attribIndex, divisor);
} }
void VertexArray::enableAttribute(size_t attribIndex, bool enabledState) void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
...@@ -172,6 +202,7 @@ void VertexArray::enableAttribute(size_t attribIndex, bool enabledState) ...@@ -172,6 +202,7 @@ void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
ASSERT(attribIndex < getMaxAttribs()); ASSERT(attribIndex < getMaxAttribs());
mState.mVertexAttributes[attribIndex].enabled = enabledState; mState.mVertexAttributes[attribIndex].enabled = enabledState;
mDirtyBits.set(DIRTY_BIT_ATTRIB_0_ENABLED + attribIndex); mDirtyBits.set(DIRTY_BIT_ATTRIB_0_ENABLED + attribIndex);
// Update state cache // Update state cache
...@@ -189,30 +220,31 @@ void VertexArray::enableAttribute(size_t attribIndex, bool enabledState) ...@@ -189,30 +220,31 @@ void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
} }
} }
void VertexArray::setAttributeState(const Context *context, void VertexArray::setVertexAttribPointer(const Context *context,
size_t attribIndex, size_t attribIndex,
gl::Buffer *boundBuffer, gl::Buffer *boundBuffer,
GLint size, GLint size,
GLenum type, GLenum type,
bool normalized, bool normalized,
bool pureInteger, bool pureInteger,
GLsizei stride, GLsizei stride,
const void *pointer) const void *pointer)
{ {
ASSERT(attribIndex < getMaxAttribs()); ASSERT(attribIndex < getMaxAttribs());
GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0; GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
setVertexAttribFormat(attribIndex, size, type, normalized, pureInteger, 0); setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, 0);
setVertexAttribBinding(attribIndex, attribIndex); setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
VertexAttribute &attrib = mState.mVertexAttributes[attribIndex]; VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
GLsizei effectiveStride = GLsizei effectiveStride =
stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib)); stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib));
attrib.pointer = pointer; attrib.pointer = pointer;
attrib.vertexAttribArrayStride = stride; attrib.vertexAttribArrayStride = stride;
bindVertexBuffer(context, attribIndex, boundBuffer, offset, effectiveStride); bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
mDirtyBits.set(DIRTY_BIT_ATTRIB_0_POINTER + attribIndex); mDirtyBits.set(DIRTY_BIT_ATTRIB_0_POINTER + attribIndex);
} }
......
...@@ -91,30 +91,41 @@ class VertexArray final : public LabeledObject ...@@ -91,30 +91,41 @@ class VertexArray final : public LabeledObject
} }
void detachBuffer(const Context *context, GLuint bufferName); void detachBuffer(const Context *context, GLuint bufferName);
void setVertexAttribDivisor(size_t index, GLuint divisor); void setVertexAttribDivisor(const Context *context, size_t index, GLuint divisor);
void enableAttribute(size_t attribIndex, bool enabledState); void enableAttribute(size_t attribIndex, bool enabledState);
void setAttributeState(const Context *context, void setVertexAttribPointer(const Context *context,
size_t attribIndex, size_t attribIndex,
Buffer *boundBuffer, Buffer *boundBuffer,
GLint size, GLint size,
GLenum type, GLenum type,
bool normalized, bool normalized,
bool pureInteger, bool pureInteger,
GLsizei stride, GLsizei stride,
const void *pointer); const void *pointer);
void setVertexAttribFormat(size_t attribIndex, void setVertexAttribFormat(size_t attribIndex,
GLint size, GLint size,
GLenum type, GLenum type,
bool normalized, bool normalized,
bool pureInteger, bool pureInteger,
GLintptr relativeOffset); GLuint relativeOffset);
void bindVertexBuffer(const Context *context, void bindVertexBuffer(const Context *context,
size_t bindingIndex, size_t bindingIndex,
Buffer *boundBuffer, Buffer *boundBuffer,
GLintptr offset, GLintptr offset,
GLsizei stride); GLsizei stride);
void setVertexAttribBinding(size_t attribIndex, size_t bindingIndex); void setVertexAttribBinding(const Context *context, size_t attribIndex, GLuint bindingIndex);
void setVertexBindingDivisor(size_t bindingIndex, GLuint divisor); void setVertexBindingDivisor(size_t bindingIndex, GLuint divisor);
void setVertexAttribFormatImpl(size_t attribIndex,
GLint size,
GLenum type,
bool normalized,
bool pureInteger,
GLuint relativeOffset);
void bindVertexBufferImpl(const Context *context,
size_t bindingIndex,
Buffer *boundBuffer,
GLintptr offset,
GLsizei stride);
void setElementArrayBuffer(const Context *context, Buffer *buffer); void setElementArrayBuffer(const Context *context, Buffer *buffer);
...@@ -173,7 +184,7 @@ class VertexArray final : public LabeledObject ...@@ -173,7 +184,7 @@ class VertexArray final : public LabeledObject
using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>; using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
static size_t GetAttribIndex(size_t dirtyBit); static size_t GetVertexIndexFromDirtyBit(size_t dirtyBit);
void syncImplState(const Context *context); void syncImplState(const Context *context);
bool hasAnyDirtyBit() const { return mDirtyBits.any(); } bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
......
...@@ -15,20 +15,20 @@ ...@@ -15,20 +15,20 @@
using namespace gl; using namespace gl;
// Tests that function GetAttribIndex computes the index properly. // Tests that function GetIndexFromDirtyBit computes the index properly.
TEST(VertexArrayTest, VerifyGetAttribIndex) TEST(VertexArrayTest, VerifyGetIndexFromDirtyBit)
{ {
VertexArray::DirtyBits dirtyBits; VertexArray::DirtyBits dirtyBits;
size_t bits[] = {1, 4, 9, 16, 25, 36, 49, 64, 81, 90}; constexpr size_t bits[] = {1, 4, 9, 16, 25, 36, 49, 64, 81, 92};
int count = sizeof(bits) / sizeof(size_t); constexpr GLint count = sizeof(bits) / sizeof(size_t);
for (int i = 0; i < count; i++) for (GLint i = 0; i < count; i++)
{ {
dirtyBits.set(bits[i]); dirtyBits.set(bits[i]);
} }
for (size_t dirtyBit : dirtyBits) for (size_t dirtyBit : dirtyBits)
{ {
size_t index = VertexArray::GetAttribIndex(dirtyBit); const size_t index = VertexArray::GetVertexIndexFromDirtyBit(dirtyBit);
if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_ENABLED) if (dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_ENABLED)
{ {
EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED, index); EXPECT_EQ(dirtyBit - VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED, index);
......
...@@ -62,7 +62,7 @@ struct VertexAttribute final : private angle::NonCopyable ...@@ -62,7 +62,7 @@ struct VertexAttribute final : private angle::NonCopyable
bool pureInteger; bool pureInteger;
const void *pointer; const void *pointer;
GLintptr relativeOffset; GLuint relativeOffset;
GLuint vertexAttribArrayStride; // ONLY for queries of VERTEX_ATTRIB_ARRAY_STRIDE GLuint vertexAttribArrayStride; // ONLY for queries of VERTEX_ATTRIB_ARRAY_STRIDE
GLuint bindingIndex; GLuint bindingIndex;
......
...@@ -397,10 +397,7 @@ void QueryVertexAttribBase(const VertexAttribute &attrib, ...@@ -397,10 +397,7 @@ void QueryVertexAttribBase(const VertexAttribute &attrib,
*params = ConvertFromGLuint<ParamType>(attrib.bindingIndex); *params = ConvertFromGLuint<ParamType>(attrib.bindingIndex);
break; break;
case GL_VERTEX_ATTRIB_RELATIVE_OFFSET: case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
// attrib.relativeOffset should not be negative or greater than max GLint *params = ConvertFromGLuint<ParamType>(attrib.relativeOffset);
ASSERT(attrib.relativeOffset >= 0 &&
attrib.relativeOffset <= std::numeric_limits<GLint>::max());
*params = ConvertFromGLint<ParamType>(static_cast<GLint>(attrib.relativeOffset));
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
......
...@@ -50,7 +50,7 @@ void VertexArray11::syncState(const gl::Context *context, ...@@ -50,7 +50,7 @@ void VertexArray11::syncState(const gl::Context *context,
if (dirtyBit == gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER) if (dirtyBit == gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
continue; continue;
size_t index = gl::VertexArray::GetAttribIndex(dirtyBit); size_t index = gl::VertexArray::GetVertexIndexFromDirtyBit(dirtyBit);
// TODO(jiawei.shao@intel.com): Vertex Attrib Bindings // TODO(jiawei.shao@intel.com): Vertex Attrib Bindings
ASSERT(index == mData.getBindingIndexFromAttribIndex(index)); ASSERT(index == mData.getBindingIndexFromAttribIndex(index));
mAttribsToUpdate.set(index); mAttribsToUpdate.set(index);
......
...@@ -83,7 +83,13 @@ class VertexArrayGL : public VertexArrayImpl ...@@ -83,7 +83,13 @@ class VertexArrayGL : public VertexArrayImpl
void updateNeedsStreaming(size_t attribIndex); void updateNeedsStreaming(size_t attribIndex);
void updateAttribEnabled(size_t attribIndex); void updateAttribEnabled(size_t attribIndex);
void updateAttribPointer(const gl::Context *context, size_t attribIndex); void updateAttribPointer(const gl::Context *context, size_t attribIndex);
void updateAttribDivisor(size_t attribIndex);
bool supportVertexAttribBinding() const;
void updateAttribFormat(size_t attribIndex);
void updateAttribBinding(size_t attribIndex);
void updateBindingBuffer(const gl::Context *context, size_t bindingIndex);
void updateBindingDivisor(size_t bindingIndex);
void callVertexAttribPointer(GLuint attribIndex, void callVertexAttribPointer(GLuint attribIndex,
const gl::VertexAttribute &attrib, const gl::VertexAttribute &attrib,
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
1442 OPENGL D3D11 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.array_size.vertex_fragment.default_block_struct_member = SKIP 1442 OPENGL D3D11 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.array_size.vertex_fragment.default_block_struct_member = SKIP
1442 OPENGL D3D11 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.name_length.vertex_fragment.default_block_struct_member = SKIP 1442 OPENGL D3D11 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.name_length.vertex_fragment.default_block_struct_member = SKIP
1442 OPENGL D3D11 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.type.vertex_fragment.struct.* = SKIP 1442 OPENGL D3D11 : dEQP-GLES31.functional.program_interface_query.transform_feedback_varying.type.vertex_fragment.struct.* = SKIP
1442 OPENGL D3D11 : dEQP-GLES31.functional.vertex_attribute_binding.* = SKIP 1442 D3D11 : dEQP-GLES31.functional.vertex_attribute_binding.* = SKIP
1442 D3D11 : dEQP-GLES31.functional.stencil_texturing.* = SKIP 1442 D3D11 : dEQP-GLES31.functional.stencil_texturing.* = SKIP
1442 D3D11 : dEQP-GLES31.functional.state_query.shader.sampler_type = SKIP 1442 D3D11 : dEQP-GLES31.functional.state_query.shader.sampler_type = SKIP
......
...@@ -217,7 +217,7 @@ class InstancingTest : public ANGLETest ...@@ -217,7 +217,7 @@ class InstancingTest : public ANGLETest
ANGLE_GL_PROGRAM(program, vs, fs); ANGLE_GL_PROGRAM(program, vs, fs);
// Get the attribute locations // Get the attribute locations
GLint positionLoc = glGetAttribLocation(program, "a_position"); GLint positionLoc = glGetAttribLocation(program, "a_position");
GLint instancePosLoc = glGetAttribLocation(program, "a_instancePos"); GLint instancePosLoc = glGetAttribLocation(program, "a_instancePos");
// If this ASSERT fails then the vertex shader code should be refactored // If this ASSERT fails then the vertex shader code should be refactored
...@@ -446,6 +446,102 @@ TEST_P(InstancingTestPoints, DrawElements) ...@@ -446,6 +446,102 @@ TEST_P(InstancingTestPoints, DrawElements)
checkQuads(); checkQuads();
} }
class InstancingTestES31 : public InstancingTest
{
public:
InstancingTestES31() {}
};
// Verify that VertexAttribDivisor can update both binding divisor and attribBinding.
TEST_P(InstancingTestES31, UpdateAttribBindingByVertexAttribDivisor)
{
const std::string vs =
"attribute vec3 a_instancePos;\n"
"attribute vec3 a_position;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(a_position.xyz + a_instancePos.xyz, 1.0);\n"
"}\n";
const std::string fs =
"precision mediump float;\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(1.0, 0, 0, 1.0);\n"
"}\n";
constexpr GLsizei kFloatStride = 4;
ANGLE_GL_PROGRAM(program, vs, fs);
glUseProgram(program);
// Get the attribute locations
GLint positionLoc = glGetAttribLocation(program, "a_position");
GLint instancePosLoc = glGetAttribLocation(program, "a_instancePos");
ASSERT_NE(-1, positionLoc);
ASSERT_NE(-1, instancePosLoc);
ASSERT_GL_NO_ERROR();
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLBuffer quadBuffer;
glBindBuffer(GL_ARRAY_BUFFER, quadBuffer);
glBufferData(GL_ARRAY_BUFFER, mQuadVertices.size() * kFloatStride, mQuadVertices.data(),
GL_STATIC_DRAW);
GLBuffer instancesBuffer;
glBindBuffer(GL_ARRAY_BUFFER, instancesBuffer);
glBufferData(GL_ARRAY_BUFFER, mInstances.size() * kFloatStride, mInstances.data(),
GL_STATIC_DRAW);
// Set the formats by VertexAttribFormat
glVertexAttribFormat(positionLoc, 3, GL_FLOAT, GL_FALSE, 0);
glVertexAttribFormat(instancePosLoc, 3, GL_FLOAT, GL_FALSE, 0);
glEnableVertexAttribArray(positionLoc);
glEnableVertexAttribArray(instancePosLoc);
const GLint positionBinding = instancePosLoc;
const GLint instanceBinding = positionLoc;
// Load the vertex position into the binding indexed positionBinding (== instancePosLoc)
// Load the instance position into the binding indexed instanceBinding (== positionLoc)
glBindVertexBuffer(positionBinding, quadBuffer, 0, kFloatStride * 3);
glBindVertexBuffer(instanceBinding, instancesBuffer, 0, kFloatStride * 3);
// The attribute indexed positionLoc is using the binding indexed positionBinding
// The attribute indexed instancePosLoc is using the binding indexed instanceBinding
glVertexAttribBinding(positionLoc, positionBinding);
glVertexAttribBinding(instancePosLoc, instanceBinding);
// Enable instancing on the binding indexed instanceBinding
glVertexBindingDivisor(instanceBinding, 1);
// Do the first instanced draw
glDrawElementsInstanced(GL_TRIANGLES, static_cast<GLsizei>(mIndices.size()), GL_UNSIGNED_SHORT,
mIndices.data(), static_cast<GLsizei>(mInstances.size()) / 3);
checkQuads();
// Load the vertex position into the binding indexed positionLoc.
// Load the instance position into the binding indexed instancePosLoc.
glBindVertexBuffer(positionLoc, quadBuffer, 0, kFloatStride * 3);
glBindVertexBuffer(instancePosLoc, instancesBuffer, 0, kFloatStride * 3);
// The attribute indexed positionLoc is using the binding indexed positionLoc.
glVertexAttribBinding(positionLoc, positionLoc);
// Call VertexAttribDivisor to both enable instancing on instancePosLoc and set the attribute
// indexed instancePosLoc using the binding indexed instancePosLoc.
glVertexAttribDivisor(instancePosLoc, 1);
// Do the second instanced draw
glDrawElementsInstanced(GL_TRIANGLES, static_cast<GLsizei>(mIndices.size()), GL_UNSIGNED_SHORT,
mIndices.data(), static_cast<GLsizei>(mInstances.size()) / 3);
checkQuads();
glDeleteVertexArrays(1, &vao);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these // Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against. We test on D3D9 and D3D11 9_3 because they use special codepaths // tests should be run against. We test on D3D9 and D3D11 9_3 because they use special codepaths
// when attribute zero is instanced, unlike D3D11. // when attribute zero is instanced, unlike D3D11.
...@@ -460,3 +556,7 @@ ANGLE_INSTANTIATE_TEST(InstancingTestAllConfigs, ...@@ -460,3 +556,7 @@ ANGLE_INSTANTIATE_TEST(InstancingTestAllConfigs,
ANGLE_INSTANTIATE_TEST(InstancingTestNo9_3, ES2_D3D9(), ES2_D3D11()); ANGLE_INSTANTIATE_TEST(InstancingTestNo9_3, ES2_D3D9(), ES2_D3D11());
ANGLE_INSTANTIATE_TEST(InstancingTestPoints, ES2_D3D11(), ES2_D3D11_FL9_3()); ANGLE_INSTANTIATE_TEST(InstancingTestPoints, ES2_D3D11(), ES2_D3D11_FL9_3());
// TODO(jiawei.shao@intel.com): Add D3D11 when Vertex Attrib Binding is supported on D3D11
// back-ends.
ANGLE_INSTANTIATE_TEST(InstancingTestES31, ES31_OPENGL(), ES31_OPENGLES());
...@@ -131,6 +131,9 @@ GLColor32F ReadColor32F(GLint x, GLint y); ...@@ -131,6 +131,9 @@ GLColor32F ReadColor32F(GLint x, GLint y);
#define EXPECT_PIXEL_EQ(x, y, r, g, b, a) \ #define EXPECT_PIXEL_EQ(x, y, r, g, b, a) \
EXPECT_EQ(angle::MakeGLColor(r, g, b, a), angle::ReadColor(x, y)) EXPECT_EQ(angle::MakeGLColor(r, g, b, a), angle::ReadColor(x, y))
#define EXPECT_PIXEL_NE(x, y, r, g, b, a) \
EXPECT_NE(angle::MakeGLColor(r, g, b, a), angle::ReadColor(x, y))
#define EXPECT_PIXEL_32F_EQ(x, y, r, g, b, a) \ #define EXPECT_PIXEL_32F_EQ(x, y, r, g, b, a) \
EXPECT_EQ(angle::MakeGLColor32F(r, g, b, a), angle::ReadColor32F(x, y)) EXPECT_EQ(angle::MakeGLColor32F(r, g, b, a), angle::ReadColor32F(x, y))
......
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