xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/metal/TransformFeedbackMtl.mm (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1//
2// Copyright 2020 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// TransformFeedbackMtl.mm:
7//    Defines the class interface for TransformFeedbackMtl, implementing TransformFeedbackImpl.
8//
9
10#include "libANGLE/renderer/metal/TransformFeedbackMtl.h"
11
12#include "common/debug.h"
13#include "libANGLE/Context.h"
14#include "libANGLE/Query.h"
15#include "libANGLE/renderer/metal/ContextMtl.h"
16#include "libANGLE/renderer/metal/QueryMtl.h"
17
18namespace rx
19{
20
21TransformFeedbackMtl::TransformFeedbackMtl(const gl::TransformFeedbackState &state)
22    : TransformFeedbackImpl(state)
23{}
24
25TransformFeedbackMtl::~TransformFeedbackMtl() {}
26
27angle::Result TransformFeedbackMtl::begin(const gl::Context *context,
28                                          gl::PrimitiveMode primitiveMode)
29{
30    mtl::GetImpl(context)->onTransformFeedbackActive(context, this);
31
32    return angle::Result::Continue;
33}
34
35angle::Result TransformFeedbackMtl::end(const gl::Context *context)
36{
37    const gl::State &glState = context->getState();
38    gl::Query *transformFeedbackQuery =
39        glState.getActiveQuery(gl::QueryType::TransformFeedbackPrimitivesWritten);
40    if (transformFeedbackQuery)
41    {
42        mtl::GetImpl(transformFeedbackQuery)->onTransformFeedbackEnd(context);
43    }
44
45    mtl::GetImpl(context)->onTransformFeedbackInactive(context, this);
46
47    return angle::Result::Continue;
48}
49
50angle::Result TransformFeedbackMtl::pause(const gl::Context *context)
51{
52    // When XFB is paused, OpenGL allows XFB buffers to be bound for other purposes. We need to call
53    // onTransformFeedbackInactive() to issue a sync.
54    mtl::GetImpl(context)->onTransformFeedbackInactive(context, this);
55
56    return angle::Result::Continue;
57}
58
59angle::Result TransformFeedbackMtl::resume(const gl::Context *context)
60{
61    mtl::GetImpl(context)->onTransformFeedbackActive(context, this);
62
63    return angle::Result::Continue;
64}
65
66angle::Result TransformFeedbackMtl::bindIndexedBuffer(
67    const gl::Context *context,
68    size_t index,
69    const gl::OffsetBindingPointer<gl::Buffer> &binding)
70{
71    // Do nothing for now
72
73    return angle::Result::Continue;
74}
75
76angle::Result TransformFeedbackMtl::getBufferOffsets(ContextMtl *contextMtl,
77                                                     GLint drawCallFirstVertex,
78                                                     uint32_t skippedVertices,
79                                                     int32_t *offsetsOut)
80{
81    int64_t verticesDrawn = static_cast<int64_t>(mState.getVerticesDrawn()) + skippedVertices;
82    const gl::ProgramExecutable *executable = contextMtl->getState().getProgramExecutable();
83    ASSERT(executable);
84    const std::vector<GLsizei> &bufferStrides = executable->getTransformFeedbackStrides();
85    size_t xfbBufferCount                     = executable->getTransformFeedbackBufferCount();
86
87    ASSERT(xfbBufferCount > 0);
88
89    for (size_t bufferIndex = 0; bufferIndex < xfbBufferCount; ++bufferIndex)
90    {
91        const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
92            mState.getIndexedBuffer(bufferIndex);
93
94        ASSERT((bufferBinding.getOffset() % 4) == 0);
95
96        // Offset the gl_VertexIndex by drawCallFirstVertex
97        int64_t drawCallVertexOffset = static_cast<int64_t>(verticesDrawn) - drawCallFirstVertex;
98
99        int64_t writeOffset =
100            (bufferBinding.getOffset() + drawCallVertexOffset * bufferStrides[bufferIndex]) /
101            static_cast<int64_t>(sizeof(uint32_t));
102
103        offsetsOut[bufferIndex] = static_cast<int32_t>(writeOffset);
104
105        // Check for overflow.
106        ANGLE_CHECK_GL_ALLOC(contextMtl, offsetsOut[bufferIndex] == writeOffset);
107    }
108
109    return angle::Result::Continue;
110}
111
112}  // namespace rx
113