Commit 73bd218e by Geoff Lang Committed by Commit Bot

Support virtualized contexts and transform feedback in Renderer11.

Track buffer offets in the transform feedback object and dirty them when a buffer is bound. This fixes problems when a buffer is rebound at the same offset and maintains tracking between context switches. BUG=angleproject:1447 BUG=angleproject:1298 Change-Id: I2f890e3ad5edacab47f624a95a502615c86cc0c8 Reviewed-on: https://chromium-review.googlesource.com/360910Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent e074f728
...@@ -16,31 +16,51 @@ ...@@ -16,31 +16,51 @@
namespace gl namespace gl
{ {
TransformFeedback::TransformFeedback(rx::GLImplFactory *implFactory, GLuint id, const Caps &caps) TransformFeedbackState::TransformFeedbackState(size_t maxIndexedBuffers)
: RefCountObject(id), : mLabel(),
mImplementation(implFactory->createTransformFeedback()),
mLabel(),
mActive(false), mActive(false),
mPrimitiveMode(GL_NONE), mPrimitiveMode(GL_NONE),
mPaused(false), mPaused(false),
mProgram(nullptr), mProgram(nullptr),
mGenericBuffer(), mGenericBuffer(),
mIndexedBuffers(caps.maxTransformFeedbackSeparateAttributes) mIndexedBuffers(maxIndexedBuffers)
{
}
const BindingPointer<Buffer> &TransformFeedbackState::getGenericBuffer() const
{
return mGenericBuffer;
}
const OffsetBindingPointer<Buffer> &TransformFeedbackState::getIndexedBuffer(size_t idx) const
{
return mIndexedBuffers[idx];
}
const std::vector<OffsetBindingPointer<Buffer>> &TransformFeedbackState::getIndexedBuffers() const
{
return mIndexedBuffers;
}
TransformFeedback::TransformFeedback(rx::GLImplFactory *implFactory, GLuint id, const Caps &caps)
: RefCountObject(id),
mState(caps.maxTransformFeedbackSeparateAttributes),
mImplementation(implFactory->createTransformFeedback(mState))
{ {
ASSERT(mImplementation != nullptr); ASSERT(mImplementation != nullptr);
} }
TransformFeedback::~TransformFeedback() TransformFeedback::~TransformFeedback()
{ {
if (mProgram) if (mState.mProgram)
{ {
mProgram->release(); mState.mProgram->release();
mProgram = nullptr; mState.mProgram = nullptr;
} }
mGenericBuffer.set(nullptr); mState.mGenericBuffer.set(nullptr);
for (size_t i = 0; i < mIndexedBuffers.size(); i++) for (size_t i = 0; i < mState.mIndexedBuffers.size(); i++)
{ {
mIndexedBuffers[i].set(nullptr); mState.mIndexedBuffers[i].set(nullptr);
} }
SafeDelete(mImplementation); SafeDelete(mImplementation);
...@@ -48,129 +68,129 @@ TransformFeedback::~TransformFeedback() ...@@ -48,129 +68,129 @@ TransformFeedback::~TransformFeedback()
void TransformFeedback::setLabel(const std::string &label) void TransformFeedback::setLabel(const std::string &label)
{ {
mLabel = label; mState.mLabel = label;
} }
const std::string &TransformFeedback::getLabel() const const std::string &TransformFeedback::getLabel() const
{ {
return mLabel; return mState.mLabel;
} }
void TransformFeedback::begin(GLenum primitiveMode, Program *program) void TransformFeedback::begin(GLenum primitiveMode, Program *program)
{ {
mActive = true; mState.mActive = true;
mPrimitiveMode = primitiveMode; mState.mPrimitiveMode = primitiveMode;
mPaused = false; mState.mPaused = false;
mImplementation->begin(primitiveMode); mImplementation->begin(primitiveMode);
bindProgram(program); bindProgram(program);
} }
void TransformFeedback::end() void TransformFeedback::end()
{ {
mActive = false; mState.mActive = false;
mPrimitiveMode = GL_NONE; mState.mPrimitiveMode = GL_NONE;
mPaused = false; mState.mPaused = false;
mImplementation->end(); mImplementation->end();
if (mProgram) if (mState.mProgram)
{ {
mProgram->release(); mState.mProgram->release();
mProgram = nullptr; mState.mProgram = nullptr;
} }
} }
void TransformFeedback::pause() void TransformFeedback::pause()
{ {
mPaused = true; mState.mPaused = true;
mImplementation->pause(); mImplementation->pause();
} }
void TransformFeedback::resume() void TransformFeedback::resume()
{ {
mPaused = false; mState.mPaused = false;
mImplementation->resume(); mImplementation->resume();
} }
bool TransformFeedback::isActive() const bool TransformFeedback::isActive() const
{ {
return mActive; return mState.mActive;
} }
bool TransformFeedback::isPaused() const bool TransformFeedback::isPaused() const
{ {
return mPaused; return mState.mPaused;
} }
GLenum TransformFeedback::getPrimitiveMode() const GLenum TransformFeedback::getPrimitiveMode() const
{ {
return mPrimitiveMode; return mState.mPrimitiveMode;
} }
void TransformFeedback::bindProgram(Program *program) void TransformFeedback::bindProgram(Program *program)
{ {
if (mProgram != program) if (mState.mProgram != program)
{ {
if (mProgram != nullptr) if (mState.mProgram != nullptr)
{ {
mProgram->release(); mState.mProgram->release();
} }
mProgram = program; mState.mProgram = program;
if (mProgram != nullptr) if (mState.mProgram != nullptr)
{ {
mProgram->addRef(); mState.mProgram->addRef();
} }
} }
} }
bool TransformFeedback::hasBoundProgram(GLuint program) const bool TransformFeedback::hasBoundProgram(GLuint program) const
{ {
return mProgram != nullptr && mProgram->id() == program; return mState.mProgram != nullptr && mState.mProgram->id() == program;
} }
void TransformFeedback::bindGenericBuffer(Buffer *buffer) void TransformFeedback::bindGenericBuffer(Buffer *buffer)
{ {
mGenericBuffer.set(buffer); mState.mGenericBuffer.set(buffer);
mImplementation->bindGenericBuffer(mGenericBuffer); mImplementation->bindGenericBuffer(mState.mGenericBuffer);
} }
void TransformFeedback::detachBuffer(GLuint bufferName) void TransformFeedback::detachBuffer(GLuint bufferName)
{ {
for (size_t index = 0; index < mIndexedBuffers.size(); index++) for (size_t index = 0; index < mState.mIndexedBuffers.size(); index++)
{ {
if (mIndexedBuffers[index].id() == bufferName) if (mState.mIndexedBuffers[index].id() == bufferName)
{ {
mIndexedBuffers[index].set(nullptr); mState.mIndexedBuffers[index].set(nullptr);
mImplementation->bindIndexedBuffer(index, mIndexedBuffers[index]); mImplementation->bindIndexedBuffer(index, mState.mIndexedBuffers[index]);
} }
} }
if (mGenericBuffer.id() == bufferName) if (mState.mGenericBuffer.id() == bufferName)
{ {
mGenericBuffer.set(nullptr); mState.mGenericBuffer.set(nullptr);
mImplementation->bindGenericBuffer(mGenericBuffer); mImplementation->bindGenericBuffer(mState.mGenericBuffer);
} }
} }
const BindingPointer<Buffer> &TransformFeedback::getGenericBuffer() const const BindingPointer<Buffer> &TransformFeedback::getGenericBuffer() const
{ {
return mGenericBuffer; return mState.mGenericBuffer;
} }
void TransformFeedback::bindIndexedBuffer(size_t index, Buffer *buffer, size_t offset, size_t size) void TransformFeedback::bindIndexedBuffer(size_t index, Buffer *buffer, size_t offset, size_t size)
{ {
ASSERT(index < mIndexedBuffers.size()); ASSERT(index < mState.mIndexedBuffers.size());
mIndexedBuffers[index].set(buffer, offset, size); mState.mIndexedBuffers[index].set(buffer, offset, size);
mImplementation->bindIndexedBuffer(index, mIndexedBuffers[index]); mImplementation->bindIndexedBuffer(index, mState.mIndexedBuffers[index]);
} }
const OffsetBindingPointer<Buffer> &TransformFeedback::getIndexedBuffer(size_t index) const const OffsetBindingPointer<Buffer> &TransformFeedback::getIndexedBuffer(size_t index) const
{ {
ASSERT(index < mIndexedBuffers.size()); ASSERT(index < mState.mIndexedBuffers.size());
return mIndexedBuffers[index]; return mState.mIndexedBuffers[index];
} }
size_t TransformFeedback::getIndexedBufferCount() const size_t TransformFeedback::getIndexedBufferCount() const
{ {
return mIndexedBuffers.size(); return mState.mIndexedBuffers.size();
} }
rx::TransformFeedbackImpl *TransformFeedback::getImplementation() rx::TransformFeedbackImpl *TransformFeedback::getImplementation()
......
...@@ -26,6 +26,30 @@ class Buffer; ...@@ -26,6 +26,30 @@ class Buffer;
struct Caps; struct Caps;
class Program; class Program;
class TransformFeedbackState final : public angle::NonCopyable
{
public:
TransformFeedbackState(size_t maxIndexedBuffers);
const BindingPointer<Buffer> &getGenericBuffer() const;
const OffsetBindingPointer<Buffer> &getIndexedBuffer(size_t idx) const;
const std::vector<OffsetBindingPointer<Buffer>> &getIndexedBuffers() const;
private:
friend class TransformFeedback;
std::string mLabel;
bool mActive;
GLenum mPrimitiveMode;
bool mPaused;
Program *mProgram;
BindingPointer<Buffer> mGenericBuffer;
std::vector<OffsetBindingPointer<Buffer>> mIndexedBuffers;
};
class TransformFeedback final : public RefCountObject, public LabeledObject class TransformFeedback final : public RefCountObject, public LabeledObject
{ {
public: public:
...@@ -61,18 +85,8 @@ class TransformFeedback final : public RefCountObject, public LabeledObject ...@@ -61,18 +85,8 @@ class TransformFeedback final : public RefCountObject, public LabeledObject
private: private:
void bindProgram(Program *program); void bindProgram(Program *program);
TransformFeedbackState mState;
rx::TransformFeedbackImpl* mImplementation; rx::TransformFeedbackImpl* mImplementation;
std::string mLabel;
bool mActive;
GLenum mPrimitiveMode;
bool mPaused;
Program *mProgram;
BindingPointer<Buffer> mGenericBuffer;
std::vector<OffsetBindingPointer<Buffer>> mIndexedBuffers;
}; };
} }
......
...@@ -14,12 +14,18 @@ ...@@ -14,12 +14,18 @@
#include "tests/angle_unittests_utils.h" #include "tests/angle_unittests_utils.h"
using ::testing::_; using ::testing::_;
using ::testing::get;
using ::testing::Return; using ::testing::Return;
using ::testing::SetArgumentPointee; using ::testing::SetArgumentPointee;
namespace namespace
{ {
ACTION(CreateMockTransformFeedbackImpl)
{
return new rx::MockTransformFeedbackImpl(arg0);
}
class TransformFeedbackTest : public testing::Test class TransformFeedbackTest : public testing::Test
{ {
protected: protected:
...@@ -27,17 +33,18 @@ class TransformFeedbackTest : public testing::Test ...@@ -27,17 +33,18 @@ class TransformFeedbackTest : public testing::Test
void SetUp() override void SetUp() override
{ {
mImpl = new rx::MockTransformFeedbackImpl; EXPECT_CALL(mMockFactory, createTransformFeedback(_))
EXPECT_CALL(mMockFactory, createTransformFeedback()) .WillOnce(CreateMockTransformFeedbackImpl())
.WillOnce(Return(mImpl))
.RetiresOnSaturation(); .RetiresOnSaturation();
// Set a reasonable number of tf attributes // Set a reasonable number of tf attributes
mCaps.maxTransformFeedbackSeparateAttributes = 8; mCaps.maxTransformFeedbackSeparateAttributes = 8;
EXPECT_CALL(*mImpl, destructor());
mFeedback = new gl::TransformFeedback(&mMockFactory, 1, mCaps); mFeedback = new gl::TransformFeedback(&mMockFactory, 1, mCaps);
mFeedback->addRef(); mFeedback->addRef();
mImpl = rx::GetImplAs<rx::MockTransformFeedbackImpl>(mFeedback);
EXPECT_CALL(*mImpl, destructor());
} }
void TearDown() override void TearDown() override
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "libANGLE/Framebuffer.h" #include "libANGLE/Framebuffer.h"
#include "libANGLE/Program.h" #include "libANGLE/Program.h"
#include "libANGLE/Shader.h" #include "libANGLE/Shader.h"
#include "libANGLE/TransformFeedback.h"
#include "libANGLE/VertexArray.h" #include "libANGLE/VertexArray.h"
namespace gl namespace gl
...@@ -73,7 +74,8 @@ class GLImplFactory : angle::NonCopyable ...@@ -73,7 +74,8 @@ class GLImplFactory : angle::NonCopyable
virtual FenceSyncImpl *createFenceSync() = 0; virtual FenceSyncImpl *createFenceSync() = 0;
// Transform Feedback creation // Transform Feedback creation
virtual TransformFeedbackImpl *createTransformFeedback() = 0; virtual TransformFeedbackImpl *createTransformFeedback(
const gl::TransformFeedbackState &state) = 0;
// Sampler object creation // Sampler object creation
virtual SamplerImpl *createSampler() = 0; virtual SamplerImpl *createSampler() = 0;
......
...@@ -18,6 +18,7 @@ namespace rx ...@@ -18,6 +18,7 @@ namespace rx
class TransformFeedbackImpl : angle::NonCopyable class TransformFeedbackImpl : angle::NonCopyable
{ {
public: public:
TransformFeedbackImpl(const gl::TransformFeedbackState &state) : mState(state) {}
virtual ~TransformFeedbackImpl() { } virtual ~TransformFeedbackImpl() { }
virtual void begin(GLenum primitiveMode) = 0; virtual void begin(GLenum primitiveMode) = 0;
...@@ -27,6 +28,9 @@ class TransformFeedbackImpl : angle::NonCopyable ...@@ -27,6 +28,9 @@ class TransformFeedbackImpl : angle::NonCopyable
virtual void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) = 0; virtual void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) = 0;
virtual void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) = 0; virtual void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) = 0;
protected:
const gl::TransformFeedbackState &mState;
}; };
} }
......
...@@ -19,6 +19,10 @@ namespace rx ...@@ -19,6 +19,10 @@ namespace rx
class MockTransformFeedbackImpl : public TransformFeedbackImpl class MockTransformFeedbackImpl : public TransformFeedbackImpl
{ {
public: public:
MockTransformFeedbackImpl(const gl::TransformFeedbackState &state)
: TransformFeedbackImpl(state)
{
}
~MockTransformFeedbackImpl() { destructor(); } ~MockTransformFeedbackImpl() { destructor(); }
MOCK_METHOD1(begin, void(GLenum primitiveMode)); MOCK_METHOD1(begin, void(GLenum primitiveMode));
......
//
// Copyright 2014 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.
//
// TransformFeedbackD3D.cpp is a no-op implementation for both the D3D9 and D3D11 renderers.
#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h"
namespace rx
{
TransformFeedbackD3D::TransformFeedbackD3D()
{
}
TransformFeedbackD3D::~TransformFeedbackD3D()
{
}
void TransformFeedbackD3D::begin(GLenum primitiveMode)
{
}
void TransformFeedbackD3D::end()
{
}
void TransformFeedbackD3D::pause()
{
}
void TransformFeedbackD3D::resume()
{
}
void TransformFeedbackD3D::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
{
}
void TransformFeedbackD3D::bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding)
{
}
}
...@@ -16,12 +16,12 @@ ...@@ -16,12 +16,12 @@
#include "libANGLE/renderer/d3d/RenderbufferD3D.h" #include "libANGLE/renderer/d3d/RenderbufferD3D.h"
#include "libANGLE/renderer/d3d/SamplerD3D.h" #include "libANGLE/renderer/d3d/SamplerD3D.h"
#include "libANGLE/renderer/d3d/TextureD3D.h" #include "libANGLE/renderer/d3d/TextureD3D.h"
#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h"
#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
#include "libANGLE/renderer/d3d/d3d11/Fence11.h" #include "libANGLE/renderer/d3d/d3d11/Fence11.h"
#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/StateManager11.h" #include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h" #include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
namespace rx namespace rx
...@@ -121,9 +121,9 @@ FenceSyncImpl *Context11::createFenceSync() ...@@ -121,9 +121,9 @@ FenceSyncImpl *Context11::createFenceSync()
return new FenceSync11(mRenderer); return new FenceSync11(mRenderer);
} }
TransformFeedbackImpl *Context11::createTransformFeedback() TransformFeedbackImpl *Context11::createTransformFeedback(const gl::TransformFeedbackState &state)
{ {
return new TransformFeedbackD3D(); return new TransformFeedback11(state);
} }
SamplerImpl *Context11::createSampler() SamplerImpl *Context11::createSampler()
......
...@@ -50,7 +50,8 @@ class Context11 : public ContextImpl ...@@ -50,7 +50,8 @@ class Context11 : public ContextImpl
FenceSyncImpl *createFenceSync() override; FenceSyncImpl *createFenceSync() override;
// Transform Feedback creation // Transform Feedback creation
TransformFeedbackImpl *createTransformFeedback() override; TransformFeedbackImpl *createTransformFeedback(
const gl::TransformFeedbackState &state) override;
// Sampler object creation // Sampler object creation
SamplerImpl *createSampler() override; SamplerImpl *createSampler() override;
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" #include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
#include "libANGLE/renderer/d3d/d3d11/Trim11.h" #include "libANGLE/renderer/d3d/d3d11/Trim11.h"
#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h" #include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h" #include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
...@@ -54,7 +55,6 @@ ...@@ -54,7 +55,6 @@
#include "libANGLE/renderer/d3d/ShaderD3D.h" #include "libANGLE/renderer/d3d/ShaderD3D.h"
#include "libANGLE/renderer/d3d/SurfaceD3D.h" #include "libANGLE/renderer/d3d/SurfaceD3D.h"
#include "libANGLE/renderer/d3d/TextureD3D.h" #include "libANGLE/renderer/d3d/TextureD3D.h"
#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h"
#include "libANGLE/renderer/d3d/VertexDataManager.h" #include "libANGLE/renderer/d3d/VertexDataManager.h"
#include "libANGLE/State.h" #include "libANGLE/State.h"
#include "libANGLE/Surface.h" #include "libANGLE/Surface.h"
...@@ -444,7 +444,7 @@ Renderer11::Renderer11(egl::Display *display) ...@@ -444,7 +444,7 @@ Renderer11::Renderer11(egl::Display *display)
mAppliedGeometryShader = NULL; mAppliedGeometryShader = NULL;
mAppliedPixelShader = NULL; mAppliedPixelShader = NULL;
mAppliedNumXFBBindings = static_cast<size_t>(-1); mAppliedTFObject = angle::DirtyPointer;
ZeroMemory(&mAdapterDescription, sizeof(mAdapterDescription)); ZeroMemory(&mAdapterDescription, sizeof(mAdapterDescription));
...@@ -1668,76 +1668,40 @@ gl::Error Renderer11::applyIndexBuffer(const gl::ContextState &data, ...@@ -1668,76 +1668,40 @@ gl::Error Renderer11::applyIndexBuffer(const gl::ContextState &data,
return gl::NoError(); return gl::NoError();
} }
gl::Error Renderer11::applyTransformFeedbackBuffers(const gl::State &state) gl::Error Renderer11::applyTransformFeedbackBuffers(const gl::ContextState &data)
{ {
size_t numXFBBindings = 0; const auto &state = data.getState();
bool requiresUpdate = false;
if (state.isTransformFeedbackActiveUnpaused()) // If transform feedback is not active, unbind all buffers
if (!state.isTransformFeedbackActiveUnpaused())
{ {
const gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback(); if (mAppliedTFObject != 0)
numXFBBindings = transformFeedback->getIndexedBufferCount();
ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
for (size_t i = 0; i < numXFBBindings; i++)
{ {
const OffsetBindingPointer<gl::Buffer> &binding = transformFeedback->getIndexedBuffer(i); mDeviceContext->SOSetTargets(0, nullptr, nullptr);
mAppliedTFObject = 0;
ID3D11Buffer *d3dBuffer = nullptr;
if (binding.get() != nullptr)
{
Buffer11 *storage = GetImplAs<Buffer11>(binding.get());
auto bufferOrError = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
if (bufferOrError.isError())
{
return bufferOrError.getError();
}
d3dBuffer = bufferOrError.getResult();
}
// TODO: mAppliedTFBuffers and friends should also be kept in a vector.
if (d3dBuffer != mAppliedTFBuffers[i] || binding.getOffset() != mAppliedTFOffsets[i])
{
requiresUpdate = true;
}
} }
return gl::NoError();
} }
if (requiresUpdate || numXFBBindings != mAppliedNumXFBBindings) gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback();
TransformFeedback11 *transformFeedback11 = GetImplAs<TransformFeedback11>(transformFeedback);
uintptr_t transformFeedbackId = reinterpret_cast<uintptr_t>(transformFeedback11);
if (mAppliedTFObject == transformFeedbackId && !transformFeedback11->isDirty())
{ {
const gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback(); return gl::NoError();
for (size_t i = 0; i < numXFBBindings; ++i) }
{
const OffsetBindingPointer<gl::Buffer> &binding = transformFeedback->getIndexedBuffer(i);
if (binding.get() != nullptr)
{
Buffer11 *storage = GetImplAs<Buffer11>(binding.get());
auto bufferOrError = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
if (bufferOrError.isError())
{
return bufferOrError.getError();
}
ID3D11Buffer *d3dBuffer = bufferOrError.getResult();
mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer || mAppliedTFOffsets[i] != binding.getOffset()) ? const std::vector<ID3D11Buffer *> *soBuffers = nullptr;
static_cast<UINT>(binding.getOffset()) : -1; ANGLE_TRY_RESULT(transformFeedback11->getSOBuffers(), soBuffers);
mAppliedTFBuffers[i] = d3dBuffer; const std::vector<UINT> &soOffsets = transformFeedback11->getSOBufferOffsets();
}
else
{
mAppliedTFBuffers[i] = nullptr;
mCurrentD3DOffsets[i] = 0;
}
mAppliedTFOffsets[i] = binding.getOffset();
}
mAppliedNumXFBBindings = numXFBBindings; mDeviceContext->SOSetTargets(transformFeedback11->getNumSOBuffers(), soBuffers->data(),
soOffsets.data());
mDeviceContext->SOSetTargets(static_cast<unsigned int>(numXFBBindings), mAppliedTFBuffers, mAppliedTFObject = transformFeedbackId;
mCurrentD3DOffsets); transformFeedback11->onApply();
}
return gl::Error(GL_NO_ERROR); return gl::NoError();
} }
gl::Error Renderer11::drawArraysImpl(const gl::ContextState &data, gl::Error Renderer11::drawArraysImpl(const gl::ContextState &data,
...@@ -2549,13 +2513,7 @@ void Renderer11::markAllStateDirty() ...@@ -2549,13 +2513,7 @@ void Renderer11::markAllStateDirty()
mAppliedGeometryShader = angle::DirtyPointer; mAppliedGeometryShader = angle::DirtyPointer;
mAppliedPixelShader = angle::DirtyPointer; mAppliedPixelShader = angle::DirtyPointer;
mAppliedNumXFBBindings = static_cast<size_t>(-1); mAppliedTFObject = angle::DirtyPointer;
for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
{
mAppliedTFBuffers[i] = NULL;
mAppliedTFOffsets[i] = 0;
}
memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants11)); memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants11));
memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants11)); memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants11));
...@@ -4235,7 +4193,7 @@ gl::Error Renderer11::genericDrawElements(Context11 *context, ...@@ -4235,7 +4193,7 @@ gl::Error Renderer11::genericDrawElements(Context11 *context,
ANGLE_TRY(applyIndexBuffer(data, indices, count, mode, type, &indexInfo)); ANGLE_TRY(applyIndexBuffer(data, indices, count, mode, type, &indexInfo));
applyTransformFeedbackBuffers(glState); applyTransformFeedbackBuffers(data);
// Transform feedback is not allowed for DrawElements, this error should have been caught at the // Transform feedback is not allowed for DrawElements, this error should have been caught at the
// API validation layer. // API validation layer.
ASSERT(!glState.isTransformFeedbackActiveUnpaused()); ASSERT(!glState.isTransformFeedbackActiveUnpaused());
...@@ -4277,7 +4235,7 @@ gl::Error Renderer11::genericDrawArrays(Context11 *context, ...@@ -4277,7 +4235,7 @@ gl::Error Renderer11::genericDrawArrays(Context11 *context,
} }
ANGLE_TRY(updateState(data, mode)); ANGLE_TRY(updateState(data, mode));
ANGLE_TRY(applyTransformFeedbackBuffers(glState)); ANGLE_TRY(applyTransformFeedbackBuffers(data));
ANGLE_TRY(applyVertexBuffer(glState, mode, first, count, instances, nullptr)); ANGLE_TRY(applyVertexBuffer(glState, mode, first, count, instances, nullptr));
ANGLE_TRY(applyTextures(context, data)); ANGLE_TRY(applyTextures(context, data));
ANGLE_TRY(applyShaders(data, mode)); ANGLE_TRY(applyShaders(data, mode));
......
...@@ -152,7 +152,7 @@ class Renderer11 : public RendererD3D ...@@ -152,7 +152,7 @@ class Renderer11 : public RendererD3D
GLenum mode, GLenum mode,
GLenum type, GLenum type,
TranslatedIndexData *indexInfo); TranslatedIndexData *indexInfo);
gl::Error applyTransformFeedbackBuffers(const gl::State &state); gl::Error applyTransformFeedbackBuffers(const gl::ContextState &data);
// lost device // lost device
bool testDeviceLost() override; bool testDeviceLost() override;
...@@ -470,15 +470,7 @@ class Renderer11 : public RendererD3D ...@@ -470,15 +470,7 @@ class Renderer11 : public RendererD3D
bool mAppliedIBChanged; bool mAppliedIBChanged;
// Currently applied transform feedback buffers // Currently applied transform feedback buffers
size_t mAppliedNumXFBBindings; uintptr_t mAppliedTFObject;
ID3D11Buffer *mAppliedTFBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current D3D buffers
// in use for streamout
GLintptr mAppliedTFOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current GL-specified
// buffer offsets to transform feedback
// buffers
UINT mCurrentD3DOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the D3D buffer offsets,
// which may differ from GLs, due
// to different append behavior
// Currently applied shaders // Currently applied shaders
uintptr_t mAppliedVertexShader; uintptr_t mAppliedVertexShader;
......
//
// Copyright 2014 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.
//
// TransformFeedbackD3D.cpp is a no-op implementation for both the D3D9 and D3D11 renderers.
#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
#include "libANGLE/Buffer.h"
#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
namespace rx
{
TransformFeedback11::TransformFeedback11(const gl::TransformFeedbackState &state)
: TransformFeedbackImpl(state),
mIsDirty(true),
mBuffers(state.getIndexedBuffers().size(), nullptr),
mBufferOffsets(state.getIndexedBuffers().size(), 0)
{
}
TransformFeedback11::~TransformFeedback11()
{
}
void TransformFeedback11::begin(GLenum primitiveMode)
{
}
void TransformFeedback11::end()
{
}
void TransformFeedback11::pause()
{
}
void TransformFeedback11::resume()
{
}
void TransformFeedback11::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
{
}
void TransformFeedback11::bindIndexedBuffer(size_t index,
const OffsetBindingPointer<gl::Buffer> &binding)
{
mIsDirty = true;
mBufferOffsets[index] = static_cast<UINT>(binding.getOffset());
}
void TransformFeedback11::onApply()
{
mIsDirty = false;
// Change all buffer offsets to -1 so that if any of them need to be re-applied, the are set to
// append
std::fill(mBufferOffsets.begin(), mBufferOffsets.end(), -1);
}
bool TransformFeedback11::isDirty() const
{
return mIsDirty;
}
UINT TransformFeedback11::getNumSOBuffers() const
{
return static_cast<UINT>(mBuffers.size());
}
gl::ErrorOrResult<const std::vector<ID3D11Buffer *> *> TransformFeedback11::getSOBuffers()
{
for (size_t bindingIdx = 0; bindingIdx < mBuffers.size(); bindingIdx++)
{
const auto &binding = mState.getIndexedBuffer(bindingIdx);
if (binding.get() != nullptr)
{
Buffer11 *storage = GetImplAs<Buffer11>(binding.get());
ANGLE_TRY_RESULT(storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK),
mBuffers[bindingIdx]);
}
}
return &mBuffers;
}
const std::vector<UINT> &TransformFeedback11::getSOBufferOffsets() const
{
return mBufferOffsets;
}
} // namespace rx
...@@ -4,22 +4,25 @@ ...@@ -4,22 +4,25 @@
// found in the LICENSE file. // found in the LICENSE file.
// //
// TransformFeedbackD3D.h: Implements the abstract rx::TransformFeedbackImpl class. // TransformFeedback11.h: Implements the abstract rx::TransformFeedbackImpl class.
#ifndef LIBANGLE_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ #ifndef LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_
#define LIBANGLE_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ #define LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_
#include "common/platform.h"
#include "libANGLE/renderer/TransformFeedbackImpl.h"
#include "libANGLE/angletypes.h" #include "libANGLE/angletypes.h"
#include "libANGLE/Error.h"
#include "libANGLE/renderer/TransformFeedbackImpl.h"
namespace rx namespace rx
{ {
class TransformFeedbackD3D : public TransformFeedbackImpl class TransformFeedback11 : public TransformFeedbackImpl
{ {
public: public:
TransformFeedbackD3D(); TransformFeedback11(const gl::TransformFeedbackState &state);
virtual ~TransformFeedbackD3D(); ~TransformFeedback11() override;
void begin(GLenum primitiveMode) override; void begin(GLenum primitiveMode) override;
void end() override; void end() override;
...@@ -28,8 +31,20 @@ class TransformFeedbackD3D : public TransformFeedbackImpl ...@@ -28,8 +31,20 @@ class TransformFeedbackD3D : public TransformFeedbackImpl
void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override; void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override;
void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override; void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override;
};
} void onApply();
bool isDirty() const;
UINT getNumSOBuffers() const;
gl::ErrorOrResult<const std::vector<ID3D11Buffer *> *> getSOBuffers();
const std::vector<UINT> &getSOBufferOffsets() const;
private:
bool mIsDirty;
std::vector<ID3D11Buffer *> mBuffers;
std::vector<UINT> mBufferOffsets;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ #endif // LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include "libANGLE/renderer/d3d/RenderbufferD3D.h" #include "libANGLE/renderer/d3d/RenderbufferD3D.h"
#include "libANGLE/renderer/d3d/SamplerD3D.h" #include "libANGLE/renderer/d3d/SamplerD3D.h"
#include "libANGLE/renderer/d3d/TextureD3D.h" #include "libANGLE/renderer/d3d/TextureD3D.h"
#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h"
#include "libANGLE/renderer/d3d/d3d9/Buffer9.h" #include "libANGLE/renderer/d3d/d3d9/Buffer9.h"
#include "libANGLE/renderer/d3d/d3d9/Fence9.h" #include "libANGLE/renderer/d3d/d3d9/Fence9.h"
#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h" #include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
...@@ -110,9 +109,10 @@ FenceSyncImpl *Context9::createFenceSync() ...@@ -110,9 +109,10 @@ FenceSyncImpl *Context9::createFenceSync()
return nullptr; return nullptr;
} }
TransformFeedbackImpl *Context9::createTransformFeedback() TransformFeedbackImpl *Context9::createTransformFeedback(const gl::TransformFeedbackState &state)
{ {
return new TransformFeedbackD3D(); UNREACHABLE();
return nullptr;
} }
SamplerImpl *Context9::createSampler() SamplerImpl *Context9::createSampler()
......
...@@ -50,7 +50,8 @@ class Context9 : public ContextImpl ...@@ -50,7 +50,8 @@ class Context9 : public ContextImpl
FenceSyncImpl *createFenceSync() override; FenceSyncImpl *createFenceSync() override;
// Transform Feedback creation // Transform Feedback creation
TransformFeedbackImpl *createTransformFeedback() override; TransformFeedbackImpl *createTransformFeedback(
const gl::TransformFeedbackState &state) override;
// Sampler object creation // Sampler object creation
SamplerImpl *createSampler() override; SamplerImpl *createSampler() override;
......
...@@ -47,7 +47,6 @@ ...@@ -47,7 +47,6 @@
#include "libANGLE/renderer/d3d/ShaderD3D.h" #include "libANGLE/renderer/d3d/ShaderD3D.h"
#include "libANGLE/renderer/d3d/SurfaceD3D.h" #include "libANGLE/renderer/d3d/SurfaceD3D.h"
#include "libANGLE/renderer/d3d/TextureD3D.h" #include "libANGLE/renderer/d3d/TextureD3D.h"
#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h"
#include "libANGLE/State.h" #include "libANGLE/State.h"
#include "libANGLE/Surface.h" #include "libANGLE/Surface.h"
#include "libANGLE/Texture.h" #include "libANGLE/Texture.h"
......
...@@ -102,10 +102,9 @@ FenceSyncImpl *ContextGL::createFenceSync() ...@@ -102,10 +102,9 @@ FenceSyncImpl *ContextGL::createFenceSync()
return new FenceSyncGL(getFunctions()); return new FenceSyncGL(getFunctions());
} }
TransformFeedbackImpl *ContextGL::createTransformFeedback() TransformFeedbackImpl *ContextGL::createTransformFeedback(const gl::TransformFeedbackState &state)
{ {
return new TransformFeedbackGL(getFunctions(), getStateManager(), return new TransformFeedbackGL(state, getFunctions(), getStateManager());
getNativeCaps().maxTransformFeedbackSeparateComponents);
} }
SamplerImpl *ContextGL::createSampler() SamplerImpl *ContextGL::createSampler()
......
...@@ -58,7 +58,8 @@ class ContextGL : public ContextImpl ...@@ -58,7 +58,8 @@ class ContextGL : public ContextImpl
FenceSyncImpl *createFenceSync() override; FenceSyncImpl *createFenceSync() override;
// Transform Feedback creation // Transform Feedback creation
TransformFeedbackImpl *createTransformFeedback() override; TransformFeedbackImpl *createTransformFeedback(
const gl::TransformFeedbackState &state) override;
// Sampler object creation // Sampler object creation
SamplerImpl *createSampler() override; SamplerImpl *createSampler() override;
......
...@@ -17,16 +17,15 @@ ...@@ -17,16 +17,15 @@
namespace rx namespace rx
{ {
TransformFeedbackGL::TransformFeedbackGL(const FunctionsGL *functions, TransformFeedbackGL::TransformFeedbackGL(const gl::TransformFeedbackState &state,
StateManagerGL *stateManager, const FunctionsGL *functions,
size_t maxTransformFeedbackBufferBindings) StateManagerGL *stateManager)
: TransformFeedbackImpl(), : TransformFeedbackImpl(state),
mFunctions(functions), mFunctions(functions),
mStateManager(stateManager), mStateManager(stateManager),
mTransformFeedbackID(0), mTransformFeedbackID(0),
mIsActive(false), mIsActive(false),
mIsPaused(false), mIsPaused(false)
mCurrentIndexedBuffers(maxTransformFeedbackBufferBindings)
{ {
mFunctions->genTransformFeedbacks(1, &mTransformFeedbackID); mFunctions->genTransformFeedbacks(1, &mTransformFeedbackID);
} }
...@@ -35,11 +34,6 @@ TransformFeedbackGL::~TransformFeedbackGL() ...@@ -35,11 +34,6 @@ TransformFeedbackGL::~TransformFeedbackGL()
{ {
mStateManager->deleteTransformFeedback(mTransformFeedbackID); mStateManager->deleteTransformFeedback(mTransformFeedbackID);
mTransformFeedbackID = 0; mTransformFeedbackID = 0;
for (auto &bufferBinding : mCurrentIndexedBuffers)
{
bufferBinding.set(nullptr);
}
} }
void TransformFeedbackGL::begin(GLenum primitiveMode) void TransformFeedbackGL::begin(GLenum primitiveMode)
...@@ -70,30 +64,25 @@ void TransformFeedbackGL::bindIndexedBuffer(size_t index, const OffsetBindingPoi ...@@ -70,30 +64,25 @@ void TransformFeedbackGL::bindIndexedBuffer(size_t index, const OffsetBindingPoi
{ {
// Directly bind buffer (not through the StateManager methods) because the buffer bindings are // Directly bind buffer (not through the StateManager methods) because the buffer bindings are
// tracked per transform feedback object // tracked per transform feedback object
if (binding != mCurrentIndexedBuffers[index]) mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
if (binding.get() != nullptr)
{ {
mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID); const BufferGL *bufferGL = GetImplAs<BufferGL>(binding.get());
if (binding.get() != nullptr) if (binding.getSize() != 0)
{ {
const BufferGL *bufferGL = GetImplAs<BufferGL>(binding.get()); mFunctions->bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index),
if (binding.getSize() != 0) bufferGL->getBufferID(), binding.getOffset(),
{ binding.getSize());
mFunctions->bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
static_cast<GLuint>(index), bufferGL->getBufferID(),
binding.getOffset(), binding.getSize());
}
else
{
mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index),
bufferGL->getBufferID());
}
} }
else else
{ {
mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index), 0); mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index),
bufferGL->getBufferID());
} }
}
mCurrentIndexedBuffers[index] = binding; else
{
mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index), 0);
} }
} }
......
...@@ -20,9 +20,9 @@ class StateManagerGL; ...@@ -20,9 +20,9 @@ class StateManagerGL;
class TransformFeedbackGL : public TransformFeedbackImpl class TransformFeedbackGL : public TransformFeedbackImpl
{ {
public: public:
TransformFeedbackGL(const FunctionsGL *functions, TransformFeedbackGL(const gl::TransformFeedbackState &state,
StateManagerGL *stateManager, const FunctionsGL *functions,
size_t maxTransformFeedbackBufferBindings); StateManagerGL *stateManager);
~TransformFeedbackGL() override; ~TransformFeedbackGL() override;
void begin(GLenum primitiveMode) override; void begin(GLenum primitiveMode) override;
...@@ -46,8 +46,6 @@ class TransformFeedbackGL : public TransformFeedbackImpl ...@@ -46,8 +46,6 @@ class TransformFeedbackGL : public TransformFeedbackImpl
mutable bool mIsActive; mutable bool mIsActive;
mutable bool mIsPaused; mutable bool mIsPaused;
std::vector<OffsetBindingPointer<gl::Buffer>> mCurrentIndexedBuffers;
}; };
} }
......
...@@ -253,9 +253,9 @@ FenceSyncImpl *ContextVk::createFenceSync() ...@@ -253,9 +253,9 @@ FenceSyncImpl *ContextVk::createFenceSync()
return new FenceSyncVk(); return new FenceSyncVk();
} }
TransformFeedbackImpl *ContextVk::createTransformFeedback() TransformFeedbackImpl *ContextVk::createTransformFeedback(const gl::TransformFeedbackState &state)
{ {
return new TransformFeedbackVk(); return new TransformFeedbackVk(state);
} }
SamplerImpl *ContextVk::createSampler() SamplerImpl *ContextVk::createSampler()
......
...@@ -111,7 +111,8 @@ class ContextVk : public ContextImpl ...@@ -111,7 +111,8 @@ class ContextVk : public ContextImpl
FenceSyncImpl *createFenceSync() override; FenceSyncImpl *createFenceSync() override;
// Transform Feedback creation // Transform Feedback creation
TransformFeedbackImpl *createTransformFeedback() override; TransformFeedbackImpl *createTransformFeedback(
const gl::TransformFeedbackState &state) override;
// Sampler object creation // Sampler object creation
SamplerImpl *createSampler() override; SamplerImpl *createSampler() override;
......
...@@ -14,7 +14,8 @@ ...@@ -14,7 +14,8 @@
namespace rx namespace rx
{ {
TransformFeedbackVk::TransformFeedbackVk() : TransformFeedbackImpl() TransformFeedbackVk::TransformFeedbackVk(const gl::TransformFeedbackState &state)
: TransformFeedbackImpl(state)
{ {
} }
......
...@@ -18,7 +18,7 @@ namespace rx ...@@ -18,7 +18,7 @@ namespace rx
class TransformFeedbackVk : public TransformFeedbackImpl class TransformFeedbackVk : public TransformFeedbackImpl
{ {
public: public:
TransformFeedbackVk(); TransformFeedbackVk(const gl::TransformFeedbackState &state);
~TransformFeedbackVk() override; ~TransformFeedbackVk() override;
void begin(GLenum primitiveMode) override; void begin(GLenum primitiveMode) override;
......
...@@ -247,8 +247,6 @@ ...@@ -247,8 +247,6 @@
'libANGLE/renderer/d3d/TextureD3D.cpp', 'libANGLE/renderer/d3d/TextureD3D.cpp',
'libANGLE/renderer/d3d/TextureD3D.h', 'libANGLE/renderer/d3d/TextureD3D.h',
'libANGLE/renderer/d3d/TextureStorage.h', 'libANGLE/renderer/d3d/TextureStorage.h',
'libANGLE/renderer/d3d/TransformFeedbackD3D.cpp',
'libANGLE/renderer/d3d/TransformFeedbackD3D.h',
'libANGLE/renderer/d3d/VaryingPacking.cpp', 'libANGLE/renderer/d3d/VaryingPacking.cpp',
'libANGLE/renderer/d3d/VaryingPacking.h', 'libANGLE/renderer/d3d/VaryingPacking.h',
'libANGLE/renderer/d3d/VertexBuffer.cpp', 'libANGLE/renderer/d3d/VertexBuffer.cpp',
...@@ -413,6 +411,8 @@ ...@@ -413,6 +411,8 @@
'libANGLE/renderer/d3d/d3d11/SwapChain11.h', 'libANGLE/renderer/d3d/d3d11/SwapChain11.h',
'libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp', 'libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp',
'libANGLE/renderer/d3d/d3d11/TextureStorage11.h', 'libANGLE/renderer/d3d/d3d11/TextureStorage11.h',
'libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp',
'libANGLE/renderer/d3d/d3d11/TransformFeedback11.h',
'libANGLE/renderer/d3d/d3d11/Trim11.cpp', 'libANGLE/renderer/d3d/d3d11/Trim11.cpp',
'libANGLE/renderer/d3d/d3d11/Trim11.h', 'libANGLE/renderer/d3d/d3d11/Trim11.h',
'libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp', 'libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp',
......
...@@ -55,7 +55,10 @@ class NullFactory : public GLImplFactory ...@@ -55,7 +55,10 @@ class NullFactory : public GLImplFactory
FenceSyncImpl *createFenceSync() override { return nullptr; } FenceSyncImpl *createFenceSync() override { return nullptr; }
// Transform Feedback creation // Transform Feedback creation
TransformFeedbackImpl *createTransformFeedback() override { return nullptr; } TransformFeedbackImpl *createTransformFeedback(const gl::TransformFeedbackState &state) override
{
return nullptr;
}
// Sampler object creation // Sampler object creation
SamplerImpl *createSampler() override { return nullptr; } SamplerImpl *createSampler() override { return nullptr; }
...@@ -82,7 +85,8 @@ class MockGLFactory : public GLImplFactory ...@@ -82,7 +85,8 @@ class MockGLFactory : public GLImplFactory
MOCK_METHOD1(createQuery, QueryImpl *(GLenum type)); MOCK_METHOD1(createQuery, QueryImpl *(GLenum type));
MOCK_METHOD0(createFenceNV, FenceNVImpl *()); MOCK_METHOD0(createFenceNV, FenceNVImpl *());
MOCK_METHOD0(createFenceSync, FenceSyncImpl *()); MOCK_METHOD0(createFenceSync, FenceSyncImpl *());
MOCK_METHOD0(createTransformFeedback, TransformFeedbackImpl *()); MOCK_METHOD1(createTransformFeedback,
TransformFeedbackImpl *(const gl::TransformFeedbackState &));
MOCK_METHOD0(createSampler, SamplerImpl *()); MOCK_METHOD0(createSampler, SamplerImpl *());
MOCK_METHOD1(createPaths, std::vector<PathImpl *>(GLsizei)); MOCK_METHOD1(createPaths, std::vector<PathImpl *>(GLsizei));
}; };
......
...@@ -17,7 +17,6 @@ class TransformFeedbackTest : public ANGLETest ...@@ -17,7 +17,6 @@ class TransformFeedbackTest : public ANGLETest
protected: protected:
TransformFeedbackTest() TransformFeedbackTest()
: mProgram(0), : mProgram(0),
mTransformFeedbackBufferSize(0),
mTransformFeedbackBuffer(0), mTransformFeedbackBuffer(0),
mTransformFeedback(0) mTransformFeedback(0)
{ {
...@@ -34,7 +33,6 @@ class TransformFeedbackTest : public ANGLETest ...@@ -34,7 +33,6 @@ class TransformFeedbackTest : public ANGLETest
ANGLETest::SetUp(); ANGLETest::SetUp();
glGenBuffers(1, &mTransformFeedbackBuffer); glGenBuffers(1, &mTransformFeedbackBuffer);
mTransformFeedbackBufferSize = 1 << 24; // ~16MB
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBuffer); glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBuffer);
glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBufferSize, NULL, glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBufferSize, NULL,
GL_STATIC_DRAW); GL_STATIC_DRAW);
...@@ -99,7 +97,7 @@ class TransformFeedbackTest : public ANGLETest ...@@ -99,7 +97,7 @@ class TransformFeedbackTest : public ANGLETest
GLuint mProgram; GLuint mProgram;
size_t mTransformFeedbackBufferSize; static const size_t mTransformFeedbackBufferSize = 1 << 24;
GLuint mTransformFeedbackBuffer; GLuint mTransformFeedbackBuffer;
GLuint mTransformFeedback; GLuint mTransformFeedback;
}; };
...@@ -143,6 +141,80 @@ TEST_P(TransformFeedbackTest, ZeroSizedViewport) ...@@ -143,6 +141,80 @@ TEST_P(TransformFeedbackTest, ZeroSizedViewport)
EXPECT_EQ(2u, primitivesWritten); EXPECT_EQ(2u, primitivesWritten);
} }
// Test that rebinding a buffer with the same offset resets the offset (no longer appending from the
// old position)
TEST_P(TransformFeedbackTest, BufferRebinding)
{
glDisable(GL_DEPTH_TEST);
// Set the program's transform feedback varyings (just gl_Position)
std::vector<std::string> tfVaryings;
tfVaryings.push_back("gl_Position");
compileDefaultProgram(tfVaryings, GL_INTERLEAVED_ATTRIBS);
glUseProgram(mProgram);
// Make sure the buffer has zero'd data
std::vector<float> data(mTransformFeedbackBufferSize / sizeof(float), 0.0f);
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBuffer);
glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBufferSize, data.data(),
GL_STATIC_DRAW);
// Bind the buffer for transform feedback output and start transform feedback
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer);
glBeginTransformFeedback(GL_TRIANGLES);
// Create a query to check how many primitives were written
GLuint primitivesWrittenQuery = 0;
glGenQueries(1, &primitivesWrittenQuery);
glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, primitivesWrittenQuery);
float originalZ = 0.5f;
drawQuad(mProgram, "position", originalZ);
// stop, reset the buffer and resume
glEndTransformFeedback();
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer);
glBeginTransformFeedback(GL_TRIANGLES);
float updatedZ = 0.75f;
drawQuad(mProgram, "position", updatedZ);
// End the query and transform feedback
glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
glEndTransformFeedback();
glUseProgram(0);
// Check how many primitives were written and verify that some were written even if
// no pixels were rendered
GLuint primitivesWritten = 0;
glGetQueryObjectuiv(primitivesWrittenQuery, GL_QUERY_RESULT_EXT, &primitivesWritten);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(4u, primitivesWritten);
// Check the buffer data
const float *bufferData = static_cast<float *>(glMapBufferRange(
GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBufferSize, GL_MAP_READ_BIT));
for (size_t vertexIdx = 0; vertexIdx < 6; vertexIdx++)
{
// Check the third (Z) component of each vertex written and make sure it has the updated
// value
EXPECT_NEAR(updatedZ, bufferData[vertexIdx * 4 + 2], 0.0001);
}
for (size_t dataIdx = 24; dataIdx < mTransformFeedbackBufferSize / sizeof(float); dataIdx++)
{
EXPECT_EQ(data[dataIdx], bufferData[dataIdx]) << "Buffer overrun detected.";
}
glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
EXPECT_GL_NO_ERROR();
}
// Test that XFB can write back vertices to a buffer and that we can draw from this buffer afterward. // Test that XFB can write back vertices to a buffer and that we can draw from this buffer afterward.
TEST_P(TransformFeedbackTest, RecordAndDraw) TEST_P(TransformFeedbackTest, RecordAndDraw)
{ {
...@@ -441,14 +513,6 @@ TEST_P(TransformFeedbackTest, MultiplePaused) ...@@ -441,14 +513,6 @@ TEST_P(TransformFeedbackTest, MultiplePaused)
// contexts returns the correct results. Helps expose bugs in ANGLE's virtual contexts. // contexts returns the correct results. Helps expose bugs in ANGLE's virtual contexts.
TEST_P(TransformFeedbackTest, MultiContext) TEST_P(TransformFeedbackTest, MultiContext)
{ {
if (GetParam() == ES3_D3D11())
{
std::cout << "Test skipped because the D3D backends cannot support simultaneous transform "
"feedback or queries on multiple contexts yet."
<< std::endl;
return;
}
#if defined(ANGLE_PLATFORM_APPLE) #if defined(ANGLE_PLATFORM_APPLE)
if ((IsNVIDIA() || IsAMD()) && GetParam() == ES3_OPENGL()) if ((IsNVIDIA() || IsAMD()) && GetParam() == ES3_OPENGL())
{ {
...@@ -773,7 +837,6 @@ class TransformFeedbackLifetimeTest : public TransformFeedbackTest ...@@ -773,7 +837,6 @@ class TransformFeedbackLifetimeTest : public TransformFeedbackTest
compileDefaultProgram(tfVaryings, GL_SEPARATE_ATTRIBS); compileDefaultProgram(tfVaryings, GL_SEPARATE_ATTRIBS);
glGenBuffers(1, &mTransformFeedbackBuffer); glGenBuffers(1, &mTransformFeedbackBuffer);
mTransformFeedbackBufferSize = 1 << 24; // ~16MB
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBuffer); glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBuffer);
glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBufferSize, NULL, glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBufferSize, NULL,
GL_DYNAMIC_DRAW); GL_DYNAMIC_DRAW);
......
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