xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/metal/ProvokingVertexHelper.mm (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker//
2*8975f5c5SAndroid Build Coastguard Worker// Copyright 2021 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker// Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker// found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker//
6*8975f5c5SAndroid Build Coastguard Worker// ProvokingVertexHelper.mm:
7*8975f5c5SAndroid Build Coastguard Worker//    Implements the class methods for ProvokingVertexHelper.
8*8975f5c5SAndroid Build Coastguard Worker//
9*8975f5c5SAndroid Build Coastguard Worker
10*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/ProvokingVertexHelper.h"
11*8975f5c5SAndroid Build Coastguard Worker#import <Foundation/Foundation.h>
12*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/Display.h"
13*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/ContextMtl.h"
14*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/DisplayMtl.h"
15*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/mtl_common.h"
16*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/shaders/rewrite_indices_shared.h"
17*8975f5c5SAndroid Build Coastguard Workernamespace rx
18*8975f5c5SAndroid Build Coastguard Worker{
19*8975f5c5SAndroid Build Coastguard Worker
20*8975f5c5SAndroid Build Coastguard Workernamespace
21*8975f5c5SAndroid Build Coastguard Worker{
22*8975f5c5SAndroid Build Coastguard Workerconstexpr size_t kInitialIndexBufferSize = 0xFFFF;  // Initial 64k pool.
23*8975f5c5SAndroid Build Coastguard Worker}
24*8975f5c5SAndroid Build Coastguard Workerstatic inline uint primCountForIndexCount(const uint fixIndexBufferKey, const uint indexCount)
25*8975f5c5SAndroid Build Coastguard Worker{
26*8975f5c5SAndroid Build Coastguard Worker    const uint fixIndexBufferMode =
27*8975f5c5SAndroid Build Coastguard Worker        (fixIndexBufferKey >> MtlFixIndexBufferKeyModeShift) & MtlFixIndexBufferKeyModeMask;
28*8975f5c5SAndroid Build Coastguard Worker
29*8975f5c5SAndroid Build Coastguard Worker    switch (fixIndexBufferMode)
30*8975f5c5SAndroid Build Coastguard Worker    {
31*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyPoints:
32*8975f5c5SAndroid Build Coastguard Worker            return indexCount;
33*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyLines:
34*8975f5c5SAndroid Build Coastguard Worker            return indexCount / 2;
35*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyLineStrip:
36*8975f5c5SAndroid Build Coastguard Worker            return (uint)MAX(0, (int)indexCount - 1);
37*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyLineLoop:
38*8975f5c5SAndroid Build Coastguard Worker            return (uint)MAX(0, (int)indexCount);
39*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyTriangles:
40*8975f5c5SAndroid Build Coastguard Worker            return indexCount / 3;
41*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyTriangleStrip:
42*8975f5c5SAndroid Build Coastguard Worker            return (uint)MAX(0, (int)indexCount - 2);
43*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyTriangleFan:
44*8975f5c5SAndroid Build Coastguard Worker            return (uint)MAX(0, (int)indexCount - 2);
45*8975f5c5SAndroid Build Coastguard Worker        default:
46*8975f5c5SAndroid Build Coastguard Worker            ASSERT(false);
47*8975f5c5SAndroid Build Coastguard Worker            return 0;
48*8975f5c5SAndroid Build Coastguard Worker    }
49*8975f5c5SAndroid Build Coastguard Worker}
50*8975f5c5SAndroid Build Coastguard Worker
51*8975f5c5SAndroid Build Coastguard Workerstatic inline uint indexCountForPrimCount(const uint fixIndexBufferKey, const uint primCount)
52*8975f5c5SAndroid Build Coastguard Worker{
53*8975f5c5SAndroid Build Coastguard Worker    const uint fixIndexBufferMode =
54*8975f5c5SAndroid Build Coastguard Worker        (fixIndexBufferKey >> MtlFixIndexBufferKeyModeShift) & MtlFixIndexBufferKeyModeMask;
55*8975f5c5SAndroid Build Coastguard Worker    switch (fixIndexBufferMode)
56*8975f5c5SAndroid Build Coastguard Worker    {
57*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyPoints:
58*8975f5c5SAndroid Build Coastguard Worker            return primCount;
59*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyLines:
60*8975f5c5SAndroid Build Coastguard Worker            return primCount * 2;
61*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyLineStrip:
62*8975f5c5SAndroid Build Coastguard Worker            return primCount * 2;
63*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyLineLoop:
64*8975f5c5SAndroid Build Coastguard Worker            return primCount * 2;
65*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyTriangles:
66*8975f5c5SAndroid Build Coastguard Worker            return primCount * 3;
67*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyTriangleStrip:
68*8975f5c5SAndroid Build Coastguard Worker            return primCount * 3;
69*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyTriangleFan:
70*8975f5c5SAndroid Build Coastguard Worker            return primCount * 3;
71*8975f5c5SAndroid Build Coastguard Worker        default:
72*8975f5c5SAndroid Build Coastguard Worker            ASSERT(false);
73*8975f5c5SAndroid Build Coastguard Worker            return 0;
74*8975f5c5SAndroid Build Coastguard Worker    }
75*8975f5c5SAndroid Build Coastguard Worker}
76*8975f5c5SAndroid Build Coastguard Worker
77*8975f5c5SAndroid Build Coastguard Workerstatic inline gl::PrimitiveMode getNewPrimitiveMode(const uint fixIndexBufferKey)
78*8975f5c5SAndroid Build Coastguard Worker{
79*8975f5c5SAndroid Build Coastguard Worker    const uint fixIndexBufferMode =
80*8975f5c5SAndroid Build Coastguard Worker        (fixIndexBufferKey >> MtlFixIndexBufferKeyModeShift) & MtlFixIndexBufferKeyModeMask;
81*8975f5c5SAndroid Build Coastguard Worker    switch (fixIndexBufferMode)
82*8975f5c5SAndroid Build Coastguard Worker    {
83*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyPoints:
84*8975f5c5SAndroid Build Coastguard Worker            return gl::PrimitiveMode::Points;
85*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyLines:
86*8975f5c5SAndroid Build Coastguard Worker            return gl::PrimitiveMode::Lines;
87*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyLineStrip:
88*8975f5c5SAndroid Build Coastguard Worker            return gl::PrimitiveMode::Lines;
89*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyLineLoop:
90*8975f5c5SAndroid Build Coastguard Worker            return gl::PrimitiveMode::Lines;
91*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyTriangles:
92*8975f5c5SAndroid Build Coastguard Worker            return gl::PrimitiveMode::Triangles;
93*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyTriangleStrip:
94*8975f5c5SAndroid Build Coastguard Worker            return gl::PrimitiveMode::Triangles;
95*8975f5c5SAndroid Build Coastguard Worker        case MtlFixIndexBufferKeyTriangleFan:
96*8975f5c5SAndroid Build Coastguard Worker            return gl::PrimitiveMode::Triangles;
97*8975f5c5SAndroid Build Coastguard Worker        default:
98*8975f5c5SAndroid Build Coastguard Worker            ASSERT(false);
99*8975f5c5SAndroid Build Coastguard Worker            return gl::PrimitiveMode::InvalidEnum;
100*8975f5c5SAndroid Build Coastguard Worker    }
101*8975f5c5SAndroid Build Coastguard Worker}
102*8975f5c5SAndroid Build Coastguard WorkerProvokingVertexHelper::ProvokingVertexHelper(ContextMtl *context) : mIndexBuffers(false)
103*8975f5c5SAndroid Build Coastguard Worker{
104*8975f5c5SAndroid Build Coastguard Worker    mIndexBuffers.initialize(context, kInitialIndexBufferSize, mtl::kIndexBufferOffsetAlignment, 0);
105*8975f5c5SAndroid Build Coastguard Worker}
106*8975f5c5SAndroid Build Coastguard Worker
107*8975f5c5SAndroid Build Coastguard Workervoid ProvokingVertexHelper::onDestroy(ContextMtl *context)
108*8975f5c5SAndroid Build Coastguard Worker{
109*8975f5c5SAndroid Build Coastguard Worker    mIndexBuffers.destroy(context);
110*8975f5c5SAndroid Build Coastguard Worker}
111*8975f5c5SAndroid Build Coastguard Worker
112*8975f5c5SAndroid Build Coastguard Workervoid ProvokingVertexHelper::releaseInFlightBuffers(ContextMtl *contextMtl)
113*8975f5c5SAndroid Build Coastguard Worker{
114*8975f5c5SAndroid Build Coastguard Worker    mIndexBuffers.releaseInFlightBuffers(contextMtl);
115*8975f5c5SAndroid Build Coastguard Worker}
116*8975f5c5SAndroid Build Coastguard Worker
117*8975f5c5SAndroid Build Coastguard Workerstatic uint buildIndexBufferKey(const mtl::ProvokingVertexComputePipelineDesc &pipelineDesc)
118*8975f5c5SAndroid Build Coastguard Worker{
119*8975f5c5SAndroid Build Coastguard Worker    uint indexBufferKey              = 0;
120*8975f5c5SAndroid Build Coastguard Worker    gl::DrawElementsType elementType = (gl::DrawElementsType)pipelineDesc.elementType;
121*8975f5c5SAndroid Build Coastguard Worker    bool doPrimPrestart              = pipelineDesc.primitiveRestartEnabled;
122*8975f5c5SAndroid Build Coastguard Worker    gl::PrimitiveMode primMode       = pipelineDesc.primitiveMode;
123*8975f5c5SAndroid Build Coastguard Worker    switch (elementType)
124*8975f5c5SAndroid Build Coastguard Worker    {
125*8975f5c5SAndroid Build Coastguard Worker        case gl::DrawElementsType::UnsignedShort:
126*8975f5c5SAndroid Build Coastguard Worker            indexBufferKey |= MtlFixIndexBufferKeyUint16 << MtlFixIndexBufferKeyInShift;
127*8975f5c5SAndroid Build Coastguard Worker            indexBufferKey |= MtlFixIndexBufferKeyUint16 << MtlFixIndexBufferKeyOutShift;
128*8975f5c5SAndroid Build Coastguard Worker            break;
129*8975f5c5SAndroid Build Coastguard Worker        case gl::DrawElementsType::UnsignedInt:
130*8975f5c5SAndroid Build Coastguard Worker            indexBufferKey |= MtlFixIndexBufferKeyUint32 << MtlFixIndexBufferKeyInShift;
131*8975f5c5SAndroid Build Coastguard Worker            indexBufferKey |= MtlFixIndexBufferKeyUint32 << MtlFixIndexBufferKeyOutShift;
132*8975f5c5SAndroid Build Coastguard Worker            break;
133*8975f5c5SAndroid Build Coastguard Worker        default:
134*8975f5c5SAndroid Build Coastguard Worker            ASSERT(false);  // Index type should only be short or int.
135*8975f5c5SAndroid Build Coastguard Worker            break;
136*8975f5c5SAndroid Build Coastguard Worker    }
137*8975f5c5SAndroid Build Coastguard Worker    indexBufferKey |= (uint)primMode << MtlFixIndexBufferKeyModeShift;
138*8975f5c5SAndroid Build Coastguard Worker    indexBufferKey |= doPrimPrestart ? MtlFixIndexBufferKeyPrimRestart : 0;
139*8975f5c5SAndroid Build Coastguard Worker    // We only rewrite indices if we're switching the provoking vertex mode.
140*8975f5c5SAndroid Build Coastguard Worker    indexBufferKey |= MtlFixIndexBufferKeyProvokingVertexLast;
141*8975f5c5SAndroid Build Coastguard Worker    return indexBufferKey;
142*8975f5c5SAndroid Build Coastguard Worker}
143*8975f5c5SAndroid Build Coastguard Worker
144*8975f5c5SAndroid Build Coastguard Workerangle::Result ProvokingVertexHelper::getComputePipleineState(
145*8975f5c5SAndroid Build Coastguard Worker    ContextMtl *context,
146*8975f5c5SAndroid Build Coastguard Worker    const mtl::ProvokingVertexComputePipelineDesc &desc,
147*8975f5c5SAndroid Build Coastguard Worker    mtl::AutoObjCPtr<id<MTLComputePipelineState>> *outComputePipeline)
148*8975f5c5SAndroid Build Coastguard Worker{
149*8975f5c5SAndroid Build Coastguard Worker    auto iter = mComputeFunctions.find(desc);
150*8975f5c5SAndroid Build Coastguard Worker    if (iter != mComputeFunctions.end())
151*8975f5c5SAndroid Build Coastguard Worker    {
152*8975f5c5SAndroid Build Coastguard Worker        return context->getPipelineCache().getComputePipeline(context, iter->second,
153*8975f5c5SAndroid Build Coastguard Worker                                                              outComputePipeline);
154*8975f5c5SAndroid Build Coastguard Worker    }
155*8975f5c5SAndroid Build Coastguard Worker
156*8975f5c5SAndroid Build Coastguard Worker    id<MTLLibrary> provokingVertexLibrary = context->getDisplay()->getDefaultShadersLib();
157*8975f5c5SAndroid Build Coastguard Worker    uint indexBufferKey                   = buildIndexBufferKey(desc);
158*8975f5c5SAndroid Build Coastguard Worker    auto fcValues = mtl::adoptObjCObj([[MTLFunctionConstantValues alloc] init]);
159*8975f5c5SAndroid Build Coastguard Worker    [fcValues setConstantValue:&indexBufferKey type:MTLDataTypeUInt withName:@"fixIndexBufferKey"];
160*8975f5c5SAndroid Build Coastguard Worker
161*8975f5c5SAndroid Build Coastguard Worker    mtl::AutoObjCPtr<id<MTLFunction>> computeShader;
162*8975f5c5SAndroid Build Coastguard Worker    if (desc.generateIndices)
163*8975f5c5SAndroid Build Coastguard Worker    {
164*8975f5c5SAndroid Build Coastguard Worker        ANGLE_TRY(CreateMslShader(context, provokingVertexLibrary, @"genIndexBuffer",
165*8975f5c5SAndroid Build Coastguard Worker                                  fcValues.get(), &computeShader));
166*8975f5c5SAndroid Build Coastguard Worker    }
167*8975f5c5SAndroid Build Coastguard Worker    else
168*8975f5c5SAndroid Build Coastguard Worker    {
169*8975f5c5SAndroid Build Coastguard Worker        ANGLE_TRY(CreateMslShader(context, provokingVertexLibrary, @"fixIndexBuffer",
170*8975f5c5SAndroid Build Coastguard Worker                                  fcValues.get(), &computeShader));
171*8975f5c5SAndroid Build Coastguard Worker    }
172*8975f5c5SAndroid Build Coastguard Worker    mComputeFunctions[desc] = computeShader;
173*8975f5c5SAndroid Build Coastguard Worker
174*8975f5c5SAndroid Build Coastguard Worker    return context->getPipelineCache().getComputePipeline(context, computeShader,
175*8975f5c5SAndroid Build Coastguard Worker                                                          outComputePipeline);
176*8975f5c5SAndroid Build Coastguard Worker}
177*8975f5c5SAndroid Build Coastguard Worker
178*8975f5c5SAndroid Build Coastguard Workerangle::Result ProvokingVertexHelper::prepareCommandEncoderForDescriptor(
179*8975f5c5SAndroid Build Coastguard Worker    ContextMtl *context,
180*8975f5c5SAndroid Build Coastguard Worker    mtl::ComputeCommandEncoder *encoder,
181*8975f5c5SAndroid Build Coastguard Worker    mtl::ProvokingVertexComputePipelineDesc desc)
182*8975f5c5SAndroid Build Coastguard Worker{
183*8975f5c5SAndroid Build Coastguard Worker    mtl::AutoObjCPtr<id<MTLComputePipelineState>> pipelineState;
184*8975f5c5SAndroid Build Coastguard Worker    ANGLE_TRY(getComputePipleineState(context, desc, &pipelineState));
185*8975f5c5SAndroid Build Coastguard Worker
186*8975f5c5SAndroid Build Coastguard Worker    encoder->setComputePipelineState(pipelineState);
187*8975f5c5SAndroid Build Coastguard Worker
188*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
189*8975f5c5SAndroid Build Coastguard Worker}
190*8975f5c5SAndroid Build Coastguard Worker
191*8975f5c5SAndroid Build Coastguard Workerangle::Result ProvokingVertexHelper::preconditionIndexBuffer(ContextMtl *context,
192*8975f5c5SAndroid Build Coastguard Worker                                                             mtl::BufferRef indexBuffer,
193*8975f5c5SAndroid Build Coastguard Worker                                                             size_t indexCount,
194*8975f5c5SAndroid Build Coastguard Worker                                                             size_t indexOffset,
195*8975f5c5SAndroid Build Coastguard Worker                                                             bool primitiveRestartEnabled,
196*8975f5c5SAndroid Build Coastguard Worker                                                             gl::PrimitiveMode primitiveMode,
197*8975f5c5SAndroid Build Coastguard Worker                                                             gl::DrawElementsType elementsType,
198*8975f5c5SAndroid Build Coastguard Worker                                                             size_t &outIndexCount,
199*8975f5c5SAndroid Build Coastguard Worker                                                             size_t &outIndexOffset,
200*8975f5c5SAndroid Build Coastguard Worker                                                             gl::PrimitiveMode &outPrimitiveMode,
201*8975f5c5SAndroid Build Coastguard Worker                                                             mtl::BufferRef &outNewBuffer)
202*8975f5c5SAndroid Build Coastguard Worker{
203*8975f5c5SAndroid Build Coastguard Worker    // Get specialized program
204*8975f5c5SAndroid Build Coastguard Worker    // Upload index buffer
205*8975f5c5SAndroid Build Coastguard Worker    // dispatch per-primitive?
206*8975f5c5SAndroid Build Coastguard Worker    mtl::ProvokingVertexComputePipelineDesc pipelineDesc;
207*8975f5c5SAndroid Build Coastguard Worker    pipelineDesc.elementType             = (uint8_t)elementsType;
208*8975f5c5SAndroid Build Coastguard Worker    pipelineDesc.primitiveMode           = primitiveMode;
209*8975f5c5SAndroid Build Coastguard Worker    pipelineDesc.primitiveRestartEnabled = primitiveRestartEnabled;
210*8975f5c5SAndroid Build Coastguard Worker    pipelineDesc.generateIndices         = false;
211*8975f5c5SAndroid Build Coastguard Worker    uint indexBufferKey                  = buildIndexBufferKey(pipelineDesc);
212*8975f5c5SAndroid Build Coastguard Worker    uint primCount     = primCountForIndexCount(indexBufferKey, (uint32_t)indexCount);
213*8975f5c5SAndroid Build Coastguard Worker    uint newIndexCount = indexCountForPrimCount(indexBufferKey, primCount);
214*8975f5c5SAndroid Build Coastguard Worker    size_t indexSize   = gl::GetDrawElementsTypeSize(elementsType);
215*8975f5c5SAndroid Build Coastguard Worker    size_t newOffset   = 0;
216*8975f5c5SAndroid Build Coastguard Worker    mtl::BufferRef newBuffer;
217*8975f5c5SAndroid Build Coastguard Worker    ANGLE_TRY(mIndexBuffers.allocate(context, newIndexCount * indexSize + indexOffset, nullptr,
218*8975f5c5SAndroid Build Coastguard Worker                                     &newBuffer, &newOffset));
219*8975f5c5SAndroid Build Coastguard Worker    uint indexCountEncoded     = (uint)indexCount;
220*8975f5c5SAndroid Build Coastguard Worker    auto threadsPerThreadgroup = MTLSizeMake(MIN(primCount, 64u), 1, 1);
221*8975f5c5SAndroid Build Coastguard Worker
222*8975f5c5SAndroid Build Coastguard Worker    mtl::ComputeCommandEncoder *encoder =
223*8975f5c5SAndroid Build Coastguard Worker        context->getComputeCommandEncoderWithoutEndingRenderEncoder();
224*8975f5c5SAndroid Build Coastguard Worker    ANGLE_TRY(prepareCommandEncoderForDescriptor(context, encoder, pipelineDesc));
225*8975f5c5SAndroid Build Coastguard Worker    encoder->setBuffer(indexBuffer, static_cast<uint32_t>(indexOffset), 0);
226*8975f5c5SAndroid Build Coastguard Worker    encoder->setBufferForWrite(
227*8975f5c5SAndroid Build Coastguard Worker        newBuffer, static_cast<uint32_t>(indexOffset) + static_cast<uint32_t>(newOffset), 1);
228*8975f5c5SAndroid Build Coastguard Worker    encoder->setData(&indexCountEncoded, 2);
229*8975f5c5SAndroid Build Coastguard Worker    encoder->setData(&primCount, 3);
230*8975f5c5SAndroid Build Coastguard Worker    encoder->dispatch(
231*8975f5c5SAndroid Build Coastguard Worker        MTLSizeMake((primCount + threadsPerThreadgroup.width - 1) / threadsPerThreadgroup.width, 1,
232*8975f5c5SAndroid Build Coastguard Worker                    1),
233*8975f5c5SAndroid Build Coastguard Worker        threadsPerThreadgroup);
234*8975f5c5SAndroid Build Coastguard Worker    outIndexCount    = newIndexCount;
235*8975f5c5SAndroid Build Coastguard Worker    outIndexOffset   = newOffset;
236*8975f5c5SAndroid Build Coastguard Worker    outPrimitiveMode = getNewPrimitiveMode(indexBufferKey);
237*8975f5c5SAndroid Build Coastguard Worker    outNewBuffer     = newBuffer;
238*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
239*8975f5c5SAndroid Build Coastguard Worker}
240*8975f5c5SAndroid Build Coastguard Worker
241*8975f5c5SAndroid Build Coastguard Workerangle::Result ProvokingVertexHelper::generateIndexBuffer(ContextMtl *context,
242*8975f5c5SAndroid Build Coastguard Worker                                                         size_t first,
243*8975f5c5SAndroid Build Coastguard Worker                                                         size_t indexCount,
244*8975f5c5SAndroid Build Coastguard Worker                                                         gl::PrimitiveMode primitiveMode,
245*8975f5c5SAndroid Build Coastguard Worker                                                         gl::DrawElementsType elementsType,
246*8975f5c5SAndroid Build Coastguard Worker                                                         size_t &outIndexCount,
247*8975f5c5SAndroid Build Coastguard Worker                                                         size_t &outIndexOffset,
248*8975f5c5SAndroid Build Coastguard Worker                                                         gl::PrimitiveMode &outPrimitiveMode,
249*8975f5c5SAndroid Build Coastguard Worker                                                         mtl::BufferRef &outNewBuffer)
250*8975f5c5SAndroid Build Coastguard Worker{
251*8975f5c5SAndroid Build Coastguard Worker    // Get specialized program
252*8975f5c5SAndroid Build Coastguard Worker    // Upload index buffer
253*8975f5c5SAndroid Build Coastguard Worker    // dispatch per-primitive?
254*8975f5c5SAndroid Build Coastguard Worker    mtl::ProvokingVertexComputePipelineDesc pipelineDesc;
255*8975f5c5SAndroid Build Coastguard Worker    pipelineDesc.elementType             = (uint8_t)elementsType;
256*8975f5c5SAndroid Build Coastguard Worker    pipelineDesc.primitiveMode           = primitiveMode;
257*8975f5c5SAndroid Build Coastguard Worker    pipelineDesc.primitiveRestartEnabled = false;
258*8975f5c5SAndroid Build Coastguard Worker    pipelineDesc.generateIndices         = true;
259*8975f5c5SAndroid Build Coastguard Worker    uint indexBufferKey                  = buildIndexBufferKey(pipelineDesc);
260*8975f5c5SAndroid Build Coastguard Worker    uint primCount        = primCountForIndexCount(indexBufferKey, (uint32_t)indexCount);
261*8975f5c5SAndroid Build Coastguard Worker    uint newIndexCount    = indexCountForPrimCount(indexBufferKey, primCount);
262*8975f5c5SAndroid Build Coastguard Worker    size_t indexSize      = gl::GetDrawElementsTypeSize(elementsType);
263*8975f5c5SAndroid Build Coastguard Worker    size_t newIndexOffset = 0;
264*8975f5c5SAndroid Build Coastguard Worker    mtl::BufferRef newBuffer;
265*8975f5c5SAndroid Build Coastguard Worker    ANGLE_TRY(mIndexBuffers.allocate(context, newIndexCount * indexSize, nullptr, &newBuffer,
266*8975f5c5SAndroid Build Coastguard Worker                                     &newIndexOffset));
267*8975f5c5SAndroid Build Coastguard Worker    uint indexCountEncoded     = static_cast<uint>(indexCount);
268*8975f5c5SAndroid Build Coastguard Worker    uint firstVertexEncoded    = static_cast<uint>(first);
269*8975f5c5SAndroid Build Coastguard Worker    uint indexOffsetEncoded    = static_cast<uint>(newIndexOffset);
270*8975f5c5SAndroid Build Coastguard Worker    auto threadsPerThreadgroup = MTLSizeMake(MIN(primCount, 64u), 1, 1);
271*8975f5c5SAndroid Build Coastguard Worker
272*8975f5c5SAndroid Build Coastguard Worker    mtl::ComputeCommandEncoder *encoder =
273*8975f5c5SAndroid Build Coastguard Worker        context->getComputeCommandEncoderWithoutEndingRenderEncoder();
274*8975f5c5SAndroid Build Coastguard Worker    ANGLE_TRY(prepareCommandEncoderForDescriptor(context, encoder, pipelineDesc));
275*8975f5c5SAndroid Build Coastguard Worker    encoder->setBufferForWrite(newBuffer, indexOffsetEncoded, 1);
276*8975f5c5SAndroid Build Coastguard Worker    encoder->setData(indexCountEncoded, 2);
277*8975f5c5SAndroid Build Coastguard Worker    encoder->setData(primCount, 3);
278*8975f5c5SAndroid Build Coastguard Worker    encoder->setData(firstVertexEncoded, 4);
279*8975f5c5SAndroid Build Coastguard Worker    encoder->dispatch(
280*8975f5c5SAndroid Build Coastguard Worker        MTLSizeMake((primCount + threadsPerThreadgroup.width - 1) / threadsPerThreadgroup.width, 1,
281*8975f5c5SAndroid Build Coastguard Worker                    1),
282*8975f5c5SAndroid Build Coastguard Worker        threadsPerThreadgroup);
283*8975f5c5SAndroid Build Coastguard Worker    outIndexCount    = newIndexCount;
284*8975f5c5SAndroid Build Coastguard Worker    outIndexOffset   = newIndexOffset;
285*8975f5c5SAndroid Build Coastguard Worker    outPrimitiveMode = getNewPrimitiveMode(indexBufferKey);
286*8975f5c5SAndroid Build Coastguard Worker    outNewBuffer     = newBuffer;
287*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
288*8975f5c5SAndroid Build Coastguard Worker}
289*8975f5c5SAndroid Build Coastguard Worker
290*8975f5c5SAndroid Build Coastguard Worker}  // namespace rx
291