Commit 045536bf by Geoff Lang

Store current transform feedback buffer bindings in the object itself.

BUG=angleproject:763 Change-Id: I76565f68fa8145da29713de2a517a39a8d50a24b Reviewed-on: https://chromium-review.googlesource.com/263061Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent bb0a0bbd
...@@ -100,12 +100,6 @@ Context::Context(const egl::Config *config, int clientVersion, const Context *sh ...@@ -100,12 +100,6 @@ Context::Context(const egl::Config *config, int clientVersion, const Context *sh
bindIndexedUniformBuffer(0, i, 0, -1); bindIndexedUniformBuffer(0, i, 0, -1);
} }
bindGenericTransformFeedbackBuffer(0);
for (unsigned int i = 0; i < mCaps.maxTransformFeedbackSeparateAttributes; i++)
{
bindIndexedTransformFeedbackBuffer(0, i, 0, -1);
}
bindCopyReadBuffer(0); bindCopyReadBuffer(0);
bindCopyWriteBuffer(0); bindCopyWriteBuffer(0);
bindPixelPackBuffer(0); bindPixelPackBuffer(0);
...@@ -115,7 +109,7 @@ Context::Context(const egl::Config *config, int clientVersion, const Context *sh ...@@ -115,7 +109,7 @@ Context::Context(const egl::Config *config, int clientVersion, const Context *sh
// In the initial state, a default transform feedback object is bound and treated as // In the initial state, a default transform feedback object is bound and treated as
// a transform feedback object with a name of zero. That object is bound any time // a transform feedback object with a name of zero. That object is bound any time
// BindTransformFeedback is called with id of zero // BindTransformFeedback is called with id of zero
mTransformFeedbackZero.set(new TransformFeedback(mRenderer->createTransformFeedback(), 0)); mTransformFeedbackZero.set(new TransformFeedback(mRenderer->createTransformFeedback(), 0, mCaps));
bindTransformFeedback(0); bindTransformFeedback(0);
mHasBeenCurrent = false; mHasBeenCurrent = false;
...@@ -264,7 +258,7 @@ GLuint Context::createSampler() ...@@ -264,7 +258,7 @@ GLuint Context::createSampler()
GLuint Context::createTransformFeedback() GLuint Context::createTransformFeedback()
{ {
GLuint handle = mTransformFeedbackAllocator.allocate(); GLuint handle = mTransformFeedbackAllocator.allocate();
TransformFeedback *transformFeedback = new TransformFeedback(mRenderer->createTransformFeedback(), handle); TransformFeedback *transformFeedback = new TransformFeedback(mRenderer->createTransformFeedback(), handle, mCaps);
transformFeedback->addRef(); transformFeedback->addRef();
mTransformFeedbackMap[handle] = transformFeedback; mTransformFeedbackMap[handle] = transformFeedback;
return handle; return handle;
...@@ -588,14 +582,14 @@ void Context::bindGenericTransformFeedbackBuffer(GLuint buffer) ...@@ -588,14 +582,14 @@ void Context::bindGenericTransformFeedbackBuffer(GLuint buffer)
{ {
mResourceManager->checkBufferAllocation(buffer); mResourceManager->checkBufferAllocation(buffer);
mState.setGenericTransformFeedbackBufferBinding(getBuffer(buffer)); mState.getCurrentTransformFeedback()->bindGenericBuffer(getBuffer(buffer));
} }
void Context::bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size) void Context::bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size)
{ {
mResourceManager->checkBufferAllocation(buffer); mResourceManager->checkBufferAllocation(buffer);
mState.setIndexedTransformFeedbackBufferBinding(index, getBuffer(buffer), offset, size); mState.getCurrentTransformFeedback()->bindIndexedBuffer(index, getBuffer(buffer), offset, size);
} }
void Context::bindCopyReadBuffer(GLuint buffer) void Context::bindCopyReadBuffer(GLuint buffer)
...@@ -1125,6 +1119,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu ...@@ -1125,6 +1119,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
case GL_UNIFORM_BUFFER_BINDING: case GL_UNIFORM_BUFFER_BINDING:
case GL_TRANSFORM_FEEDBACK_BINDING: case GL_TRANSFORM_FEEDBACK_BINDING:
case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
case GL_COPY_READ_BUFFER_BINDING: case GL_COPY_READ_BUFFER_BINDING:
case GL_COPY_WRITE_BUFFER_BINDING: case GL_COPY_WRITE_BUFFER_BINDING:
case GL_TEXTURE_BINDING_3D: case GL_TEXTURE_BINDING_3D:
......
...@@ -73,7 +73,6 @@ public: ...@@ -73,7 +73,6 @@ public:
ObjectType *operator->() const { return mObject; } ObjectType *operator->() const { return mObject; }
GLuint id() const { return (mObject != nullptr) ? mObject->id() : 0; } GLuint id() const { return (mObject != nullptr) ? mObject->id() : 0; }
bool operator!() const { return (mObject == nullptr); }
private: private:
ObjectType *mObject; ObjectType *mObject;
......
...@@ -120,7 +120,6 @@ void State::initialize(const Caps& caps, GLuint clientVersion) ...@@ -120,7 +120,6 @@ void State::initialize(const Caps& caps, GLuint clientVersion)
} }
mUniformBuffers.resize(caps.maxCombinedUniformBlocks); mUniformBuffers.resize(caps.maxCombinedUniformBlocks);
mTransformFeedbackBuffers.resize(caps.maxTransformFeedbackSeparateAttributes);
mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits); mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits);
mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits); mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits);
...@@ -177,17 +176,11 @@ void State::reset() ...@@ -177,17 +176,11 @@ void State::reset()
} }
mGenericUniformBuffer.set(NULL); mGenericUniformBuffer.set(NULL);
mGenericTransformFeedbackBuffer.set(NULL);
for (BufferVector::iterator bufItr = mUniformBuffers.begin(); bufItr != mUniformBuffers.end(); ++bufItr) for (BufferVector::iterator bufItr = mUniformBuffers.begin(); bufItr != mUniformBuffers.end(); ++bufItr)
{ {
bufItr->set(NULL); bufItr->set(NULL);
} }
for (BufferVector::iterator bufItr = mTransformFeedbackBuffers.begin(); bufItr != mTransformFeedbackBuffers.end(); ++bufItr)
{
bufItr->set(NULL);
}
mCopyReadBuffer.set(NULL); mCopyReadBuffer.set(NULL);
mCopyWriteBuffer.set(NULL); mCopyWriteBuffer.set(NULL);
...@@ -956,42 +949,6 @@ GLsizeiptr State::getIndexedUniformBufferSize(GLuint index) const ...@@ -956,42 +949,6 @@ GLsizeiptr State::getIndexedUniformBufferSize(GLuint index) const
return mUniformBuffers[index].getSize(); return mUniformBuffers[index].getSize();
} }
void State::setGenericTransformFeedbackBufferBinding(Buffer *buffer)
{
mGenericTransformFeedbackBuffer.set(buffer);
}
void State::setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size)
{
mTransformFeedbackBuffers[index].set(buffer, offset, size);
}
GLuint State::getIndexedTransformFeedbackBufferId(GLuint index) const
{
ASSERT(static_cast<size_t>(index) < mTransformFeedbackBuffers.size());
return mTransformFeedbackBuffers[index].id();
}
Buffer *State::getIndexedTransformFeedbackBuffer(GLuint index) const
{
ASSERT(static_cast<size_t>(index) < mTransformFeedbackBuffers.size());
return mTransformFeedbackBuffers[index].get();
}
GLuint State::getIndexedTransformFeedbackBufferOffset(GLuint index) const
{
ASSERT(static_cast<size_t>(index) < mTransformFeedbackBuffers.size());
return static_cast<unsigned int>(mTransformFeedbackBuffers[index].getOffset());
}
size_t State::getTransformFeedbackBufferIndexRange() const
{
return mTransformFeedbackBuffers.size();
}
void State::setCopyReadBufferBinding(Buffer *buffer) void State::setCopyReadBufferBinding(Buffer *buffer)
{ {
mCopyReadBuffer.set(buffer); mCopyReadBuffer.set(buffer);
...@@ -1022,7 +979,7 @@ Buffer *State::getTargetBuffer(GLenum target) const ...@@ -1022,7 +979,7 @@ Buffer *State::getTargetBuffer(GLenum target) const
case GL_ELEMENT_ARRAY_BUFFER: return getVertexArray()->getElementArrayBuffer(); case GL_ELEMENT_ARRAY_BUFFER: return getVertexArray()->getElementArrayBuffer();
case GL_PIXEL_PACK_BUFFER: return mPack.pixelBuffer.get(); case GL_PIXEL_PACK_BUFFER: return mPack.pixelBuffer.get();
case GL_PIXEL_UNPACK_BUFFER: return mUnpack.pixelBuffer.get(); case GL_PIXEL_UNPACK_BUFFER: return mUnpack.pixelBuffer.get();
case GL_TRANSFORM_FEEDBACK_BUFFER: return mGenericTransformFeedbackBuffer.get(); case GL_TRANSFORM_FEEDBACK_BUFFER: return mTransformFeedback->getGenericBuffer().get();
case GL_UNIFORM_BUFFER: return mGenericUniformBuffer.get(); case GL_UNIFORM_BUFFER: return mGenericUniformBuffer.get();
default: UNREACHABLE(); return NULL; default: UNREACHABLE(); return NULL;
} }
...@@ -1366,7 +1323,7 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) ...@@ -1366,7 +1323,7 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
*params = mGenericUniformBuffer.id(); *params = mGenericUniformBuffer.id();
break; break;
case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
*params = mGenericTransformFeedbackBuffer.id(); *params = mTransformFeedback->getGenericBuffer().id();
break; break;
case GL_COPY_READ_BUFFER_BINDING: case GL_COPY_READ_BUFFER_BINDING:
*params = mCopyReadBuffer.id(); *params = mCopyReadBuffer.id();
...@@ -1391,9 +1348,9 @@ bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data) ...@@ -1391,9 +1348,9 @@ bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data)
switch (target) switch (target)
{ {
case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
if (static_cast<size_t>(index) < mTransformFeedbackBuffers.size()) if (static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount())
{ {
*data = mTransformFeedbackBuffers[index].id(); *data = mTransformFeedback->getIndexedBuffer(index).id();
} }
break; break;
case GL_UNIFORM_BUFFER_BINDING: case GL_UNIFORM_BUFFER_BINDING:
...@@ -1414,15 +1371,15 @@ bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data) ...@@ -1414,15 +1371,15 @@ bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data)
switch (target) switch (target)
{ {
case GL_TRANSFORM_FEEDBACK_BUFFER_START: case GL_TRANSFORM_FEEDBACK_BUFFER_START:
if (static_cast<size_t>(index) < mTransformFeedbackBuffers.size()) if (static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount())
{ {
*data = mTransformFeedbackBuffers[index].getOffset(); *data = mTransformFeedback->getIndexedBuffer(index).getOffset();
} }
break; break;
case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
if (static_cast<size_t>(index) < mTransformFeedbackBuffers.size()) if (static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount())
{ {
*data = mTransformFeedbackBuffers[index].getSize(); *data = mTransformFeedback->getIndexedBuffer(index).getSize();
} }
break; break;
case GL_UNIFORM_BUFFER_START: case GL_UNIFORM_BUFFER_START:
......
...@@ -203,14 +203,6 @@ class State : angle::NonCopyable ...@@ -203,14 +203,6 @@ class State : angle::NonCopyable
GLintptr getIndexedUniformBufferOffset(GLuint index) const; GLintptr getIndexedUniformBufferOffset(GLuint index) const;
GLsizeiptr getIndexedUniformBufferSize(GLuint index) const; GLsizeiptr getIndexedUniformBufferSize(GLuint index) const;
// GL_TRANSFORM_FEEDBACK_BUFFER - Both indexed and generic targets
void setGenericTransformFeedbackBufferBinding(Buffer *buffer);
void setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size);
GLuint getIndexedTransformFeedbackBufferId(GLuint index) const;
Buffer *getIndexedTransformFeedbackBuffer(GLuint index) const;
GLuint getIndexedTransformFeedbackBufferOffset(GLuint index) const;
size_t getTransformFeedbackBufferIndexRange() const;
// GL_COPY_[READ/WRITE]_BUFFER // GL_COPY_[READ/WRITE]_BUFFER
void setCopyReadBufferBinding(Buffer *buffer); void setCopyReadBufferBinding(Buffer *buffer);
void setCopyWriteBufferBinding(Buffer *buffer); void setCopyWriteBufferBinding(Buffer *buffer);
...@@ -317,8 +309,6 @@ class State : angle::NonCopyable ...@@ -317,8 +309,6 @@ class State : angle::NonCopyable
BufferVector mUniformBuffers; BufferVector mUniformBuffers;
BindingPointer<TransformFeedback> mTransformFeedback; BindingPointer<TransformFeedback> mTransformFeedback;
BindingPointer<Buffer> mGenericTransformFeedbackBuffer;
BufferVector mTransformFeedbackBuffers;
BindingPointer<Buffer> mCopyReadBuffer; BindingPointer<Buffer> mCopyReadBuffer;
BindingPointer<Buffer> mCopyWriteBuffer; BindingPointer<Buffer> mCopyWriteBuffer;
......
...@@ -5,23 +5,34 @@ ...@@ -5,23 +5,34 @@
// //
#include "libANGLE/TransformFeedback.h" #include "libANGLE/TransformFeedback.h"
#include "libANGLE/Buffer.h"
#include "libANGLE/Caps.h"
#include "libANGLE/renderer/TransformFeedbackImpl.h" #include "libANGLE/renderer/TransformFeedbackImpl.h"
namespace gl namespace gl
{ {
TransformFeedback::TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id) TransformFeedback::TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id, const Caps &caps)
: RefCountObject(id), : RefCountObject(id),
mImplementation(impl), mImplementation(impl),
mActive(false), mActive(false),
mPrimitiveMode(GL_NONE), mPrimitiveMode(GL_NONE),
mPaused(false) mPaused(false),
mGenericBuffer(),
mIndexedBuffers(caps.maxTransformFeedbackSeparateAttributes)
{ {
ASSERT(impl != NULL); ASSERT(impl != NULL);
} }
TransformFeedback::~TransformFeedback() TransformFeedback::~TransformFeedback()
{ {
mGenericBuffer.set(nullptr);
for (size_t i = 0; i < mIndexedBuffers.size(); i++)
{
mIndexedBuffers[i].set(nullptr);
}
SafeDelete(mImplementation); SafeDelete(mImplementation);
} }
...@@ -68,6 +79,35 @@ GLenum TransformFeedback::getPrimitiveMode() const ...@@ -68,6 +79,35 @@ GLenum TransformFeedback::getPrimitiveMode() const
return mPrimitiveMode; return mPrimitiveMode;
} }
void TransformFeedback::bindGenericBuffer(Buffer *buffer)
{
mGenericBuffer.set(buffer);
mImplementation->bindGenericBuffer(mGenericBuffer);
}
const BindingPointer<Buffer> &TransformFeedback::getGenericBuffer() const
{
return mGenericBuffer;
}
void TransformFeedback::bindIndexedBuffer(size_t index, Buffer *buffer, size_t offset, size_t size)
{
ASSERT(index < mIndexedBuffers.size());
mIndexedBuffers[index].set(buffer, offset, size);
mImplementation->bindIndexedBuffer(index, mIndexedBuffers[index]);
}
const OffsetBindingPointer<Buffer> &TransformFeedback::getIndexedBuffer(size_t index) const
{
ASSERT(index < mIndexedBuffers.size());
return mIndexedBuffers[index];
}
size_t TransformFeedback::getIndexedBufferCount() const
{
return mIndexedBuffers.size();
}
rx::TransformFeedbackImpl *TransformFeedback::getImplementation() rx::TransformFeedbackImpl *TransformFeedback::getImplementation()
{ {
return mImplementation; return mImplementation;
......
...@@ -20,11 +20,13 @@ class TransformFeedbackImpl; ...@@ -20,11 +20,13 @@ class TransformFeedbackImpl;
namespace gl namespace gl
{ {
class Buffer;
struct Caps;
class TransformFeedback : public RefCountObject class TransformFeedback : public RefCountObject
{ {
public: public:
TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id); TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id, const Caps &caps);
virtual ~TransformFeedback(); virtual ~TransformFeedback();
void begin(GLenum primitiveMode); void begin(GLenum primitiveMode);
...@@ -36,6 +38,13 @@ class TransformFeedback : public RefCountObject ...@@ -36,6 +38,13 @@ class TransformFeedback : public RefCountObject
bool isPaused() const; bool isPaused() const;
GLenum getPrimitiveMode() const; GLenum getPrimitiveMode() const;
void bindGenericBuffer(Buffer *buffer);
const BindingPointer<Buffer> &getGenericBuffer() const;
void bindIndexedBuffer(size_t index, Buffer *buffer, size_t offset, size_t size);
const OffsetBindingPointer<Buffer> &getIndexedBuffer(size_t index) const;
size_t getIndexedBufferCount() const;
rx::TransformFeedbackImpl *getImplementation(); rx::TransformFeedbackImpl *getImplementation();
const rx::TransformFeedbackImpl *getImplementation() const; const rx::TransformFeedbackImpl *getImplementation() const;
...@@ -45,6 +54,9 @@ class TransformFeedback : public RefCountObject ...@@ -45,6 +54,9 @@ class TransformFeedback : public RefCountObject
bool mActive; bool mActive;
GLenum mPrimitiveMode; GLenum mPrimitiveMode;
bool mPaused; bool mPaused;
BindingPointer<Buffer> mGenericBuffer;
std::vector<OffsetBindingPointer<Buffer>> mIndexedBuffers;
}; };
} }
......
...@@ -6,32 +6,29 @@ ...@@ -6,32 +6,29 @@
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "libANGLE/Caps.h"
#include "libANGLE/TransformFeedback.h" #include "libANGLE/TransformFeedback.h"
#include "libANGLE/renderer/TransformFeedbackImpl.h" #include "libANGLE/renderer/BufferImpl_mock.h"
#include "libANGLE/renderer/TransformFeedbackImpl_mock.h"
namespace { using ::testing::_;
using ::testing::Return;
using ::testing::SetArgumentPointee;
class MockTransformFeedbackImpl : public rx::TransformFeedbackImpl namespace
{ {
public:
virtual ~MockTransformFeedbackImpl() { destroy(); }
MOCK_METHOD1(begin, void(GLenum primitiveMode));
MOCK_METHOD0(end, void());
MOCK_METHOD0(pause, void());
MOCK_METHOD0(resume, void());
MOCK_METHOD0(destroy, void());
};
class TransformFeedbackTest : public testing::Test class TransformFeedbackTest : public testing::Test
{ {
protected: protected:
virtual void SetUp() virtual void SetUp()
{ {
mImpl = new MockTransformFeedbackImpl; // Set a reasonable number of tf attributes
EXPECT_CALL(*mImpl, destroy()); mCaps.maxTransformFeedbackSeparateAttributes = 8;
mFeedback = new gl::TransformFeedback(mImpl, 1);
mImpl = new rx::MockTransformFeedbackImpl;
EXPECT_CALL(*mImpl, destructor());
mFeedback = new gl::TransformFeedback(mImpl, 1, mCaps);
mFeedback->addRef(); mFeedback->addRef();
} }
...@@ -40,16 +37,17 @@ class TransformFeedbackTest : public testing::Test ...@@ -40,16 +37,17 @@ class TransformFeedbackTest : public testing::Test
mFeedback->release(); mFeedback->release();
} }
MockTransformFeedbackImpl* mImpl; rx::MockTransformFeedbackImpl* mImpl;
gl::TransformFeedback* mFeedback; gl::TransformFeedback* mFeedback;
gl::Caps mCaps;
}; };
TEST_F(TransformFeedbackTest, DestructionDeletesImpl) TEST_F(TransformFeedbackTest, DestructionDeletesImpl)
{ {
MockTransformFeedbackImpl* impl = new MockTransformFeedbackImpl; rx::MockTransformFeedbackImpl* impl = new rx::MockTransformFeedbackImpl;
EXPECT_CALL(*impl, destroy()).Times(1).RetiresOnSaturation(); EXPECT_CALL(*impl, destructor()).Times(1).RetiresOnSaturation();
gl::TransformFeedback* feedback = new gl::TransformFeedback(impl, 1); gl::TransformFeedback* feedback = new gl::TransformFeedback(impl, 1, mCaps);
feedback->addRef(); feedback->addRef();
feedback->release(); feedback->release();
...@@ -91,4 +89,41 @@ TEST_F(TransformFeedbackTest, SideEffectsOfPauseAndResume) ...@@ -91,4 +89,41 @@ TEST_F(TransformFeedbackTest, SideEffectsOfPauseAndResume)
mFeedback->end(); mFeedback->end();
} }
TEST_F(TransformFeedbackTest, BufferBinding)
{
rx::MockBufferImpl *bufferImpl = new rx::MockBufferImpl;
gl::Buffer *buffer = new gl::Buffer(bufferImpl, 1);
EXPECT_CALL(*bufferImpl, destructor()).Times(1).RetiresOnSaturation();
static const size_t bindIndex = 0;
rx::MockTransformFeedbackImpl *feedbackImpl = new rx::MockTransformFeedbackImpl;
gl::TransformFeedback *feedback = new gl::TransformFeedback(feedbackImpl, 1, mCaps);
EXPECT_EQ(feedback->getIndexedBufferCount(), mCaps.maxTransformFeedbackSeparateAttributes);
EXPECT_CALL(*feedbackImpl, bindGenericBuffer(_));
feedback->bindGenericBuffer(buffer);
EXPECT_EQ(feedback->getGenericBuffer().get(), buffer);
EXPECT_CALL(*feedbackImpl, bindIndexedBuffer(_, _));
feedback->bindIndexedBuffer(bindIndex, buffer, 0, 1);
for (size_t i = 0; i < feedback->getIndexedBufferCount(); i++)
{
if (i == bindIndex)
{
EXPECT_EQ(feedback->getIndexedBuffer(i).get(), buffer);
}
else
{
EXPECT_EQ(feedback->getIndexedBuffer(i).get(), nullptr);
}
}
feedback->addRef();
feedback->release();
testing::Mock::VerifyAndClear(bufferImpl);
}
} // namespace } // namespace
//
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// BufferImpl_mock.h: Defines a mock of the BufferImpl class.
#ifndef LIBANGLE_RENDERER_BUFFERIMPLMOCK_H_
#define LIBANGLE_RENDERER_BUFFERIMPLMOCK_H_
#include "gmock/gmock.h"
#include "libANGLE/renderer/BufferImpl.h"
namespace rx
{
class MockBufferImpl : public BufferImpl
{
public:
~MockBufferImpl() override { destructor(); }
MOCK_METHOD3(setData, gl::Error(const void*, size_t, GLenum));
MOCK_METHOD3(setSubData, gl::Error(const void*, size_t, size_t));
MOCK_METHOD4(copySubData, gl::Error(BufferImpl *, GLintptr, GLintptr, GLsizeiptr));
MOCK_METHOD2(map, gl::Error(GLenum, GLvoid **));
MOCK_METHOD4(mapRange, gl::Error(size_t, size_t, GLbitfield, GLvoid **));
MOCK_METHOD1(unmap, gl::Error(GLboolean *result));
MOCK_METHOD1(getData, gl::Error(const uint8_t **));
MOCK_METHOD0(destructor, void());
};
}
#endif // LIBANGLE_RENDERER_BUFFERIMPLMOCK_H_
...@@ -24,6 +24,9 @@ class TransformFeedbackImpl : angle::NonCopyable ...@@ -24,6 +24,9 @@ class TransformFeedbackImpl : angle::NonCopyable
virtual void end() = 0; virtual void end() = 0;
virtual void pause() = 0; virtual void pause() = 0;
virtual void resume() = 0; virtual void resume() = 0;
virtual void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) = 0;
virtual void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) = 0;
}; };
} }
......
//
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// TransformFeedbackImpl_mock.h: Defines a mock of the TransformFeedbackImpl class.
#ifndef LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPLMOCK_H_
#define LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPLMOCK_H_
#include "gmock/gmock.h"
#include "libANGLE/renderer/TransformFeedbackImpl.h"
namespace rx
{
class MockTransformFeedbackImpl : public TransformFeedbackImpl
{
public:
~MockTransformFeedbackImpl() override { destructor(); }
MOCK_METHOD1(begin, void(GLenum primitiveMode));
MOCK_METHOD0(end, void());
MOCK_METHOD0(pause, void());
MOCK_METHOD0(resume, void());
MOCK_METHOD1(bindGenericBuffer, void(const BindingPointer<gl::Buffer> &));
MOCK_METHOD2(bindIndexedBuffer, void(size_t, const OffsetBindingPointer<gl::Buffer> &));
MOCK_METHOD0(destructor, void());
};
}
#endif // LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPLMOCK_H_
...@@ -496,12 +496,13 @@ bool RendererD3D::skipDraw(const gl::Data &data, GLenum drawMode) ...@@ -496,12 +496,13 @@ bool RendererD3D::skipDraw(const gl::Data &data, GLenum drawMode)
void RendererD3D::markTransformFeedbackUsage(const gl::Data &data) void RendererD3D::markTransformFeedbackUsage(const gl::Data &data)
{ {
for (size_t i = 0; i < data.caps->maxTransformFeedbackSeparateAttributes; i++) const gl::TransformFeedback *transformFeedback = data.state->getCurrentTransformFeedback();
for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
{ {
gl::Buffer *buffer = data.state->getIndexedTransformFeedbackBuffer(i); const OffsetBindingPointer<gl::Buffer> &binding = transformFeedback->getIndexedBuffer(i);
if (buffer) if (binding.get() != nullptr)
{ {
BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer); BufferD3D *bufferD3D = GetImplAs<BufferD3D>(binding.get());
bufferD3D->markTransformFeedbackUsage(); bufferD3D->markTransformFeedbackUsage();
} }
} }
......
...@@ -35,4 +35,12 @@ void TransformFeedbackD3D::resume() ...@@ -35,4 +35,12 @@ void TransformFeedbackD3D::resume()
{ {
} }
void TransformFeedbackD3D::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
{
}
void TransformFeedbackD3D::bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding)
{
}
} }
...@@ -21,10 +21,13 @@ class TransformFeedbackD3D : public TransformFeedbackImpl ...@@ -21,10 +21,13 @@ class TransformFeedbackD3D : public TransformFeedbackImpl
TransformFeedbackD3D(); TransformFeedbackD3D();
virtual ~TransformFeedbackD3D(); virtual ~TransformFeedbackD3D();
virtual void begin(GLenum primitiveMode); void begin(GLenum primitiveMode) override;
virtual void end(); void end() override;
virtual void pause(); void pause() override;
virtual void resume(); void resume() override;
void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override;
void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override;
}; };
} }
......
...@@ -1425,22 +1425,23 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State &state) ...@@ -1425,22 +1425,23 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State &state)
if (state.isTransformFeedbackActiveUnpaused()) if (state.isTransformFeedbackActiveUnpaused())
{ {
numXFBBindings = state.getTransformFeedbackBufferIndexRange(); const gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback();
numXFBBindings = transformFeedback->getIndexedBufferCount();
ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
for (size_t i = 0; i < numXFBBindings; i++) for (size_t i = 0; i < numXFBBindings; i++)
{ {
gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i); const OffsetBindingPointer<gl::Buffer> &binding = transformFeedback->getIndexedBuffer(i);
GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i);
ID3D11Buffer *d3dBuffer = NULL; ID3D11Buffer *d3dBuffer = NULL;
if (curXFBBuffer) if (binding.get() != nullptr)
{ {
Buffer11 *storage = GetImplAs<Buffer11>(curXFBBuffer); Buffer11 *storage = GetImplAs<Buffer11>(binding.get());
d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
} }
// TODO: mAppliedTFBuffers and friends should also be kept in a vector. // TODO: mAppliedTFBuffers and friends should also be kept in a vector.
if (d3dBuffer != mAppliedTFBuffers[i] || curXFBOffset != mAppliedTFOffsets[i]) if (d3dBuffer != mAppliedTFBuffers[i] || binding.getOffset() != mAppliedTFOffsets[i])
{ {
requiresUpdate = true; requiresUpdate = true;
} }
...@@ -1449,18 +1450,17 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State &state) ...@@ -1449,18 +1450,17 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State &state)
if (requiresUpdate || numXFBBindings != mAppliedNumXFBBindings) if (requiresUpdate || numXFBBindings != mAppliedNumXFBBindings)
{ {
const gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback();
for (size_t i = 0; i < numXFBBindings; ++i) for (size_t i = 0; i < numXFBBindings; ++i)
{ {
gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i); const OffsetBindingPointer<gl::Buffer> &binding = transformFeedback->getIndexedBuffer(i);
GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i); if (binding.get() != nullptr)
if (curXFBBuffer)
{ {
Buffer11 *storage = GetImplAs<Buffer11>(curXFBBuffer); Buffer11 *storage = GetImplAs<Buffer11>(binding.get());
ID3D11Buffer *d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); ID3D11Buffer *d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer || mAppliedTFOffsets[i] != curXFBOffset) ? mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer || mAppliedTFOffsets[i] != binding.getOffset()) ?
static_cast<UINT>(curXFBOffset) : -1; static_cast<UINT>(binding.getOffset()) : -1;
mAppliedTFBuffers[i] = d3dBuffer; mAppliedTFBuffers[i] = d3dBuffer;
} }
else else
...@@ -1468,7 +1468,7 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State &state) ...@@ -1468,7 +1468,7 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State &state)
mAppliedTFBuffers[i] = NULL; mAppliedTFBuffers[i] = NULL;
mCurrentD3DOffsets[i] = 0; mCurrentD3DOffsets[i] = 0;
} }
mAppliedTFOffsets[i] = curXFBOffset; mAppliedTFOffsets[i] = binding.getOffset();
} }
mAppliedNumXFBBindings = numXFBBindings; mAppliedNumXFBBindings = numXFBBindings;
......
...@@ -40,4 +40,14 @@ void TransformFeedbackGL::resume() ...@@ -40,4 +40,14 @@ void TransformFeedbackGL::resume()
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void TransformFeedbackGL::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
{
UNIMPLEMENTED();
}
void TransformFeedbackGL::bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding)
{
UNIMPLEMENTED();
}
} }
...@@ -24,6 +24,9 @@ class TransformFeedbackGL : public TransformFeedbackImpl ...@@ -24,6 +24,9 @@ class TransformFeedbackGL : public TransformFeedbackImpl
void end() override; void end() override;
void pause() override; void pause() override;
void resume() override; void resume() override;
void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override;
void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override;
}; };
} }
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
'<(angle_path)/src/libANGLE/ResourceManager_unittest.cpp', '<(angle_path)/src/libANGLE/ResourceManager_unittest.cpp',
'<(angle_path)/src/libANGLE/Surface_unittest.cpp', '<(angle_path)/src/libANGLE/Surface_unittest.cpp',
'<(angle_path)/src/libANGLE/TransformFeedback_unittest.cpp', '<(angle_path)/src/libANGLE/TransformFeedback_unittest.cpp',
'<(angle_path)/src/libANGLE/renderer/BufferImpl_mock.h',
'<(angle_path)/src/libANGLE/renderer/TransformFeedbackImpl_mock.h',
'<(angle_path)/src/tests/angle_unittests_utils.h', '<(angle_path)/src/tests/angle_unittests_utils.h',
'<(angle_path)/src/tests/compiler_tests/API_test.cpp', '<(angle_path)/src/tests/compiler_tests/API_test.cpp',
'<(angle_path)/src/tests/compiler_tests/CollectVariables_test.cpp', '<(angle_path)/src/tests/compiler_tests/CollectVariables_test.cpp',
......
...@@ -194,3 +194,61 @@ TYPED_TEST(TransformFeedbackTest, RecordAndDraw) ...@@ -194,3 +194,61 @@ TYPED_TEST(TransformFeedbackTest, RecordAndDraw)
EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255); EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Test that buffer binding happens only on the current transform feedback object
TYPED_TEST(TransformFeedbackTest, BufferBinding)
{
// Reset any state
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
// Generate a new transform feedback and buffer
GLuint transformFeedbackObject = 0;
glGenTransformFeedbacks(1, &transformFeedbackObject);
GLuint scratchBuffer = 0;
glGenBuffers(1, &scratchBuffer);
EXPECT_GL_NO_ERROR();
// Bind TF 0 and a buffer
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBuffer);
EXPECT_GL_NO_ERROR();
// Check that the buffer ID matches the one that was just bound
GLint currentBufferBinding = 0;
glGetIntegerv(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, &currentBufferBinding);
EXPECT_EQ(currentBufferBinding, mTransformFeedbackBuffer);
EXPECT_GL_NO_ERROR();
// Check that the buffer ID for the newly bound transform feedback is zero
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackObject);
glGetIntegerv(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, &currentBufferBinding);
EXPECT_EQ(currentBufferBinding, 0);
EXPECT_GL_NO_ERROR();
// Bind a buffer to this TF
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, scratchBuffer, 0, 32);
glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, 0, &currentBufferBinding);
EXPECT_EQ(scratchBuffer, currentBufferBinding);
EXPECT_GL_NO_ERROR();
// Rebind the original TF and check it's bindings
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, 0, &currentBufferBinding);
EXPECT_EQ(0, currentBufferBinding);
EXPECT_GL_NO_ERROR();
// Clean up
glDeleteTransformFeedbacks(1, &transformFeedbackObject);
glDeleteBuffers(1, &scratchBuffer);
}
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