Commit a9ca8e20 by Geoff Lang

Revert "Implement TransformFeedbackGL."

Failing on AMD Linux bots. This reverts commit a9c52881. Change-Id: I2a2db8c3d96c4b927d7d784486c6df772ae63084 Reviewed-on: https://chromium-review.googlesource.com/308130Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent a9c52881
...@@ -38,7 +38,7 @@ namespace ...@@ -38,7 +38,7 @@ namespace
void MarkTransformFeedbackBufferUsage(gl::TransformFeedback *transformFeedback) void MarkTransformFeedbackBufferUsage(gl::TransformFeedback *transformFeedback)
{ {
if (transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused()) if (transformFeedback->isActive() && !transformFeedback->isPaused())
{ {
for (size_t tfBufferIndex = 0; tfBufferIndex < transformFeedback->getIndexedBufferCount(); for (size_t tfBufferIndex = 0; tfBufferIndex < transformFeedback->getIndexedBufferCount();
tfBufferIndex++) tfBufferIndex++)
...@@ -138,16 +138,12 @@ Context::Context(const egl::Config *config, ...@@ -138,16 +138,12 @@ Context::Context(const egl::Config *config,
bindPixelPackBuffer(0); bindPixelPackBuffer(0);
bindPixelUnpackBuffer(0); bindPixelUnpackBuffer(0);
if (mClientVersion >= 3) // [OpenGL ES 3.0.2] section 2.14.1 pg 85:
{ // In the initial state, a default transform feedback object is bound and treated as
// [OpenGL ES 3.0.2] section 2.14.1 pg 85: // a transform feedback object with a name of zero. That object is bound any time
// In the initial state, a default transform feedback object is bound and treated as // BindTransformFeedback is called with id of zero
// a transform feedback object with a name of zero. That object is bound any time mTransformFeedbackZero.set(new TransformFeedback(mRenderer->createTransformFeedback(), 0, mCaps));
// BindTransformFeedback is called with id of zero bindTransformFeedback(0);
mTransformFeedbackZero.set(
new TransformFeedback(mRenderer->createTransformFeedback(), 0, mCaps));
bindTransformFeedback(0);
}
mHasBeenCurrent = false; mHasBeenCurrent = false;
mContextLost = false; mContextLost = false;
...@@ -192,7 +188,7 @@ Context::~Context() ...@@ -192,7 +188,7 @@ Context::~Context()
mTransformFeedbackZero.set(NULL); mTransformFeedbackZero.set(NULL);
for (auto transformFeedback : mTransformFeedbackMap) for (auto transformFeedback : mTransformFeedbackMap)
{ {
transformFeedback.second->release(); SafeDelete(transformFeedback.second);
} }
for (auto &zeroTexture : mZeroTextures) for (auto &zeroTexture : mZeroTextures)
......
...@@ -235,7 +235,7 @@ LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, ...@@ -235,7 +235,7 @@ LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size,
Program::Data::Data() Program::Data::Data()
: mAttachedFragmentShader(nullptr), : mAttachedFragmentShader(nullptr),
mAttachedVertexShader(nullptr), mAttachedVertexShader(nullptr),
mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS) mTransformFeedbackBufferMode(GL_NONE)
{ {
} }
...@@ -2014,12 +2014,6 @@ bool Program::linkValidateTransformFeedback(InfoLog &infoLog, ...@@ -2014,12 +2014,6 @@ bool Program::linkValidateTransformFeedback(InfoLog &infoLog,
} }
uniqueNames.insert(tfVaryingName); uniqueNames.insert(tfVaryingName);
if (varying->isArray())
{
infoLog << "Capture of arrays is undefined and not supported.";
return false;
}
// TODO(jmadill): Investigate implementation limits on D3D11 // TODO(jmadill): Investigate implementation limits on D3D11
size_t componentCount = gl::VariableComponentCount(varying->type); size_t componentCount = gl::VariableComponentCount(varying->type);
if (mData.mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS && if (mData.mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
...@@ -2037,9 +2031,10 @@ bool Program::linkValidateTransformFeedback(InfoLog &infoLog, ...@@ -2037,9 +2031,10 @@ bool Program::linkValidateTransformFeedback(InfoLog &infoLog,
} }
} }
// TODO(jmadill): investigate if we can support capturing array elements.
if (tfVaryingName.find('[') != std::string::npos) if (tfVaryingName.find('[') != std::string::npos)
{ {
infoLog << "Capture of array elements is undefined and not supported."; infoLog << "Capture of array elements not currently supported.";
return false; return false;
} }
......
...@@ -76,13 +76,6 @@ class BindingPointer ...@@ -76,13 +76,6 @@ class BindingPointer
GLuint id() const { return (mObject != nullptr) ? mObject->id() : 0; } GLuint id() const { return (mObject != nullptr) ? mObject->id() : 0; }
bool operator==(const BindingPointer<ObjectType> &other) const
{
return mObject == other.mObject;
}
bool operator!=(const BindingPointer<ObjectType> &other) const { return !(*this == other); }
private: private:
ObjectType *mObject; ObjectType *mObject;
}; };
...@@ -110,16 +103,6 @@ class OffsetBindingPointer : public BindingPointer<ObjectType> ...@@ -110,16 +103,6 @@ class OffsetBindingPointer : public BindingPointer<ObjectType>
GLintptr getOffset() const { return mOffset; } GLintptr getOffset() const { return mOffset; }
GLsizeiptr getSize() const { return mSize; } GLsizeiptr getSize() const { return mSize; }
bool operator==(const OffsetBindingPointer<ObjectType> &other) const
{
return this->get() == other.get() && mOffset == other.mOffset && mSize == other.mSize;
}
bool operator!=(const OffsetBindingPointer<ObjectType> &other) const
{
return !(*this == other);
}
private: private:
GLintptr mOffset; GLintptr mOffset;
GLsizeiptr mSize; GLsizeiptr mSize;
......
...@@ -918,29 +918,6 @@ void FunctionsGL::initialize() ...@@ -918,29 +918,6 @@ void FunctionsGL::initialize()
AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGetQueryObjectivARB"), &getQueryObjectiv); AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGetQueryObjectivARB"), &getQueryObjectiv);
AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGetQueryObjectuivARB"), &getQueryObjectuiv); AssignGLExtensionEntryPoint(extensions, "GL_ARB_occlusion_query", loadProcAddress("glGetQueryObjectuivARB"), &getQueryObjectuiv);
// EXT_transform_feedback
AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glBindBufferRangeEXT"), &bindBufferRange);
AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glBindBufferBaseEXT"), &bindBufferBase);
AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glBeginTransformFeedbackEXT"), &beginTransformFeedback);
AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glEndTransformFeedbackEXT"), &endTransformFeedback);
AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glTransformFeedbackVaryingsEXT"), &transformFeedbackVaryings);
AssignGLExtensionEntryPoint(extensions, "EXT_transform_feedback", loadProcAddress("glGetTransformFeedbackVaryingEXT"), &getTransformFeedbackVarying);
// GL_ARB_transform_feedback2
AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glBindTransformFeedback"), &bindTransformFeedback);
AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glDeleteTransformFeedbacks"), &deleteTransformFeedbacks);
AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glGenTransformFeedbacks"), &genTransformFeedbacks);
AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glIsTransformFeedback"), &isTransformFeedback);
AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glPauseTransformFeedback"), &pauseTransformFeedback);
AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glResumeTransformFeedback"), &resumeTransformFeedback);
AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback2", loadProcAddress("glDrawTransformFeedback"), &drawTransformFeedback);
// GL_ARB_transform_feedback3
AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glDrawTransformFeedbackStream"), &drawTransformFeedbackStream);
AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glBeginQueryIndexed"), &beginQueryIndexed);
AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glEndQueryIndexed"), &endQueryIndexed);
AssignGLExtensionEntryPoint(extensions, "GL_ARB_transform_feedback3", loadProcAddress("glGetQueryIndexediv"), &getQueryIndexediv);
// 1.0 // 1.0
if (isAtLeastGL(gl::Version(1, 0))) if (isAtLeastGL(gl::Version(1, 0)))
{ {
......
...@@ -51,29 +51,6 @@ LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog) ...@@ -51,29 +51,6 @@ LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog)
// Reset the program state, delete the current program if one exists // Reset the program state, delete the current program if one exists
reset(); reset();
// Set the transform feedback state
std::vector<const GLchar *> transformFeedbackVaryings;
for (const auto &tfVarying : mData.getTransformFeedbackVaryingNames())
{
transformFeedbackVaryings.push_back(tfVarying.c_str());
}
if (transformFeedbackVaryings.empty())
{
if (mFunctions->transformFeedbackVaryings)
{
mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
mData.getTransformFeedbackBufferMode());
}
}
else
{
ASSERT(mFunctions->transformFeedbackVaryings);
mFunctions->transformFeedbackVaryings(
mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()),
&transformFeedbackVaryings[0], mData.getTransformFeedbackBufferMode());
}
const gl::Shader *vertexShader = mData.getAttachedVertexShader(); const gl::Shader *vertexShader = mData.getAttachedVertexShader();
const gl::Shader *fragmentShader = mData.getAttachedFragmentShader(); const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
......
...@@ -315,8 +315,7 @@ FenceSyncImpl *RendererGL::createFenceSync() ...@@ -315,8 +315,7 @@ FenceSyncImpl *RendererGL::createFenceSync()
TransformFeedbackImpl *RendererGL::createTransformFeedback() TransformFeedbackImpl *RendererGL::createTransformFeedback()
{ {
return new TransformFeedbackGL(mFunctions, mStateManager, return new TransformFeedbackGL();
getRendererCaps().maxTransformFeedbackSeparateComponents);
} }
SamplerImpl *RendererGL::createSampler() SamplerImpl *RendererGL::createSampler()
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include "common/BitSetIterator.h" #include "common/BitSetIterator.h"
#include "libANGLE/Data.h" #include "libANGLE/Data.h"
#include "libANGLE/Framebuffer.h" #include "libANGLE/Framebuffer.h"
#include "libANGLE/TransformFeedback.h"
#include "libANGLE/VertexArray.h" #include "libANGLE/VertexArray.h"
#include "libANGLE/Query.h" #include "libANGLE/Query.h"
#include "libANGLE/renderer/gl/BufferGL.h" #include "libANGLE/renderer/gl/BufferGL.h"
...@@ -20,7 +19,6 @@ ...@@ -20,7 +19,6 @@
#include "libANGLE/renderer/gl/ProgramGL.h" #include "libANGLE/renderer/gl/ProgramGL.h"
#include "libANGLE/renderer/gl/SamplerGL.h" #include "libANGLE/renderer/gl/SamplerGL.h"
#include "libANGLE/renderer/gl/TextureGL.h" #include "libANGLE/renderer/gl/TextureGL.h"
#include "libANGLE/renderer/gl/TransformFeedbackGL.h"
#include "libANGLE/renderer/gl/VertexArrayGL.h" #include "libANGLE/renderer/gl/VertexArrayGL.h"
#include "libANGLE/renderer/gl/QueryGL.h" #include "libANGLE/renderer/gl/QueryGL.h"
...@@ -44,9 +42,7 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, const gl::Caps &ren ...@@ -44,9 +42,7 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, const gl::Caps &ren
mTextureUnitIndex(0), mTextureUnitIndex(0),
mTextures(), mTextures(),
mSamplers(rendererCaps.maxCombinedTextureImageUnits, 0), mSamplers(rendererCaps.maxCombinedTextureImageUnits, 0),
mTransformFeedback(0),
mQueries(), mQueries(),
mPrevDrawTransformFeedback(nullptr),
mPrevDrawQueries(), mPrevDrawQueries(),
mPrevDrawContext(0), mPrevDrawContext(0),
mUnpackAlignment(4), mUnpackAlignment(4),
...@@ -263,25 +259,6 @@ void StateManagerGL::deleteRenderbuffer(GLuint rbo) ...@@ -263,25 +259,6 @@ void StateManagerGL::deleteRenderbuffer(GLuint rbo)
} }
} }
void StateManagerGL::deleteTransformFeedback(GLuint transformFeedback)
{
if (transformFeedback != 0)
{
if (mTransformFeedback == transformFeedback)
{
bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
}
if (mPrevDrawTransformFeedback != nullptr &&
mPrevDrawTransformFeedback->getTransformFeedbackID() == transformFeedback)
{
mPrevDrawTransformFeedback = nullptr;
}
mFunctions->deleteTransformFeedbacks(1, &transformFeedback);
}
}
void StateManagerGL::deleteQuery(GLuint query) void StateManagerGL::deleteQuery(GLuint query)
{ {
if (query != 0) if (query != 0)
...@@ -539,26 +516,6 @@ void StateManagerGL::bindRenderbuffer(GLenum type, GLuint renderbuffer) ...@@ -539,26 +516,6 @@ void StateManagerGL::bindRenderbuffer(GLenum type, GLuint renderbuffer)
} }
} }
void StateManagerGL::bindTransformFeedback(GLenum type, GLuint transformFeedback)
{
ASSERT(type == GL_TRANSFORM_FEEDBACK);
if (mTransformFeedback != transformFeedback)
{
// Pause the current transform feedback if one is active.
// To handle virtualized contexts, StateManagerGL needs to be able to bind a new transform
// feedback at any time, even if there is one active.
if (mPrevDrawTransformFeedback != nullptr &&
mPrevDrawTransformFeedback->getTransformFeedbackID() != transformFeedback)
{
mPrevDrawTransformFeedback->syncPausedState(true);
mPrevDrawTransformFeedback = nullptr;
}
mTransformFeedback = transformFeedback;
mFunctions->bindTransformFeedback(type, mTransformFeedback);
}
}
void StateManagerGL::beginQuery(GLenum type, GLuint query) void StateManagerGL::beginQuery(GLenum type, GLuint query)
{ {
// Make sure this is a valid query type and there is no current active query of this type // Make sure this is a valid query type and there is no current active query of this type
...@@ -637,25 +594,6 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data) ...@@ -637,25 +594,6 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data)
{ {
const gl::State &state = *data.state; const gl::State &state = *data.state;
// If the context has changed, pause the previous context's transform feedback and queries
if (data.context != mPrevDrawContext)
{
if (mPrevDrawTransformFeedback != nullptr)
{
mPrevDrawTransformFeedback->syncPausedState(true);
}
for (QueryGL *prevQuery : mPrevDrawQueries)
{
prevQuery->pause();
}
}
mPrevDrawTransformFeedback = nullptr;
mPrevDrawQueries.clear();
mPrevDrawContext = data.context;
// Sync the current program state
const gl::Program *program = state.getProgram(); const gl::Program *program = state.getProgram();
const ProgramGL *programGL = GetImplAs<ProgramGL>(program); const ProgramGL *programGL = GetImplAs<ProgramGL>(program);
useProgram(programGL->getProgramID()); useProgram(programGL->getProgramID());
...@@ -733,23 +671,17 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data) ...@@ -733,23 +671,17 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data)
// Seamless cubemaps are required for ES3 and higher contexts. // Seamless cubemaps are required for ES3 and higher contexts.
setTextureCubemapSeamlessEnabled(data.clientVersion >= 3); setTextureCubemapSeamlessEnabled(data.clientVersion >= 3);
// Set the current transform feedback state // If the context has changed, pause the previous context's queries
gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback(); if (data.context != mPrevDrawContext)
if (transformFeedback)
{
TransformFeedbackGL *transformFeedbackGL =
GetImplAs<TransformFeedbackGL>(transformFeedback);
bindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackGL->getTransformFeedbackID());
transformFeedbackGL->syncActiveState(transformFeedback->isActive(),
transformFeedback->getPrimitiveMode());
transformFeedbackGL->syncPausedState(transformFeedback->isPaused());
mPrevDrawTransformFeedback = transformFeedbackGL;
}
else
{ {
bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); for (QueryGL *prevQuery : mPrevDrawQueries)
mPrevDrawTransformFeedback = nullptr; {
prevQuery->pause();
}
} }
mPrevDrawQueries.clear();
mPrevDrawContext = data.context;
// Set the current query state // Set the current query state
for (GLenum queryType : QueryTypes) for (GLenum queryType : QueryTypes)
......
...@@ -28,7 +28,6 @@ namespace rx ...@@ -28,7 +28,6 @@ namespace rx
{ {
class FunctionsGL; class FunctionsGL;
class TransformFeedbackGL;
class QueryGL; class QueryGL;
class StateManagerGL final : angle::NonCopyable class StateManagerGL final : angle::NonCopyable
...@@ -43,7 +42,6 @@ class StateManagerGL final : angle::NonCopyable ...@@ -43,7 +42,6 @@ class StateManagerGL final : angle::NonCopyable
void deleteBuffer(GLuint buffer); void deleteBuffer(GLuint buffer);
void deleteFramebuffer(GLuint fbo); void deleteFramebuffer(GLuint fbo);
void deleteRenderbuffer(GLuint rbo); void deleteRenderbuffer(GLuint rbo);
void deleteTransformFeedback(GLuint transformFeedback);
void deleteQuery(GLuint query); void deleteQuery(GLuint query);
void useProgram(GLuint program); void useProgram(GLuint program);
...@@ -56,7 +54,6 @@ class StateManagerGL final : angle::NonCopyable ...@@ -56,7 +54,6 @@ class StateManagerGL final : angle::NonCopyable
void bindSampler(size_t unit, GLuint sampler); void bindSampler(size_t unit, GLuint sampler);
void bindFramebuffer(GLenum type, GLuint framebuffer); void bindFramebuffer(GLenum type, GLuint framebuffer);
void bindRenderbuffer(GLenum type, GLuint renderbuffer); void bindRenderbuffer(GLenum type, GLuint renderbuffer);
void bindTransformFeedback(GLenum type, GLuint transformFeedback);
void beginQuery(GLenum type, GLuint query); void beginQuery(GLenum type, GLuint query);
void endQuery(GLenum type, GLuint query); void endQuery(GLenum type, GLuint query);
...@@ -165,11 +162,8 @@ class StateManagerGL final : angle::NonCopyable ...@@ -165,11 +162,8 @@ class StateManagerGL final : angle::NonCopyable
std::map<GLenum, std::vector<GLuint>> mTextures; std::map<GLenum, std::vector<GLuint>> mTextures;
std::vector<GLuint> mSamplers; std::vector<GLuint> mSamplers;
GLuint mTransformFeedback;
std::map<GLenum, GLuint> mQueries; std::map<GLenum, GLuint> mQueries;
TransformFeedbackGL *mPrevDrawTransformFeedback;
std::set<QueryGL *> mPrevDrawQueries; std::set<QueryGL *> mPrevDrawQueries;
uintptr_t mPrevDrawContext; uintptr_t mPrevDrawContext;
......
...@@ -9,134 +9,51 @@ ...@@ -9,134 +9,51 @@
#include "libANGLE/renderer/gl/TransformFeedbackGL.h" #include "libANGLE/renderer/gl/TransformFeedbackGL.h"
#include "common/debug.h" #include "common/debug.h"
#include "libANGLE/Data.h"
#include "libANGLE/renderer/gl/BufferGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
namespace rx namespace rx
{ {
TransformFeedbackGL::TransformFeedbackGL(const FunctionsGL *functions, TransformFeedbackGL::TransformFeedbackGL()
StateManagerGL *stateManager, : TransformFeedbackImpl()
size_t maxTransformFeedbackBufferBindings) {}
: TransformFeedbackImpl(),
mFunctions(functions),
mStateManager(stateManager),
mTransformFeedbackID(0),
mIsActive(false),
mIsPaused(false),
mCurrentIndexedBuffers(maxTransformFeedbackBufferBindings)
{
mFunctions->genTransformFeedbacks(1, &mTransformFeedbackID);
}
TransformFeedbackGL::~TransformFeedbackGL() TransformFeedbackGL::~TransformFeedbackGL()
{ {}
mStateManager->deleteTransformFeedback(mTransformFeedbackID);
mTransformFeedbackID = 0;
for (auto &bufferBinding : mCurrentIndexedBuffers)
{
bufferBinding.set(nullptr);
}
}
void TransformFeedbackGL::begin(GLenum primitiveMode) void TransformFeedbackGL::begin(GLenum primitiveMode)
{ {
// Do not begin directly, StateManagerGL will handle beginning and resuming transform feedback. // Skipped to prevent assertions in tests
// UNIMPLEMENTED();
} }
void TransformFeedbackGL::end() void TransformFeedbackGL::end()
{ {
syncActiveState(false, GL_NONE); // Skipped to prevent assertions in tests
// UNIMPLEMENTED();
} }
void TransformFeedbackGL::pause() void TransformFeedbackGL::pause()
{ {
syncPausedState(true); // Skipped to prevent assertions in tests
// UNIMPLEMENTED();
} }
void TransformFeedbackGL::resume() void TransformFeedbackGL::resume()
{ {
// Do not resume directly, StateManagerGL will handle beginning and resuming transform feedback. // Skipped to prevent assertions in tests
// UNIMPLEMENTED();
} }
void TransformFeedbackGL::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) void TransformFeedbackGL::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
{ {
// Skipped to prevent assertions in tests
// UNIMPLEMENTED();
} }
void TransformFeedbackGL::bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) void TransformFeedbackGL::bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding)
{ {
// Directly bind buffer (not through the StateManager methods) because the buffer bindings are // Skipped to prevent assertions in tests
// tracked per transform feedback object // UNIMPLEMENTED();
if (binding != mCurrentIndexedBuffers[index])
{
mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
if (binding.get() != nullptr)
{
const BufferGL *bufferGL = GetImplAs<BufferGL>(binding.get());
if (binding.getSize() != 0)
{
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
{
mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index), 0);
}
mCurrentIndexedBuffers[index] = binding;
}
}
GLuint TransformFeedbackGL::getTransformFeedbackID() const
{
return mTransformFeedbackID;
}
void TransformFeedbackGL::syncActiveState(bool active, GLenum primitiveMode) const
{
if (mIsActive != active)
{
mIsActive = active;
mIsPaused = false;
mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
if (mIsActive)
{
mFunctions->beginTransformFeedback(primitiveMode);
}
else
{
mFunctions->endTransformFeedback();
}
}
}
void TransformFeedbackGL::syncPausedState(bool paused) const
{
if (mIsActive && mIsPaused != paused)
{
mIsPaused = paused;
mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
if (mIsPaused)
{
mFunctions->pauseTransformFeedback();
}
else
{
mFunctions->resumeTransformFeedback();
}
}
} }
} }
...@@ -14,15 +14,10 @@ ...@@ -14,15 +14,10 @@
namespace rx namespace rx
{ {
class FunctionsGL;
class StateManagerGL;
class TransformFeedbackGL : public TransformFeedbackImpl class TransformFeedbackGL : public TransformFeedbackImpl
{ {
public: public:
TransformFeedbackGL(const FunctionsGL *functions, TransformFeedbackGL();
StateManagerGL *stateManager,
size_t maxTransformFeedbackBufferBindings);
~TransformFeedbackGL() override; ~TransformFeedbackGL() override;
void begin(GLenum primitiveMode) override; void begin(GLenum primitiveMode) override;
...@@ -32,22 +27,6 @@ class TransformFeedbackGL : public TransformFeedbackImpl ...@@ -32,22 +27,6 @@ class TransformFeedbackGL : 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;
GLuint getTransformFeedbackID() const;
void syncActiveState(bool active, GLenum primitiveMode) const;
void syncPausedState(bool paused) const;
private:
const FunctionsGL *mFunctions;
StateManagerGL *mStateManager;
GLuint mTransformFeedbackID;
mutable bool mIsActive;
mutable bool mIsPaused;
std::vector<OffsetBindingPointer<gl::Buffer>> mCurrentIndexedBuffers;
}; };
} }
......
...@@ -478,8 +478,7 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM ...@@ -478,8 +478,7 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM
caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits; caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits;
// Table 6.34, implementation dependent transform feedback limits // Table 6.34, implementation dependent transform feedback limits
if (functions->isAtLeastGL(gl::Version(4, 0)) || if (functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_EXT_transform_feedback") ||
functions->hasGLExtension("GL_ARB_transform_feedback2") ||
functions->isAtLeastGLES(gl::Version(3, 0))) functions->isAtLeastGLES(gl::Version(3, 0)))
{ {
caps->maxTransformFeedbackInterleavedComponents = QuerySingleGLInt(functions, GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS); caps->maxTransformFeedbackInterleavedComponents = QuerySingleGLInt(functions, GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS);
......
...@@ -133,9 +133,6 @@ TEST_P(TransformFeedbackTest, RecordAndDraw) ...@@ -133,9 +133,6 @@ TEST_P(TransformFeedbackTest, RecordAndDraw)
return; return;
} }
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Set the program's transform feedback varyings (just gl_Position) // Set the program's transform feedback varyings (just gl_Position)
const GLchar* transformFeedbackVaryings[] = const GLchar* transformFeedbackVaryings[] =
{ {
...@@ -339,288 +336,7 @@ TEST_P(TransformFeedbackTest, VertexOnly) ...@@ -339,288 +336,7 @@ TEST_P(TransformFeedbackTest, VertexOnly)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Test that multiple paused transform feedbacks do not generate errors or crash
TEST_P(TransformFeedbackTest, MultiplePaused)
{
const size_t drawSize = 1024;
std::vector<float> transformFeedbackData(drawSize);
for (size_t i = 0; i < drawSize; i++)
{
transformFeedbackData[i] = static_cast<float>(i + 1);
}
// Initialize the buffers to zero
size_t bufferSize = drawSize;
std::vector<float> bufferInitialData(bufferSize, 0);
const size_t transformFeedbackCount = 8;
// clang-format off
const std::string vertexShaderSource = SHADER_SOURCE
( #version 300 es\n
in highp vec4 position;
in float transformFeedbackInput;
out float transformFeedbackOutput;
void main(void)
{
gl_Position = position;
transformFeedbackOutput = transformFeedbackInput;
}
);
const std::string fragmentShaderSource = SHADER_SOURCE
( #version 300 es\n
out mediump vec4 color;
void main(void)
{
color = vec4(1.0, 1.0, 1.0, 1.0);
}
);
// clang-format on
std::vector<std::string> tfVaryings;
tfVaryings.push_back("transformFeedbackOutput");
GLuint program = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
tfVaryings, GL_INTERLEAVED_ATTRIBS);
ASSERT_NE(program, 0u);
glUseProgram(program);
GLint positionLocation = glGetAttribLocation(program, "position");
glDisableVertexAttribArray(positionLocation);
glVertexAttrib4f(positionLocation, 0.0f, 0.0f, 0.0f, 1.0f);
GLint tfInputLocation = glGetAttribLocation(program, "transformFeedbackInput");
glEnableVertexAttribArray(tfInputLocation);
glVertexAttribPointer(tfInputLocation, 1, GL_FLOAT, false, 0, &transformFeedbackData[0]);
glDepthMask(GL_FALSE);
glEnable(GL_DEPTH_TEST);
ASSERT_GL_NO_ERROR();
GLuint transformFeedbacks[transformFeedbackCount];
glGenTransformFeedbacks(transformFeedbackCount, transformFeedbacks);
GLuint buffers[transformFeedbackCount];
glGenBuffers(transformFeedbackCount, buffers);
for (size_t i = 0; i < transformFeedbackCount; i++)
{
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbacks[i]);
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffers[i]);
glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bufferSize * sizeof(GLfloat),
&bufferInitialData[0], GL_DYNAMIC_DRAW);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffers[i]);
ASSERT_GL_NO_ERROR();
glBeginTransformFeedback(GL_POINTS);
glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(drawSize));
glPauseTransformFeedback();
EXPECT_GL_NO_ERROR();
}
for (size_t i = 0; i < transformFeedbackCount; i++)
{
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbacks[i]);
glEndTransformFeedback();
glDeleteTransformFeedbacks(1, &transformFeedbacks[i]);
EXPECT_GL_NO_ERROR();
}
}
// Test that running multiple simultaneous queries and transform feedbacks from multiple EGL
// contexts returns the correct results. Helps expose bugs in ANGLE's virtual contexts.
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 (isNVidia() && GetParam() == ES3_OPENGL())
{
std::cout << "Test skipped on NVidia OpenGL on OSX due to driver bugs." << std::endl;
return;
}
#endif
EGLint contextAttributes[] = {
EGL_CONTEXT_MAJOR_VERSION_KHR,
GetParam().majorVersion,
EGL_CONTEXT_MINOR_VERSION_KHR,
GetParam().minorVersion,
EGL_NONE,
};
EGLWindow *window = getEGLWindow();
EGLDisplay display = window->getDisplay();
EGLConfig config = window->getConfig();
EGLSurface surface = window->getSurface();
const size_t passCount = 5;
struct ContextInfo
{
EGLContext context;
GLuint program;
GLuint query;
GLuint buffer;
size_t primitiveCounts[passCount];
};
ContextInfo contexts[32];
const size_t maxDrawSize = 1024;
std::vector<float> transformFeedbackData(maxDrawSize);
for (size_t i = 0; i < maxDrawSize; i++)
{
transformFeedbackData[i] = static_cast<float>(i + 1);
}
// Initialize the buffers to zero
size_t bufferSize = maxDrawSize * passCount;
std::vector<float> bufferInitialData(bufferSize, 0);
for (auto &context : contexts)
{
context.context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
ASSERT_NE(context.context, EGL_NO_CONTEXT);
eglMakeCurrent(display, surface, surface, context.context);
// clang-format off
const std::string vertexShaderSource = SHADER_SOURCE
( #version 300 es\n
in highp vec4 position;
in float transformFeedbackInput;
out float transformFeedbackOutput;
void main(void)
{
gl_Position = position;
transformFeedbackOutput = transformFeedbackInput;
}
);
const std::string fragmentShaderSource = SHADER_SOURCE
( #version 300 es\n
out mediump vec4 color;
void main(void)
{
color = vec4(1.0, 1.0, 1.0, 1.0);
}
);
// clang-format on
std::vector<std::string> tfVaryings;
tfVaryings.push_back("transformFeedbackOutput");
context.program = CompileProgramWithTransformFeedback(
vertexShaderSource, fragmentShaderSource, tfVaryings, GL_INTERLEAVED_ATTRIBS);
ASSERT_NE(context.program, 0u);
glUseProgram(context.program);
GLint positionLocation = glGetAttribLocation(context.program, "position");
glDisableVertexAttribArray(positionLocation);
glVertexAttrib4f(positionLocation, 0.0f, 0.0f, 0.0f, 1.0f);
GLint tfInputLocation = glGetAttribLocation(context.program, "transformFeedbackInput");
glEnableVertexAttribArray(tfInputLocation);
glVertexAttribPointer(tfInputLocation, 1, GL_FLOAT, false, 0, &transformFeedbackData[0]);
glDepthMask(GL_FALSE);
glEnable(GL_DEPTH_TEST);
glGenQueriesEXT(1, &context.query);
glBeginQueryEXT(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, context.query);
ASSERT_GL_NO_ERROR();
glGenBuffers(1, &context.buffer);
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, context.buffer);
glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bufferSize * sizeof(GLfloat),
&bufferInitialData[0], GL_DYNAMIC_DRAW);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, context.buffer);
ASSERT_GL_NO_ERROR();
// For each pass, draw between 0 and maxDrawSize primitives
for (auto &primCount : context.primitiveCounts)
{
primCount = rand() % maxDrawSize;
}
glBeginTransformFeedback(GL_POINTS);
}
for (size_t pass = 0; pass < passCount; pass++)
{
for (const auto &context : contexts)
{
eglMakeCurrent(display, surface, surface, context.context);
glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(context.primitiveCounts[pass]));
}
}
for (const auto &context : contexts)
{
eglMakeCurrent(display, surface, surface, context.context);
glEndTransformFeedback();
glEndQueryEXT(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
GLuint result = 0;
glGetQueryObjectuivEXT(context.query, GL_QUERY_RESULT_EXT, &result);
EXPECT_GL_NO_ERROR();
size_t totalPrimCount = 0;
for (const auto &primCount : context.primitiveCounts)
{
totalPrimCount += primCount;
}
EXPECT_EQ(static_cast<GLuint>(totalPrimCount), result);
const float *bufferData = reinterpret_cast<float *>(glMapBufferRange(
GL_TRANSFORM_FEEDBACK_BUFFER, 0, bufferSize * sizeof(GLfloat), GL_MAP_READ_BIT));
size_t curBufferIndex = 0;
for (const auto &primCount : context.primitiveCounts)
{
for (size_t prim = 0; prim < primCount; prim++)
{
EXPECT_EQ(bufferData[curBufferIndex], prim + 1);
curBufferIndex++;
}
}
while (curBufferIndex < bufferSize)
{
EXPECT_EQ(bufferData[curBufferIndex], 0.0f);
curBufferIndex++;
}
glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
}
eglMakeCurrent(display, surface, surface, window->getContext());
for (auto &context : contexts)
{
eglDestroyContext(display, context.context);
context.context = EGL_NO_CONTEXT;
}
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against. // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(TransformFeedbackTest, ES3_D3D11(), ES3_OPENGL()); ANGLE_INSTANTIATE_TEST(TransformFeedbackTest, ES3_D3D11());
} // namespace } // namespace
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