Hash :
0bfa5504
Author :
Date :
2019-06-03T10:40:10
Vulkan: Emulate Transform Feedback with vertex shader output In ES 3.0 and 3.1, only non-indexed GL_POINTS, GL_LINES and GL_TRIANGLES is supported for transform feedback. Without tessellation and geometry shaders, we can calculate the exact location where each vertex transform output should be written on the CPU, and have each vertex shader invocation write its data separately to the appropriate location in the buffer. This depends on the vertexPipelineStoresAndAtomics Vulkan feature. Bug: angleproject:3205 Change-Id: I68ccbb80aece597cf20c557a0aee842360fea593 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1645678 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Jamie Madill <jmadill@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 116 117 118 119
//
// 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; }
GLsizeiptr getVerticesDrawn() const { return mVerticesDrawn; }
GLsizeiptr getPrimitivesDrawn() const;
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;
GLsizeiptr getVerticesDrawn() const { return mState.getVerticesDrawn(); }
GLsizeiptr getPrimitivesDrawn() const { return mState.getPrimitivesDrawn(); }
// 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;
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_