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
bindIndexedUniformBuffer(0, i, 0, -1);
}
bindGenericTransformFeedbackBuffer(0);
for (unsigned int i = 0; i < mCaps.maxTransformFeedbackSeparateAttributes; i++)
{
bindIndexedTransformFeedbackBuffer(0, i, 0, -1);
}
bindCopyReadBuffer(0);
bindCopyWriteBuffer(0);
bindPixelPackBuffer(0);
......@@ -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
// a transform feedback object with a name of zero. That object is bound any time
// BindTransformFeedback is called with id of zero
mTransformFeedbackZero.set(new TransformFeedback(mRenderer->createTransformFeedback(), 0));
mTransformFeedbackZero.set(new TransformFeedback(mRenderer->createTransformFeedback(), 0, mCaps));
bindTransformFeedback(0);
mHasBeenCurrent = false;
......@@ -264,7 +258,7 @@ GLuint Context::createSampler()
GLuint Context::createTransformFeedback()
{
GLuint handle = mTransformFeedbackAllocator.allocate();
TransformFeedback *transformFeedback = new TransformFeedback(mRenderer->createTransformFeedback(), handle);
TransformFeedback *transformFeedback = new TransformFeedback(mRenderer->createTransformFeedback(), handle, mCaps);
transformFeedback->addRef();
mTransformFeedbackMap[handle] = transformFeedback;
return handle;
......@@ -588,14 +582,14 @@ void Context::bindGenericTransformFeedbackBuffer(GLuint buffer)
{
mResourceManager->checkBufferAllocation(buffer);
mState.setGenericTransformFeedbackBufferBinding(getBuffer(buffer));
mState.getCurrentTransformFeedback()->bindGenericBuffer(getBuffer(buffer));
}
void Context::bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size)
{
mResourceManager->checkBufferAllocation(buffer);
mState.setIndexedTransformFeedbackBufferBinding(index, getBuffer(buffer), offset, size);
mState.getCurrentTransformFeedback()->bindIndexedBuffer(index, getBuffer(buffer), offset, size);
}
void Context::bindCopyReadBuffer(GLuint buffer)
......@@ -1125,6 +1119,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
case GL_UNIFORM_BUFFER_BINDING:
case GL_TRANSFORM_FEEDBACK_BINDING:
case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
case GL_COPY_READ_BUFFER_BINDING:
case GL_COPY_WRITE_BUFFER_BINDING:
case GL_TEXTURE_BINDING_3D:
......
......@@ -73,7 +73,6 @@ public:
ObjectType *operator->() const { return mObject; }
GLuint id() const { return (mObject != nullptr) ? mObject->id() : 0; }
bool operator!() const { return (mObject == nullptr); }
private:
ObjectType *mObject;
......
......@@ -120,7 +120,6 @@ void State::initialize(const Caps& caps, GLuint clientVersion)
}
mUniformBuffers.resize(caps.maxCombinedUniformBlocks);
mTransformFeedbackBuffers.resize(caps.maxTransformFeedbackSeparateAttributes);
mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits);
mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits);
......@@ -177,17 +176,11 @@ void State::reset()
}
mGenericUniformBuffer.set(NULL);
mGenericTransformFeedbackBuffer.set(NULL);
for (BufferVector::iterator bufItr = mUniformBuffers.begin(); bufItr != mUniformBuffers.end(); ++bufItr)
{
bufItr->set(NULL);
}
for (BufferVector::iterator bufItr = mTransformFeedbackBuffers.begin(); bufItr != mTransformFeedbackBuffers.end(); ++bufItr)
{
bufItr->set(NULL);
}
mCopyReadBuffer.set(NULL);
mCopyWriteBuffer.set(NULL);
......@@ -956,42 +949,6 @@ GLsizeiptr State::getIndexedUniformBufferSize(GLuint index) const
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)
{
mCopyReadBuffer.set(buffer);
......@@ -1022,7 +979,7 @@ Buffer *State::getTargetBuffer(GLenum target) const
case GL_ELEMENT_ARRAY_BUFFER: return getVertexArray()->getElementArrayBuffer();
case GL_PIXEL_PACK_BUFFER: return mPack.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();
default: UNREACHABLE(); return NULL;
}
......@@ -1366,7 +1323,7 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
*params = mGenericUniformBuffer.id();
break;
case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
*params = mGenericTransformFeedbackBuffer.id();
*params = mTransformFeedback->getGenericBuffer().id();
break;
case GL_COPY_READ_BUFFER_BINDING:
*params = mCopyReadBuffer.id();
......@@ -1391,9 +1348,9 @@ bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data)
switch (target)
{
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;
case GL_UNIFORM_BUFFER_BINDING:
......@@ -1414,15 +1371,15 @@ bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data)
switch (target)
{
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;
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;
case GL_UNIFORM_BUFFER_START:
......
......@@ -203,14 +203,6 @@ class State : angle::NonCopyable
GLintptr getIndexedUniformBufferOffset(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
void setCopyReadBufferBinding(Buffer *buffer);
void setCopyWriteBufferBinding(Buffer *buffer);
......@@ -317,8 +309,6 @@ class State : angle::NonCopyable
BufferVector mUniformBuffers;
BindingPointer<TransformFeedback> mTransformFeedback;
BindingPointer<Buffer> mGenericTransformFeedbackBuffer;
BufferVector mTransformFeedbackBuffers;
BindingPointer<Buffer> mCopyReadBuffer;
BindingPointer<Buffer> mCopyWriteBuffer;
......
......@@ -5,23 +5,34 @@
//
#include "libANGLE/TransformFeedback.h"
#include "libANGLE/Buffer.h"
#include "libANGLE/Caps.h"
#include "libANGLE/renderer/TransformFeedbackImpl.h"
namespace gl
{
TransformFeedback::TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id)
TransformFeedback::TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id, const Caps &caps)
: RefCountObject(id),
mImplementation(impl),
mActive(false),
mPrimitiveMode(GL_NONE),
mPaused(false)
mPaused(false),
mGenericBuffer(),
mIndexedBuffers(caps.maxTransformFeedbackSeparateAttributes)
{
ASSERT(impl != NULL);
}
TransformFeedback::~TransformFeedback()
{
mGenericBuffer.set(nullptr);
for (size_t i = 0; i < mIndexedBuffers.size(); i++)
{
mIndexedBuffers[i].set(nullptr);
}
SafeDelete(mImplementation);
}
......@@ -68,6 +79,35 @@ GLenum TransformFeedback::getPrimitiveMode() const
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()
{
return mImplementation;
......
......@@ -20,11 +20,13 @@ class TransformFeedbackImpl;
namespace gl
{
class Buffer;
struct Caps;
class TransformFeedback : public RefCountObject
{
public:
TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id);
TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id, const Caps &caps);
virtual ~TransformFeedback();
void begin(GLenum primitiveMode);
......@@ -36,6 +38,13 @@ class TransformFeedback : public RefCountObject
bool isPaused() 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();
const rx::TransformFeedbackImpl *getImplementation() const;
......@@ -45,6 +54,9 @@ class TransformFeedback : public RefCountObject
bool mActive;
GLenum mPrimitiveMode;
bool mPaused;
BindingPointer<Buffer> mGenericBuffer;
std::vector<OffsetBindingPointer<Buffer>> mIndexedBuffers;
};
}
......
......@@ -6,32 +6,29 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "libANGLE/Caps.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
{
protected:
virtual void SetUp()
{
mImpl = new MockTransformFeedbackImpl;
EXPECT_CALL(*mImpl, destroy());
mFeedback = new gl::TransformFeedback(mImpl, 1);
// Set a reasonable number of tf attributes
mCaps.maxTransformFeedbackSeparateAttributes = 8;
mImpl = new rx::MockTransformFeedbackImpl;
EXPECT_CALL(*mImpl, destructor());
mFeedback = new gl::TransformFeedback(mImpl, 1, mCaps);
mFeedback->addRef();
}
......@@ -40,16 +37,17 @@ class TransformFeedbackTest : public testing::Test
mFeedback->release();
}
MockTransformFeedbackImpl* mImpl;
rx::MockTransformFeedbackImpl* mImpl;
gl::TransformFeedback* mFeedback;
gl::Caps mCaps;
};
TEST_F(TransformFeedbackTest, DestructionDeletesImpl)
{
MockTransformFeedbackImpl* impl = new MockTransformFeedbackImpl;
EXPECT_CALL(*impl, destroy()).Times(1).RetiresOnSaturation();
rx::MockTransformFeedbackImpl* impl = new rx::MockTransformFeedbackImpl;
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->release();
......@@ -91,4 +89,41 @@ TEST_F(TransformFeedbackTest, SideEffectsOfPauseAndResume)
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
//
// 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
virtual void end() = 0;
virtual void pause() = 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)
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);
if (buffer)
const OffsetBindingPointer<gl::Buffer> &binding = transformFeedback->getIndexedBuffer(i);
if (binding.get() != nullptr)
{
BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
BufferD3D *bufferD3D = GetImplAs<BufferD3D>(binding.get());
bufferD3D->markTransformFeedbackUsage();
}
}
......
......@@ -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
TransformFeedbackD3D();
virtual ~TransformFeedbackD3D();
virtual void begin(GLenum primitiveMode);
virtual void end();
virtual void pause();
virtual void resume();
void begin(GLenum primitiveMode) override;
void end() override;
void pause() override;
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)
if (state.isTransformFeedbackActiveUnpaused())
{
numXFBBindings = state.getTransformFeedbackBufferIndexRange();
const gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback();
numXFBBindings = transformFeedback->getIndexedBufferCount();
ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
for (size_t i = 0; i < numXFBBindings; i++)
{
gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i);
GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i);
const OffsetBindingPointer<gl::Buffer> &binding = transformFeedback->getIndexedBuffer(i);
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);
}
// 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;
}
......@@ -1449,18 +1450,17 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State &state)
if (requiresUpdate || numXFBBindings != mAppliedNumXFBBindings)
{
const gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback();
for (size_t i = 0; i < numXFBBindings; ++i)
{
gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i);
GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i);
if (curXFBBuffer)
const OffsetBindingPointer<gl::Buffer> &binding = transformFeedback->getIndexedBuffer(i);
if (binding.get() != nullptr)
{
Buffer11 *storage = GetImplAs<Buffer11>(curXFBBuffer);
Buffer11 *storage = GetImplAs<Buffer11>(binding.get());
ID3D11Buffer *d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer || mAppliedTFOffsets[i] != curXFBOffset) ?
static_cast<UINT>(curXFBOffset) : -1;
mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer || mAppliedTFOffsets[i] != binding.getOffset()) ?
static_cast<UINT>(binding.getOffset()) : -1;
mAppliedTFBuffers[i] = d3dBuffer;
}
else
......@@ -1468,7 +1468,7 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State &state)
mAppliedTFBuffers[i] = NULL;
mCurrentD3DOffsets[i] = 0;
}
mAppliedTFOffsets[i] = curXFBOffset;
mAppliedTFOffsets[i] = binding.getOffset();
}
mAppliedNumXFBBindings = numXFBBindings;
......
......@@ -40,4 +40,14 @@ void TransformFeedbackGL::resume()
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
void end() override;
void pause() 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 @@
'<(angle_path)/src/libANGLE/ResourceManager_unittest.cpp',
'<(angle_path)/src/libANGLE/Surface_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/compiler_tests/API_test.cpp',
'<(angle_path)/src/tests/compiler_tests/CollectVariables_test.cpp',
......
......@@ -194,3 +194,61 @@ TYPED_TEST(TransformFeedbackTest, RecordAndDraw)
EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
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