Commit 1a683460 by Geoff Lang

Implement TransformFeedbackGL.

Reland with supression for TransformFeedbackTest.MultiContext on Linux AMD. BUG=angleproject:889 Change-Id: I6f2a2e856dacf16308de222dd0936bedbb3b175c Reviewed-on: https://chromium-review.googlesource.com/307871 Tryjob-Request: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent a9ca8e20
...@@ -38,7 +38,7 @@ namespace ...@@ -38,7 +38,7 @@ namespace
void MarkTransformFeedbackBufferUsage(gl::TransformFeedback *transformFeedback) void MarkTransformFeedbackBufferUsage(gl::TransformFeedback *transformFeedback)
{ {
if (transformFeedback->isActive() && !transformFeedback->isPaused()) if (transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
{ {
for (size_t tfBufferIndex = 0; tfBufferIndex < transformFeedback->getIndexedBufferCount(); for (size_t tfBufferIndex = 0; tfBufferIndex < transformFeedback->getIndexedBufferCount();
tfBufferIndex++) tfBufferIndex++)
...@@ -138,12 +138,16 @@ Context::Context(const egl::Config *config, ...@@ -138,12 +138,16 @@ Context::Context(const egl::Config *config,
bindPixelPackBuffer(0); bindPixelPackBuffer(0);
bindPixelUnpackBuffer(0); bindPixelUnpackBuffer(0);
// [OpenGL ES 3.0.2] section 2.14.1 pg 85: if (mClientVersion >= 3)
// 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 // [OpenGL ES 3.0.2] section 2.14.1 pg 85:
// BindTransformFeedback is called with id of zero // In the initial state, a default transform feedback object is bound and treated as
mTransformFeedbackZero.set(new TransformFeedback(mRenderer->createTransformFeedback(), 0, mCaps)); // a transform feedback object with a name of zero. That object is bound any time
bindTransformFeedback(0); // BindTransformFeedback is called with id of zero
mTransformFeedbackZero.set(
new TransformFeedback(mRenderer->createTransformFeedback(), 0, mCaps));
bindTransformFeedback(0);
}
mHasBeenCurrent = false; mHasBeenCurrent = false;
mContextLost = false; mContextLost = false;
...@@ -188,7 +192,7 @@ Context::~Context() ...@@ -188,7 +192,7 @@ Context::~Context()
mTransformFeedbackZero.set(NULL); mTransformFeedbackZero.set(NULL);
for (auto transformFeedback : mTransformFeedbackMap) for (auto transformFeedback : mTransformFeedbackMap)
{ {
SafeDelete(transformFeedback.second); transformFeedback.second->release();
} }
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_NONE) mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS)
{ {
} }
...@@ -2014,6 +2014,12 @@ bool Program::linkValidateTransformFeedback(InfoLog &infoLog, ...@@ -2014,6 +2014,12 @@ 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 &&
...@@ -2031,10 +2037,9 @@ bool Program::linkValidateTransformFeedback(InfoLog &infoLog, ...@@ -2031,10 +2037,9 @@ 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 not currently supported."; infoLog << "Capture of array elements is undefined and not supported.";
return false; return false;
} }
......
...@@ -76,6 +76,13 @@ class BindingPointer ...@@ -76,6 +76,13 @@ 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;
}; };
...@@ -103,6 +110,16 @@ class OffsetBindingPointer : public BindingPointer<ObjectType> ...@@ -103,6 +110,16 @@ 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,6 +918,29 @@ void FunctionsGL::initialize() ...@@ -918,6 +918,29 @@ 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,6 +51,29 @@ LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog) ...@@ -51,6 +51,29 @@ 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,7 +315,8 @@ FenceSyncImpl *RendererGL::createFenceSync() ...@@ -315,7 +315,8 @@ FenceSyncImpl *RendererGL::createFenceSync()
TransformFeedbackImpl *RendererGL::createTransformFeedback() TransformFeedbackImpl *RendererGL::createTransformFeedback()
{ {
return new TransformFeedbackGL(); return new TransformFeedbackGL(mFunctions, mStateManager,
getRendererCaps().maxTransformFeedbackSeparateComponents);
} }
SamplerImpl *RendererGL::createSampler() SamplerImpl *RendererGL::createSampler()
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#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"
...@@ -19,6 +20,7 @@ ...@@ -19,6 +20,7 @@
#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"
...@@ -42,7 +44,9 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, const gl::Caps &ren ...@@ -42,7 +44,9 @@ 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),
...@@ -259,6 +263,25 @@ void StateManagerGL::deleteRenderbuffer(GLuint rbo) ...@@ -259,6 +263,25 @@ 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)
...@@ -516,6 +539,26 @@ void StateManagerGL::bindRenderbuffer(GLenum type, GLuint renderbuffer) ...@@ -516,6 +539,26 @@ 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
...@@ -594,6 +637,25 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data) ...@@ -594,6 +637,25 @@ 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());
...@@ -671,17 +733,23 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::Data &data) ...@@ -671,17 +733,23 @@ 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);
// If the context has changed, pause the previous context's queries // Set the current transform feedback state
if (data.context != mPrevDrawContext) gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback();
if (transformFeedback)
{ {
for (QueryGL *prevQuery : mPrevDrawQueries) TransformFeedbackGL *transformFeedbackGL =
{ GetImplAs<TransformFeedbackGL>(transformFeedback);
prevQuery->pause(); bindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackGL->getTransformFeedbackID());
} transformFeedbackGL->syncActiveState(transformFeedback->isActive(),
transformFeedback->getPrimitiveMode());
transformFeedbackGL->syncPausedState(transformFeedback->isPaused());
mPrevDrawTransformFeedback = transformFeedbackGL;
}
else
{
bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
mPrevDrawTransformFeedback = nullptr;
} }
mPrevDrawQueries.clear();
mPrevDrawContext = data.context;
// Set the current query state // Set the current query state
for (GLenum queryType : QueryTypes) for (GLenum queryType : QueryTypes)
......
...@@ -28,6 +28,7 @@ namespace rx ...@@ -28,6 +28,7 @@ namespace rx
{ {
class FunctionsGL; class FunctionsGL;
class TransformFeedbackGL;
class QueryGL; class QueryGL;
class StateManagerGL final : angle::NonCopyable class StateManagerGL final : angle::NonCopyable
...@@ -42,6 +43,7 @@ class StateManagerGL final : angle::NonCopyable ...@@ -42,6 +43,7 @@ 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);
...@@ -54,6 +56,7 @@ class StateManagerGL final : angle::NonCopyable ...@@ -54,6 +56,7 @@ 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);
...@@ -162,8 +165,11 @@ class StateManagerGL final : angle::NonCopyable ...@@ -162,8 +165,11 @@ 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,51 +9,134 @@ ...@@ -9,51 +9,134 @@
#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() TransformFeedbackGL::TransformFeedbackGL(const FunctionsGL *functions,
: TransformFeedbackImpl() StateManagerGL *stateManager,
{} 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)
{ {
// Skipped to prevent assertions in tests // Do not begin directly, StateManagerGL will handle beginning and resuming transform feedback.
// UNIMPLEMENTED();
} }
void TransformFeedbackGL::end() void TransformFeedbackGL::end()
{ {
// Skipped to prevent assertions in tests syncActiveState(false, GL_NONE);
// UNIMPLEMENTED();
} }
void TransformFeedbackGL::pause() void TransformFeedbackGL::pause()
{ {
// Skipped to prevent assertions in tests syncPausedState(true);
// UNIMPLEMENTED();
} }
void TransformFeedbackGL::resume() void TransformFeedbackGL::resume()
{ {
// Skipped to prevent assertions in tests // Do not resume directly, StateManagerGL will handle beginning and resuming transform feedback.
// 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)
{ {
// Skipped to prevent assertions in tests // Directly bind buffer (not through the StateManager methods) because the buffer bindings are
// UNIMPLEMENTED(); // tracked per transform feedback object
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,10 +14,15 @@ ...@@ -14,10 +14,15 @@
namespace rx namespace rx
{ {
class FunctionsGL;
class StateManagerGL;
class TransformFeedbackGL : public TransformFeedbackImpl class TransformFeedbackGL : public TransformFeedbackImpl
{ {
public: public:
TransformFeedbackGL(); TransformFeedbackGL(const FunctionsGL *functions,
StateManagerGL *stateManager,
size_t maxTransformFeedbackBufferBindings);
~TransformFeedbackGL() override; ~TransformFeedbackGL() override;
void begin(GLenum primitiveMode) override; void begin(GLenum primitiveMode) override;
...@@ -27,6 +32,22 @@ class TransformFeedbackGL : public TransformFeedbackImpl ...@@ -27,6 +32,22 @@ 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,7 +478,8 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM ...@@ -478,7 +478,8 @@ 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(3, 0)) || functions->hasGLExtension("GL_EXT_transform_feedback") || if (functions->isAtLeastGL(gl::Version(4, 0)) ||
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);
......
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