Hash :
4b654982
Author :
Date :
2019-01-31T17:04:14
GL backend: Transform feedback driver bug workaround In some drivers, if transform feedback is paused and a new program is bound, calling endTransformFeedback does not correctly unpause first, creating an invalid paused but inactive state that causes errors later. Before calling endTransformFeedback we first ensure that the current program is the one associated with this transform feedback object when beginTransformFeedback was called. Bug: 832238 Change-Id: I2373b0c123fd20a7ee3ada76ed878d4968184476 Reviewed-on: https://chromium-review.googlesource.com/c/1448661 Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: James Darpinian <jdarpinian@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
//
// Copyright (c) 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.
//
#ifndef LIBANGLE_TRANSFORM_FEEDBACK_H_
#define LIBANGLE_TRANSFORM_FEEDBACK_H_
#include "libANGLE/RefCountObject.h"
#include "common/PackedEnums.h"
#include "common/angleutils.h"
#include "libANGLE/Debug.h"
#include "angle_gl.h"
namespace rx
{
class GLImplFactory;
class TransformFeedbackImpl;
class TransformFeedbackGL;
} // namespace rx
namespace gl
{
class Buffer;
struct Caps;
class Context;
class Program;
class TransformFeedbackState final : angle::NonCopyable
{
public:
TransformFeedbackState(size_t maxIndexedBuffers);
~TransformFeedbackState();
const OffsetBindingPointer<Buffer> &getIndexedBuffer(size_t idx) const;
const std::vector<OffsetBindingPointer<Buffer>> &getIndexedBuffers() const;
const Program *getBoundProgram() const { return mProgram; }
private:
friend class TransformFeedback;
std::string mLabel;
bool mActive;
PrimitiveMode mPrimitiveMode;
bool mPaused;
GLsizeiptr mVerticesDrawn;
GLsizeiptr mVertexCapacity;
Program *mProgram;
std::vector<OffsetBindingPointer<Buffer>> mIndexedBuffers;
};
class TransformFeedback final : public RefCountObject, public LabeledObject
{
public:
TransformFeedback(rx::GLImplFactory *implFactory, GLuint id, const Caps &caps);
~TransformFeedback() override;
void onDestroy(const Context *context) override;
void setLabel(const Context *context, const std::string &label) override;
const std::string &getLabel() const override;
angle::Result begin(const Context *context, PrimitiveMode primitiveMode, Program *program);
angle::Result end(const Context *context);
angle::Result pause(const Context *context);
angle::Result resume(const Context *context);
bool isActive() const { return mState.mActive; }
bool isPaused() const;
PrimitiveMode getPrimitiveMode() const;
// Validates that the vertices produced by a draw call will fit in the bound transform feedback
// buffers.
bool checkBufferSpaceForDraw(GLsizei count, GLsizei primcount) const;
// This must be called after each draw call when transform feedback is enabled to keep track of
// how many vertices have been written to the buffers. This information is needed by
// checkBufferSpaceForDraw because each draw call appends vertices to the buffers starting just
// after the last vertex of the previous draw call.
void onVerticesDrawn(const Context *context, GLsizei count, GLsizei primcount);
bool hasBoundProgram(GLuint program) const;
angle::Result bindIndexedBuffer(const Context *context,
size_t index,
Buffer *buffer,
size_t offset,
size_t size);
const OffsetBindingPointer<Buffer> &getIndexedBuffer(size_t index) const;
size_t getIndexedBufferCount() const;
// Returns true if any buffer bound to this object is also bound to another target.
bool buffersBoundForOtherUse() const;
angle::Result detachBuffer(const Context *context, GLuint bufferName);
rx::TransformFeedbackImpl *getImplementation();
const rx::TransformFeedbackImpl *getImplementation() const;
void onBindingChanged(const Context *context, bool bound);
private:
void bindProgram(const Context *context, Program *program);
TransformFeedbackState mState;
rx::TransformFeedbackImpl *mImplementation;
};
} // namespace gl
#endif // LIBANGLE_TRANSFORM_FEEDBACK_H_