xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/metal/ProgramExecutableMtl.mm (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker//
2*8975f5c5SAndroid Build Coastguard Worker// Copyright 2023 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// ProgramExecutableMtl.cpp: Implementation of ProgramExecutableMtl.
7*8975f5c5SAndroid Build Coastguard Worker
8*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/ProgramExecutableMtl.h"
9*8975f5c5SAndroid Build Coastguard Worker
10*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/BufferMtl.h"
11*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/ContextMtl.h"
12*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/TextureMtl.h"
13*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/blocklayoutMetal.h"
14*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/renderermtl_utils.h"
15*8975f5c5SAndroid Build Coastguard Worker
16*8975f5c5SAndroid Build Coastguard Workernamespace rx
17*8975f5c5SAndroid Build Coastguard Worker{
18*8975f5c5SAndroid Build Coastguard Workernamespace
19*8975f5c5SAndroid Build Coastguard Worker{
20*8975f5c5SAndroid Build Coastguard Worker#define SHADER_ENTRY_NAME @"main0"
21*8975f5c5SAndroid Build Coastguard Worker
22*8975f5c5SAndroid Build Coastguard Workerbool CompareBlockInfo(const sh::BlockMemberInfo &a, const sh::BlockMemberInfo &b)
23*8975f5c5SAndroid Build Coastguard Worker{
24*8975f5c5SAndroid Build Coastguard Worker    return a.offset < b.offset;
25*8975f5c5SAndroid Build Coastguard Worker}
26*8975f5c5SAndroid Build Coastguard Worker
27*8975f5c5SAndroid Build Coastguard Workersize_t GetAlignmentOfUniformGroup(sh::BlockLayoutMap *blockLayoutMap)
28*8975f5c5SAndroid Build Coastguard Worker{
29*8975f5c5SAndroid Build Coastguard Worker    size_t align = 1;
30*8975f5c5SAndroid Build Coastguard Worker    for (auto layoutIter = blockLayoutMap->begin(); layoutIter != blockLayoutMap->end();
31*8975f5c5SAndroid Build Coastguard Worker         ++layoutIter)
32*8975f5c5SAndroid Build Coastguard Worker    {
33*8975f5c5SAndroid Build Coastguard Worker        align = std::max(mtl::GetMetalAlignmentForGLType(layoutIter->second.type), align);
34*8975f5c5SAndroid Build Coastguard Worker    }
35*8975f5c5SAndroid Build Coastguard Worker    return align;
36*8975f5c5SAndroid Build Coastguard Worker}
37*8975f5c5SAndroid Build Coastguard Worker
38*8975f5c5SAndroid Build Coastguard Workervoid InitDefaultUniformBlock(const std::vector<sh::Uniform> &uniforms,
39*8975f5c5SAndroid Build Coastguard Worker                             sh::BlockLayoutMap *blockLayoutMapOut,
40*8975f5c5SAndroid Build Coastguard Worker                             size_t *blockSizeOut)
41*8975f5c5SAndroid Build Coastguard Worker{
42*8975f5c5SAndroid Build Coastguard Worker    if (uniforms.empty())
43*8975f5c5SAndroid Build Coastguard Worker    {
44*8975f5c5SAndroid Build Coastguard Worker        *blockSizeOut = 0;
45*8975f5c5SAndroid Build Coastguard Worker        return;
46*8975f5c5SAndroid Build Coastguard Worker    }
47*8975f5c5SAndroid Build Coastguard Worker
48*8975f5c5SAndroid Build Coastguard Worker    mtl::BlockLayoutEncoderMTL blockEncoder;
49*8975f5c5SAndroid Build Coastguard Worker    sh::GetActiveUniformBlockInfo(uniforms, "", &blockEncoder, blockLayoutMapOut);
50*8975f5c5SAndroid Build Coastguard Worker    size_t blockAlign = GetAlignmentOfUniformGroup(blockLayoutMapOut);
51*8975f5c5SAndroid Build Coastguard Worker    size_t blockSize  = roundUp(blockEncoder.getCurrentOffset(), blockAlign);
52*8975f5c5SAndroid Build Coastguard Worker
53*8975f5c5SAndroid Build Coastguard Worker    // TODO(jmadill): I think we still need a valid block for the pipeline even if zero sized.
54*8975f5c5SAndroid Build Coastguard Worker    if (blockSize == 0)
55*8975f5c5SAndroid Build Coastguard Worker    {
56*8975f5c5SAndroid Build Coastguard Worker        *blockSizeOut = 0;
57*8975f5c5SAndroid Build Coastguard Worker        return;
58*8975f5c5SAndroid Build Coastguard Worker    }
59*8975f5c5SAndroid Build Coastguard Worker
60*8975f5c5SAndroid Build Coastguard Worker    *blockSizeOut = blockSize;
61*8975f5c5SAndroid Build Coastguard Worker    return;
62*8975f5c5SAndroid Build Coastguard Worker}
63*8975f5c5SAndroid Build Coastguard Worker
64*8975f5c5SAndroid Build Coastguard Workertemplate <typename T>
65*8975f5c5SAndroid Build Coastguard Workerclass [[nodiscard]] ScopedAutoClearVector
66*8975f5c5SAndroid Build Coastguard Worker{
67*8975f5c5SAndroid Build Coastguard Worker  public:
68*8975f5c5SAndroid Build Coastguard Worker    ScopedAutoClearVector(std::vector<T> *array) : mArray(*array) {}
69*8975f5c5SAndroid Build Coastguard Worker    ~ScopedAutoClearVector() { mArray.clear(); }
70*8975f5c5SAndroid Build Coastguard Worker
71*8975f5c5SAndroid Build Coastguard Worker  private:
72*8975f5c5SAndroid Build Coastguard Worker    std::vector<T> &mArray;
73*8975f5c5SAndroid Build Coastguard Worker};
74*8975f5c5SAndroid Build Coastguard Worker
75*8975f5c5SAndroid Build Coastguard Workerinline void memcpy_guarded(void *dst, const void *src, const void *maxSrcPtr, size_t size)
76*8975f5c5SAndroid Build Coastguard Worker{
77*8975f5c5SAndroid Build Coastguard Worker    size_t bytesAvailable = maxSrcPtr > src ? (const uint8_t *)maxSrcPtr - (const uint8_t *)src : 0;
78*8975f5c5SAndroid Build Coastguard Worker    size_t bytesToCopy    = std::min(size, bytesAvailable);
79*8975f5c5SAndroid Build Coastguard Worker    size_t bytesToZero    = size - bytesToCopy;
80*8975f5c5SAndroid Build Coastguard Worker
81*8975f5c5SAndroid Build Coastguard Worker    if (bytesToCopy)
82*8975f5c5SAndroid Build Coastguard Worker        memcpy(dst, src, bytesToCopy);
83*8975f5c5SAndroid Build Coastguard Worker    if (bytesToZero)
84*8975f5c5SAndroid Build Coastguard Worker        memset((uint8_t *)dst + bytesToCopy, 0, bytesToZero);
85*8975f5c5SAndroid Build Coastguard Worker}
86*8975f5c5SAndroid Build Coastguard Worker
87*8975f5c5SAndroid Build Coastguard Worker// Copy matrix one column at a time
88*8975f5c5SAndroid Build Coastguard Workerinline void copy_matrix(void *dst,
89*8975f5c5SAndroid Build Coastguard Worker                        const void *src,
90*8975f5c5SAndroid Build Coastguard Worker                        const void *maxSrcPtr,
91*8975f5c5SAndroid Build Coastguard Worker                        size_t srcStride,
92*8975f5c5SAndroid Build Coastguard Worker                        size_t dstStride,
93*8975f5c5SAndroid Build Coastguard Worker                        GLenum type)
94*8975f5c5SAndroid Build Coastguard Worker{
95*8975f5c5SAndroid Build Coastguard Worker    size_t elemSize      = mtl::GetMetalSizeForGLType(gl::VariableComponentType(type));
96*8975f5c5SAndroid Build Coastguard Worker    const size_t dstRows = gl::VariableRowCount(type);
97*8975f5c5SAndroid Build Coastguard Worker    const size_t dstCols = gl::VariableColumnCount(type);
98*8975f5c5SAndroid Build Coastguard Worker
99*8975f5c5SAndroid Build Coastguard Worker    for (size_t col = 0; col < dstCols; col++)
100*8975f5c5SAndroid Build Coastguard Worker    {
101*8975f5c5SAndroid Build Coastguard Worker        size_t srcOffset = col * srcStride;
102*8975f5c5SAndroid Build Coastguard Worker        memcpy_guarded(((uint8_t *)dst) + dstStride * col, (const uint8_t *)src + srcOffset,
103*8975f5c5SAndroid Build Coastguard Worker                       maxSrcPtr, elemSize * dstRows);
104*8975f5c5SAndroid Build Coastguard Worker    }
105*8975f5c5SAndroid Build Coastguard Worker}
106*8975f5c5SAndroid Build Coastguard Worker
107*8975f5c5SAndroid Build Coastguard Worker// Copy matrix one element at a time to transpose.
108*8975f5c5SAndroid Build Coastguard Workerinline void copy_matrix_row_major(void *dst,
109*8975f5c5SAndroid Build Coastguard Worker                                  const void *src,
110*8975f5c5SAndroid Build Coastguard Worker                                  const void *maxSrcPtr,
111*8975f5c5SAndroid Build Coastguard Worker                                  size_t srcStride,
112*8975f5c5SAndroid Build Coastguard Worker                                  size_t dstStride,
113*8975f5c5SAndroid Build Coastguard Worker                                  GLenum type)
114*8975f5c5SAndroid Build Coastguard Worker{
115*8975f5c5SAndroid Build Coastguard Worker    size_t elemSize      = mtl::GetMetalSizeForGLType(gl::VariableComponentType(type));
116*8975f5c5SAndroid Build Coastguard Worker    const size_t dstRows = gl::VariableRowCount(type);
117*8975f5c5SAndroid Build Coastguard Worker    const size_t dstCols = gl::VariableColumnCount(type);
118*8975f5c5SAndroid Build Coastguard Worker
119*8975f5c5SAndroid Build Coastguard Worker    for (size_t col = 0; col < dstCols; col++)
120*8975f5c5SAndroid Build Coastguard Worker    {
121*8975f5c5SAndroid Build Coastguard Worker        for (size_t row = 0; row < dstRows; row++)
122*8975f5c5SAndroid Build Coastguard Worker        {
123*8975f5c5SAndroid Build Coastguard Worker            size_t srcOffset = row * srcStride + col * elemSize;
124*8975f5c5SAndroid Build Coastguard Worker            memcpy_guarded((uint8_t *)dst + dstStride * col + row * elemSize,
125*8975f5c5SAndroid Build Coastguard Worker                           (const uint8_t *)src + srcOffset, maxSrcPtr, elemSize);
126*8975f5c5SAndroid Build Coastguard Worker        }
127*8975f5c5SAndroid Build Coastguard Worker    }
128*8975f5c5SAndroid Build Coastguard Worker}
129*8975f5c5SAndroid Build Coastguard Worker// TODO(angleproject:7979) Upgrade ANGLE Uniform buffer remapper to compute shaders
130*8975f5c5SAndroid Build Coastguard Workerangle::Result ConvertUniformBufferData(ContextMtl *contextMtl,
131*8975f5c5SAndroid Build Coastguard Worker                                       const UBOConversionInfo &blockConversionInfo,
132*8975f5c5SAndroid Build Coastguard Worker                                       mtl::BufferPool *dynamicBuffer,
133*8975f5c5SAndroid Build Coastguard Worker                                       const uint8_t *sourceData,
134*8975f5c5SAndroid Build Coastguard Worker                                       size_t sizeToCopy,
135*8975f5c5SAndroid Build Coastguard Worker                                       mtl::BufferRef *bufferOut,
136*8975f5c5SAndroid Build Coastguard Worker                                       size_t *bufferOffsetOut)
137*8975f5c5SAndroid Build Coastguard Worker{
138*8975f5c5SAndroid Build Coastguard Worker    uint8_t *dst             = nullptr;
139*8975f5c5SAndroid Build Coastguard Worker    const uint8_t *maxSrcPtr = sourceData + sizeToCopy;
140*8975f5c5SAndroid Build Coastguard Worker    dynamicBuffer->releaseInFlightBuffers(contextMtl);
141*8975f5c5SAndroid Build Coastguard Worker
142*8975f5c5SAndroid Build Coastguard Worker    // When converting a UBO buffer, we convert all of the data
143*8975f5c5SAndroid Build Coastguard Worker    // supplied in a buffer at once (sizeToCopy = bufferMtl->size() - initial offset).
144*8975f5c5SAndroid Build Coastguard Worker    // It's possible that a buffer could represent multiple instances of
145*8975f5c5SAndroid Build Coastguard Worker    // a uniform block, so we loop over the number of block conversions we intend
146*8975f5c5SAndroid Build Coastguard Worker    // to do.
147*8975f5c5SAndroid Build Coastguard Worker    size_t numBlocksToCopy =
148*8975f5c5SAndroid Build Coastguard Worker        (sizeToCopy + blockConversionInfo.stdSize() - 1) / blockConversionInfo.stdSize();
149*8975f5c5SAndroid Build Coastguard Worker    size_t bytesToAllocate = numBlocksToCopy * blockConversionInfo.metalSize();
150*8975f5c5SAndroid Build Coastguard Worker    ANGLE_TRY(dynamicBuffer->allocate(contextMtl, bytesToAllocate, &dst, bufferOut, bufferOffsetOut,
151*8975f5c5SAndroid Build Coastguard Worker                                      nullptr));
152*8975f5c5SAndroid Build Coastguard Worker
153*8975f5c5SAndroid Build Coastguard Worker    const std::vector<sh::BlockMemberInfo> &stdConversions = blockConversionInfo.stdInfo();
154*8975f5c5SAndroid Build Coastguard Worker    const std::vector<sh::BlockMemberInfo> &mtlConversions = blockConversionInfo.metalInfo();
155*8975f5c5SAndroid Build Coastguard Worker    for (size_t i = 0; i < numBlocksToCopy; ++i)
156*8975f5c5SAndroid Build Coastguard Worker    {
157*8975f5c5SAndroid Build Coastguard Worker        auto stdIterator = stdConversions.begin();
158*8975f5c5SAndroid Build Coastguard Worker        auto mtlIterator = mtlConversions.begin();
159*8975f5c5SAndroid Build Coastguard Worker
160*8975f5c5SAndroid Build Coastguard Worker        while (stdIterator != stdConversions.end())
161*8975f5c5SAndroid Build Coastguard Worker        {
162*8975f5c5SAndroid Build Coastguard Worker            for (int arraySize = 0; arraySize < stdIterator->arraySize; ++arraySize)
163*8975f5c5SAndroid Build Coastguard Worker            {
164*8975f5c5SAndroid Build Coastguard Worker                // For every entry in an array, calculate the offset based off of the
165*8975f5c5SAndroid Build Coastguard Worker                // array element size.
166*8975f5c5SAndroid Build Coastguard Worker
167*8975f5c5SAndroid Build Coastguard Worker                // Offset of a single entry is
168*8975f5c5SAndroid Build Coastguard Worker                // blockIndex*blockSize + arrayOffset*arraySize + offset of field in base struct.
169*8975f5c5SAndroid Build Coastguard Worker                // Fields are copied per block, per member, per array entry of member.
170*8975f5c5SAndroid Build Coastguard Worker
171*8975f5c5SAndroid Build Coastguard Worker                size_t stdArrayOffset = stdIterator->arrayStride * arraySize;
172*8975f5c5SAndroid Build Coastguard Worker                size_t mtlArrayOffset = mtlIterator->arrayStride * arraySize;
173*8975f5c5SAndroid Build Coastguard Worker
174*8975f5c5SAndroid Build Coastguard Worker                if (gl::IsMatrixType(mtlIterator->type))
175*8975f5c5SAndroid Build Coastguard Worker                {
176*8975f5c5SAndroid Build Coastguard Worker
177*8975f5c5SAndroid Build Coastguard Worker                    void *dstMat = dst + mtlIterator->offset + mtlArrayOffset +
178*8975f5c5SAndroid Build Coastguard Worker                                   blockConversionInfo.metalSize() * i;
179*8975f5c5SAndroid Build Coastguard Worker                    const void *srcMat = sourceData + stdIterator->offset + stdArrayOffset +
180*8975f5c5SAndroid Build Coastguard Worker                                         blockConversionInfo.stdSize() * i;
181*8975f5c5SAndroid Build Coastguard Worker                    // Transpose matricies into column major order, if they're row major encoded.
182*8975f5c5SAndroid Build Coastguard Worker                    if (stdIterator->isRowMajorMatrix)
183*8975f5c5SAndroid Build Coastguard Worker                    {
184*8975f5c5SAndroid Build Coastguard Worker                        copy_matrix_row_major(dstMat, srcMat, maxSrcPtr, stdIterator->matrixStride,
185*8975f5c5SAndroid Build Coastguard Worker                                              mtlIterator->matrixStride, mtlIterator->type);
186*8975f5c5SAndroid Build Coastguard Worker                    }
187*8975f5c5SAndroid Build Coastguard Worker                    else
188*8975f5c5SAndroid Build Coastguard Worker                    {
189*8975f5c5SAndroid Build Coastguard Worker                        copy_matrix(dstMat, srcMat, maxSrcPtr, stdIterator->matrixStride,
190*8975f5c5SAndroid Build Coastguard Worker                                    mtlIterator->matrixStride, mtlIterator->type);
191*8975f5c5SAndroid Build Coastguard Worker                    }
192*8975f5c5SAndroid Build Coastguard Worker                }
193*8975f5c5SAndroid Build Coastguard Worker                // Compress bool from four bytes to one byte because bool values in GLSL
194*8975f5c5SAndroid Build Coastguard Worker                // are uint-sized: ES 3.0 Section 2.12.6.3 "Uniform Buffer Object Storage".
195*8975f5c5SAndroid Build Coastguard Worker                // Bools in metal are byte-sized. (Metal shading language spec Table 2.2)
196*8975f5c5SAndroid Build Coastguard Worker                else if (gl::VariableComponentType(mtlIterator->type) == GL_BOOL)
197*8975f5c5SAndroid Build Coastguard Worker                {
198*8975f5c5SAndroid Build Coastguard Worker                    for (int boolCol = 0; boolCol < gl::VariableComponentCount(mtlIterator->type);
199*8975f5c5SAndroid Build Coastguard Worker                         boolCol++)
200*8975f5c5SAndroid Build Coastguard Worker                    {
201*8975f5c5SAndroid Build Coastguard Worker                        const uint8_t *srcBool =
202*8975f5c5SAndroid Build Coastguard Worker                            (sourceData + stdIterator->offset + stdArrayOffset +
203*8975f5c5SAndroid Build Coastguard Worker                             blockConversionInfo.stdSize() * i +
204*8975f5c5SAndroid Build Coastguard Worker                             gl::VariableComponentSize(GL_BOOL) * boolCol);
205*8975f5c5SAndroid Build Coastguard Worker                        unsigned int srcValue =
206*8975f5c5SAndroid Build Coastguard Worker                            srcBool < maxSrcPtr ? *((unsigned int *)(srcBool)) : 0;
207*8975f5c5SAndroid Build Coastguard Worker                        uint8_t *dstBool = dst + mtlIterator->offset + mtlArrayOffset +
208*8975f5c5SAndroid Build Coastguard Worker                                           blockConversionInfo.metalSize() * i +
209*8975f5c5SAndroid Build Coastguard Worker                                           sizeof(bool) * boolCol;
210*8975f5c5SAndroid Build Coastguard Worker                        *dstBool = (srcValue != 0);
211*8975f5c5SAndroid Build Coastguard Worker                    }
212*8975f5c5SAndroid Build Coastguard Worker                }
213*8975f5c5SAndroid Build Coastguard Worker                else
214*8975f5c5SAndroid Build Coastguard Worker                {
215*8975f5c5SAndroid Build Coastguard Worker                    memcpy_guarded(dst + mtlIterator->offset + mtlArrayOffset +
216*8975f5c5SAndroid Build Coastguard Worker                                       blockConversionInfo.metalSize() * i,
217*8975f5c5SAndroid Build Coastguard Worker                                   sourceData + stdIterator->offset + stdArrayOffset +
218*8975f5c5SAndroid Build Coastguard Worker                                       blockConversionInfo.stdSize() * i,
219*8975f5c5SAndroid Build Coastguard Worker                                   maxSrcPtr, mtl::GetMetalSizeForGLType(mtlIterator->type));
220*8975f5c5SAndroid Build Coastguard Worker                }
221*8975f5c5SAndroid Build Coastguard Worker            }
222*8975f5c5SAndroid Build Coastguard Worker            ++stdIterator;
223*8975f5c5SAndroid Build Coastguard Worker            ++mtlIterator;
224*8975f5c5SAndroid Build Coastguard Worker        }
225*8975f5c5SAndroid Build Coastguard Worker    }
226*8975f5c5SAndroid Build Coastguard Worker
227*8975f5c5SAndroid Build Coastguard Worker    ANGLE_TRY(dynamicBuffer->commit(contextMtl));
228*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
229*8975f5c5SAndroid Build Coastguard Worker}
230*8975f5c5SAndroid Build Coastguard Worker
231*8975f5c5SAndroid Build Coastguard Workerconstexpr size_t PipelineParametersToFragmentShaderVariantIndex(bool multisampledRendering,
232*8975f5c5SAndroid Build Coastguard Worker                                                                bool allowFragDepthWrite)
233*8975f5c5SAndroid Build Coastguard Worker{
234*8975f5c5SAndroid Build Coastguard Worker    const size_t index = (allowFragDepthWrite << 1) | multisampledRendering;
235*8975f5c5SAndroid Build Coastguard Worker    ASSERT(index < kFragmentShaderVariants);
236*8975f5c5SAndroid Build Coastguard Worker    return index;
237*8975f5c5SAndroid Build Coastguard Worker}
238*8975f5c5SAndroid Build Coastguard Worker
239*8975f5c5SAndroid Build Coastguard Workervoid InitArgumentBufferEncoder(mtl::Context *context,
240*8975f5c5SAndroid Build Coastguard Worker                               id<MTLFunction> function,
241*8975f5c5SAndroid Build Coastguard Worker                               uint32_t bufferIndex,
242*8975f5c5SAndroid Build Coastguard Worker                               ProgramArgumentBufferEncoderMtl *encoder)
243*8975f5c5SAndroid Build Coastguard Worker{
244*8975f5c5SAndroid Build Coastguard Worker    encoder->metalArgBufferEncoder =
245*8975f5c5SAndroid Build Coastguard Worker        mtl::adoptObjCObj([function newArgumentEncoderWithBufferIndex:bufferIndex]);
246*8975f5c5SAndroid Build Coastguard Worker    if (encoder->metalArgBufferEncoder)
247*8975f5c5SAndroid Build Coastguard Worker    {
248*8975f5c5SAndroid Build Coastguard Worker        encoder->bufferPool.initialize(context, encoder->metalArgBufferEncoder.get().encodedLength,
249*8975f5c5SAndroid Build Coastguard Worker                                       mtl::kArgumentBufferOffsetAlignment, 0);
250*8975f5c5SAndroid Build Coastguard Worker    }
251*8975f5c5SAndroid Build Coastguard Worker}
252*8975f5c5SAndroid Build Coastguard Worker
253*8975f5c5SAndroid Build Coastguard Workertemplate <typename T>
254*8975f5c5SAndroid Build Coastguard Workervoid UpdateDefaultUniformBlockWithElementSize(GLsizei count,
255*8975f5c5SAndroid Build Coastguard Worker                                              uint32_t arrayIndex,
256*8975f5c5SAndroid Build Coastguard Worker                                              int componentCount,
257*8975f5c5SAndroid Build Coastguard Worker                                              const T *v,
258*8975f5c5SAndroid Build Coastguard Worker                                              size_t baseElementSize,
259*8975f5c5SAndroid Build Coastguard Worker                                              const sh::BlockMemberInfo &layoutInfo,
260*8975f5c5SAndroid Build Coastguard Worker                                              angle::MemoryBuffer *uniformData)
261*8975f5c5SAndroid Build Coastguard Worker{
262*8975f5c5SAndroid Build Coastguard Worker    const int elementSize = (int)(baseElementSize * componentCount);
263*8975f5c5SAndroid Build Coastguard Worker
264*8975f5c5SAndroid Build Coastguard Worker    uint8_t *dst = uniformData->data() + layoutInfo.offset;
265*8975f5c5SAndroid Build Coastguard Worker    if (layoutInfo.arrayStride == 0 || layoutInfo.arrayStride == elementSize)
266*8975f5c5SAndroid Build Coastguard Worker    {
267*8975f5c5SAndroid Build Coastguard Worker        uint32_t arrayOffset = arrayIndex * layoutInfo.arrayStride;
268*8975f5c5SAndroid Build Coastguard Worker        uint8_t *writePtr    = dst + arrayOffset;
269*8975f5c5SAndroid Build Coastguard Worker        ASSERT(writePtr + (elementSize * count) <= uniformData->data() + uniformData->size());
270*8975f5c5SAndroid Build Coastguard Worker        memcpy(writePtr, v, elementSize * count);
271*8975f5c5SAndroid Build Coastguard Worker    }
272*8975f5c5SAndroid Build Coastguard Worker    else
273*8975f5c5SAndroid Build Coastguard Worker    {
274*8975f5c5SAndroid Build Coastguard Worker        // Have to respect the arrayStride between each element of the array.
275*8975f5c5SAndroid Build Coastguard Worker        int maxIndex = arrayIndex + count;
276*8975f5c5SAndroid Build Coastguard Worker        for (int writeIndex = arrayIndex, readIndex = 0; writeIndex < maxIndex;
277*8975f5c5SAndroid Build Coastguard Worker             writeIndex++, readIndex++)
278*8975f5c5SAndroid Build Coastguard Worker        {
279*8975f5c5SAndroid Build Coastguard Worker            const int arrayOffset = writeIndex * layoutInfo.arrayStride;
280*8975f5c5SAndroid Build Coastguard Worker            uint8_t *writePtr     = dst + arrayOffset;
281*8975f5c5SAndroid Build Coastguard Worker            const T *readPtr      = v + (readIndex * componentCount);
282*8975f5c5SAndroid Build Coastguard Worker            ASSERT(writePtr + elementSize <= uniformData->data() + uniformData->size());
283*8975f5c5SAndroid Build Coastguard Worker            memcpy(writePtr, readPtr, elementSize);
284*8975f5c5SAndroid Build Coastguard Worker        }
285*8975f5c5SAndroid Build Coastguard Worker    }
286*8975f5c5SAndroid Build Coastguard Worker}
287*8975f5c5SAndroid Build Coastguard Workertemplate <typename T>
288*8975f5c5SAndroid Build Coastguard Workervoid ReadFromDefaultUniformBlock(int componentCount,
289*8975f5c5SAndroid Build Coastguard Worker                                 uint32_t arrayIndex,
290*8975f5c5SAndroid Build Coastguard Worker                                 T *dst,
291*8975f5c5SAndroid Build Coastguard Worker                                 size_t elementSize,
292*8975f5c5SAndroid Build Coastguard Worker                                 const sh::BlockMemberInfo &layoutInfo,
293*8975f5c5SAndroid Build Coastguard Worker                                 const angle::MemoryBuffer *uniformData)
294*8975f5c5SAndroid Build Coastguard Worker{
295*8975f5c5SAndroid Build Coastguard Worker    ReadFromDefaultUniformBlockWithElementSize(componentCount, arrayIndex, dst, sizeof(T),
296*8975f5c5SAndroid Build Coastguard Worker                                               layoutInfo, uniformData);
297*8975f5c5SAndroid Build Coastguard Worker}
298*8975f5c5SAndroid Build Coastguard Worker
299*8975f5c5SAndroid Build Coastguard Workervoid ReadFromDefaultUniformBlockWithElementSize(int componentCount,
300*8975f5c5SAndroid Build Coastguard Worker                                                uint32_t arrayIndex,
301*8975f5c5SAndroid Build Coastguard Worker                                                void *dst,
302*8975f5c5SAndroid Build Coastguard Worker                                                size_t baseElementSize,
303*8975f5c5SAndroid Build Coastguard Worker                                                const sh::BlockMemberInfo &layoutInfo,
304*8975f5c5SAndroid Build Coastguard Worker                                                const angle::MemoryBuffer *uniformData)
305*8975f5c5SAndroid Build Coastguard Worker{
306*8975f5c5SAndroid Build Coastguard Worker    ASSERT(layoutInfo.offset != -1);
307*8975f5c5SAndroid Build Coastguard Worker
308*8975f5c5SAndroid Build Coastguard Worker    const size_t elementSize = (baseElementSize * componentCount);
309*8975f5c5SAndroid Build Coastguard Worker    const uint8_t *source    = uniformData->data() + layoutInfo.offset;
310*8975f5c5SAndroid Build Coastguard Worker
311*8975f5c5SAndroid Build Coastguard Worker    if (layoutInfo.arrayStride == 0 || (size_t)layoutInfo.arrayStride == elementSize)
312*8975f5c5SAndroid Build Coastguard Worker    {
313*8975f5c5SAndroid Build Coastguard Worker        const uint8_t *readPtr = source + arrayIndex * layoutInfo.arrayStride;
314*8975f5c5SAndroid Build Coastguard Worker        memcpy(dst, readPtr, elementSize);
315*8975f5c5SAndroid Build Coastguard Worker    }
316*8975f5c5SAndroid Build Coastguard Worker    else
317*8975f5c5SAndroid Build Coastguard Worker    {
318*8975f5c5SAndroid Build Coastguard Worker        // Have to respect the arrayStride between each element of the array.
319*8975f5c5SAndroid Build Coastguard Worker        const int arrayOffset  = arrayIndex * layoutInfo.arrayStride;
320*8975f5c5SAndroid Build Coastguard Worker        const uint8_t *readPtr = source + arrayOffset;
321*8975f5c5SAndroid Build Coastguard Worker        memcpy(dst, readPtr, elementSize);
322*8975f5c5SAndroid Build Coastguard Worker    }
323*8975f5c5SAndroid Build Coastguard Worker}
324*8975f5c5SAndroid Build Coastguard Worker
325*8975f5c5SAndroid Build Coastguard Workerclass Std140BlockLayoutEncoderFactory : public gl::CustomBlockLayoutEncoderFactory
326*8975f5c5SAndroid Build Coastguard Worker{
327*8975f5c5SAndroid Build Coastguard Worker  public:
328*8975f5c5SAndroid Build Coastguard Worker    sh::BlockLayoutEncoder *makeEncoder() override { return new sh::Std140BlockEncoder(); }
329*8975f5c5SAndroid Build Coastguard Worker};
330*8975f5c5SAndroid Build Coastguard Worker
331*8975f5c5SAndroid Build Coastguard Workerclass Std430BlockLayoutEncoderFactory : public gl::CustomBlockLayoutEncoderFactory
332*8975f5c5SAndroid Build Coastguard Worker{
333*8975f5c5SAndroid Build Coastguard Worker  public:
334*8975f5c5SAndroid Build Coastguard Worker    sh::BlockLayoutEncoder *makeEncoder() override { return new sh::Std430BlockEncoder(); }
335*8975f5c5SAndroid Build Coastguard Worker};
336*8975f5c5SAndroid Build Coastguard Worker
337*8975f5c5SAndroid Build Coastguard Workerclass StdMTLBLockLayoutEncoderFactory : public gl::CustomBlockLayoutEncoderFactory
338*8975f5c5SAndroid Build Coastguard Worker{
339*8975f5c5SAndroid Build Coastguard Worker  public:
340*8975f5c5SAndroid Build Coastguard Worker    sh::BlockLayoutEncoder *makeEncoder() override { return new mtl::BlockLayoutEncoderMTL(); }
341*8975f5c5SAndroid Build Coastguard Worker};
342*8975f5c5SAndroid Build Coastguard Worker}  // anonymous namespace
343*8975f5c5SAndroid Build Coastguard Worker
344*8975f5c5SAndroid Build Coastguard Workerangle::Result CreateMslShaderLib(mtl::Context *context,
345*8975f5c5SAndroid Build Coastguard Worker                                 gl::InfoLog &infoLog,
346*8975f5c5SAndroid Build Coastguard Worker                                 mtl::TranslatedShaderInfo *translatedMslInfo,
347*8975f5c5SAndroid Build Coastguard Worker                                 const std::map<std::string, std::string> &substitutionMacros)
348*8975f5c5SAndroid Build Coastguard Worker{
349*8975f5c5SAndroid Build Coastguard Worker    ANGLE_MTL_OBJC_SCOPE
350*8975f5c5SAndroid Build Coastguard Worker    {
351*8975f5c5SAndroid Build Coastguard Worker        mtl::LibraryCache &libraryCache = context->getDisplay()->getLibraryCache();
352*8975f5c5SAndroid Build Coastguard Worker
353*8975f5c5SAndroid Build Coastguard Worker        // Convert to actual binary shader
354*8975f5c5SAndroid Build Coastguard Worker        mtl::AutoObjCPtr<NSError *> err = nil;
355*8975f5c5SAndroid Build Coastguard Worker        const bool disableFastMath =
356*8975f5c5SAndroid Build Coastguard Worker            context->getDisplay()->getFeatures().intelDisableFastMath.enabled ||
357*8975f5c5SAndroid Build Coastguard Worker            translatedMslInfo->hasIsnanOrIsinf;
358*8975f5c5SAndroid Build Coastguard Worker        const bool usesInvariance       = translatedMslInfo->hasInvariant;
359*8975f5c5SAndroid Build Coastguard Worker        translatedMslInfo->metalLibrary = libraryCache.getOrCompileShaderLibrary(
360*8975f5c5SAndroid Build Coastguard Worker            context->getDisplay(), translatedMslInfo->metalShaderSource, substitutionMacros,
361*8975f5c5SAndroid Build Coastguard Worker            disableFastMath, usesInvariance, &err);
362*8975f5c5SAndroid Build Coastguard Worker        if (err && !translatedMslInfo->metalLibrary)
363*8975f5c5SAndroid Build Coastguard Worker        {
364*8975f5c5SAndroid Build Coastguard Worker            std::ostringstream ss;
365*8975f5c5SAndroid Build Coastguard Worker            ss << "Internal error compiling shader with Metal backend.\n";
366*8975f5c5SAndroid Build Coastguard Worker            ss << err.get().localizedDescription.UTF8String << "\n";
367*8975f5c5SAndroid Build Coastguard Worker            ss << "-----\n";
368*8975f5c5SAndroid Build Coastguard Worker            ss << *(translatedMslInfo->metalShaderSource);
369*8975f5c5SAndroid Build Coastguard Worker            ss << "-----\n";
370*8975f5c5SAndroid Build Coastguard Worker
371*8975f5c5SAndroid Build Coastguard Worker            infoLog << ss.str();
372*8975f5c5SAndroid Build Coastguard Worker
373*8975f5c5SAndroid Build Coastguard Worker            ANGLE_MTL_HANDLE_ERROR(context, ss.str().c_str(), GL_INVALID_OPERATION);
374*8975f5c5SAndroid Build Coastguard Worker            return angle::Result::Stop;
375*8975f5c5SAndroid Build Coastguard Worker        }
376*8975f5c5SAndroid Build Coastguard Worker
377*8975f5c5SAndroid Build Coastguard Worker        return angle::Result::Continue;
378*8975f5c5SAndroid Build Coastguard Worker    }
379*8975f5c5SAndroid Build Coastguard Worker}
380*8975f5c5SAndroid Build Coastguard WorkerDefaultUniformBlockMtl::DefaultUniformBlockMtl() {}
381*8975f5c5SAndroid Build Coastguard Worker
382*8975f5c5SAndroid Build Coastguard WorkerDefaultUniformBlockMtl::~DefaultUniformBlockMtl() = default;
383*8975f5c5SAndroid Build Coastguard Worker
384*8975f5c5SAndroid Build Coastguard WorkerProgramExecutableMtl::ProgramExecutableMtl(const gl::ProgramExecutable *executable)
385*8975f5c5SAndroid Build Coastguard Worker    : ProgramExecutableImpl(executable), mProgramHasFlatAttributes(false), mShadowCompareModes{}
386*8975f5c5SAndroid Build Coastguard Worker{
387*8975f5c5SAndroid Build Coastguard Worker    mCurrentShaderVariants.fill(nullptr);
388*8975f5c5SAndroid Build Coastguard Worker
389*8975f5c5SAndroid Build Coastguard Worker    for (gl::ShaderType shaderType : gl::AllShaderTypes())
390*8975f5c5SAndroid Build Coastguard Worker    {
391*8975f5c5SAndroid Build Coastguard Worker        mMslShaderTranslateInfo[shaderType].reset();
392*8975f5c5SAndroid Build Coastguard Worker    }
393*8975f5c5SAndroid Build Coastguard Worker    mMslXfbOnlyVertexShaderInfo.reset();
394*8975f5c5SAndroid Build Coastguard Worker}
395*8975f5c5SAndroid Build Coastguard Worker
396*8975f5c5SAndroid Build Coastguard WorkerProgramExecutableMtl::~ProgramExecutableMtl() {}
397*8975f5c5SAndroid Build Coastguard Worker
398*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::destroy(const gl::Context *context)
399*8975f5c5SAndroid Build Coastguard Worker{
400*8975f5c5SAndroid Build Coastguard Worker    auto contextMtl = mtl::GetImpl(context);
401*8975f5c5SAndroid Build Coastguard Worker    reset(contextMtl);
402*8975f5c5SAndroid Build Coastguard Worker}
403*8975f5c5SAndroid Build Coastguard Worker
404*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::reset(ContextMtl *context)
405*8975f5c5SAndroid Build Coastguard Worker{
406*8975f5c5SAndroid Build Coastguard Worker    mProgramHasFlatAttributes = false;
407*8975f5c5SAndroid Build Coastguard Worker
408*8975f5c5SAndroid Build Coastguard Worker    for (auto &block : mDefaultUniformBlocks)
409*8975f5c5SAndroid Build Coastguard Worker    {
410*8975f5c5SAndroid Build Coastguard Worker        block.uniformLayout.clear();
411*8975f5c5SAndroid Build Coastguard Worker    }
412*8975f5c5SAndroid Build Coastguard Worker
413*8975f5c5SAndroid Build Coastguard Worker    for (gl::ShaderType shaderType : gl::AllShaderTypes())
414*8975f5c5SAndroid Build Coastguard Worker    {
415*8975f5c5SAndroid Build Coastguard Worker        mMslShaderTranslateInfo[shaderType].reset();
416*8975f5c5SAndroid Build Coastguard Worker        mCurrentShaderVariants[shaderType] = nullptr;
417*8975f5c5SAndroid Build Coastguard Worker    }
418*8975f5c5SAndroid Build Coastguard Worker    mMslXfbOnlyVertexShaderInfo.reset();
419*8975f5c5SAndroid Build Coastguard Worker
420*8975f5c5SAndroid Build Coastguard Worker    for (ProgramShaderObjVariantMtl &var : mVertexShaderVariants)
421*8975f5c5SAndroid Build Coastguard Worker    {
422*8975f5c5SAndroid Build Coastguard Worker        var.reset(context);
423*8975f5c5SAndroid Build Coastguard Worker    }
424*8975f5c5SAndroid Build Coastguard Worker    for (ProgramShaderObjVariantMtl &var : mFragmentShaderVariants)
425*8975f5c5SAndroid Build Coastguard Worker    {
426*8975f5c5SAndroid Build Coastguard Worker        var.reset(context);
427*8975f5c5SAndroid Build Coastguard Worker    }
428*8975f5c5SAndroid Build Coastguard Worker
429*8975f5c5SAndroid Build Coastguard Worker    for (gl::ShaderType shaderType : gl::kAllGLES2ShaderTypes)
430*8975f5c5SAndroid Build Coastguard Worker    {
431*8975f5c5SAndroid Build Coastguard Worker        if (mDefaultUniformBufferPools[shaderType])
432*8975f5c5SAndroid Build Coastguard Worker        {
433*8975f5c5SAndroid Build Coastguard Worker            mDefaultUniformBufferPools[shaderType]->destroy(context);
434*8975f5c5SAndroid Build Coastguard Worker            mDefaultUniformBufferPools[shaderType].reset();
435*8975f5c5SAndroid Build Coastguard Worker        }
436*8975f5c5SAndroid Build Coastguard Worker    }
437*8975f5c5SAndroid Build Coastguard Worker}
438*8975f5c5SAndroid Build Coastguard Worker
439*8975f5c5SAndroid Build Coastguard Workerangle::Result ProgramExecutableMtl::load(ContextMtl *contextMtl, gl::BinaryInputStream *stream)
440*8975f5c5SAndroid Build Coastguard Worker{
441*8975f5c5SAndroid Build Coastguard Worker    loadTranslatedShaders(stream);
442*8975f5c5SAndroid Build Coastguard Worker    loadShaderInternalInfo(stream);
443*8975f5c5SAndroid Build Coastguard Worker    ANGLE_TRY(loadDefaultUniformBlocksInfo(contextMtl, stream));
444*8975f5c5SAndroid Build Coastguard Worker    return loadInterfaceBlockInfo(stream);
445*8975f5c5SAndroid Build Coastguard Worker}
446*8975f5c5SAndroid Build Coastguard Worker
447*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::save(gl::BinaryOutputStream *stream)
448*8975f5c5SAndroid Build Coastguard Worker{
449*8975f5c5SAndroid Build Coastguard Worker    saveTranslatedShaders(stream);
450*8975f5c5SAndroid Build Coastguard Worker    saveShaderInternalInfo(stream);
451*8975f5c5SAndroid Build Coastguard Worker    saveDefaultUniformBlocksInfo(stream);
452*8975f5c5SAndroid Build Coastguard Worker    saveInterfaceBlockInfo(stream);
453*8975f5c5SAndroid Build Coastguard Worker}
454*8975f5c5SAndroid Build Coastguard Worker
455*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::saveInterfaceBlockInfo(gl::BinaryOutputStream *stream)
456*8975f5c5SAndroid Build Coastguard Worker{
457*8975f5c5SAndroid Build Coastguard Worker    // Serializes the uniformLayout data of mDefaultUniformBlocks
458*8975f5c5SAndroid Build Coastguard Worker    // First, save the number of Ib's to process
459*8975f5c5SAndroid Build Coastguard Worker    stream->writeInt<unsigned int>((unsigned int)mUniformBlockConversions.size());
460*8975f5c5SAndroid Build Coastguard Worker    // Next, iterate through all of the conversions.
461*8975f5c5SAndroid Build Coastguard Worker    for (auto conversion : mUniformBlockConversions)
462*8975f5c5SAndroid Build Coastguard Worker    {
463*8975f5c5SAndroid Build Coastguard Worker        // Write the name of the conversion
464*8975f5c5SAndroid Build Coastguard Worker        stream->writeString(conversion.first);
465*8975f5c5SAndroid Build Coastguard Worker        // Write the number of entries in the conversion
466*8975f5c5SAndroid Build Coastguard Worker        const UBOConversionInfo &conversionInfo = conversion.second;
467*8975f5c5SAndroid Build Coastguard Worker        stream->writeVector(conversionInfo.stdInfo());
468*8975f5c5SAndroid Build Coastguard Worker        stream->writeVector(conversionInfo.metalInfo());
469*8975f5c5SAndroid Build Coastguard Worker        stream->writeInt<size_t>(conversionInfo.stdSize());
470*8975f5c5SAndroid Build Coastguard Worker        stream->writeInt<size_t>(conversionInfo.metalSize());
471*8975f5c5SAndroid Build Coastguard Worker    }
472*8975f5c5SAndroid Build Coastguard Worker}
473*8975f5c5SAndroid Build Coastguard Worker
474*8975f5c5SAndroid Build Coastguard Workerangle::Result ProgramExecutableMtl::loadInterfaceBlockInfo(gl::BinaryInputStream *stream)
475*8975f5c5SAndroid Build Coastguard Worker{
476*8975f5c5SAndroid Build Coastguard Worker    mUniformBlockConversions.clear();
477*8975f5c5SAndroid Build Coastguard Worker    // First, load the number of Ib's to process
478*8975f5c5SAndroid Build Coastguard Worker    uint32_t numBlocks = stream->readInt<uint32_t>();
479*8975f5c5SAndroid Build Coastguard Worker    // Next, iterate through all of the conversions.
480*8975f5c5SAndroid Build Coastguard Worker    for (uint32_t nBlocks = 0; nBlocks < numBlocks; ++nBlocks)
481*8975f5c5SAndroid Build Coastguard Worker    {
482*8975f5c5SAndroid Build Coastguard Worker        // Read the name of the conversion
483*8975f5c5SAndroid Build Coastguard Worker        std::string blockName = stream->readString();
484*8975f5c5SAndroid Build Coastguard Worker        // Read the number of entries in the conversion
485*8975f5c5SAndroid Build Coastguard Worker        std::vector<sh::BlockMemberInfo> stdInfo, metalInfo;
486*8975f5c5SAndroid Build Coastguard Worker        stream->readVector(&stdInfo);
487*8975f5c5SAndroid Build Coastguard Worker        stream->readVector(&metalInfo);
488*8975f5c5SAndroid Build Coastguard Worker        size_t stdSize   = stream->readInt<size_t>();
489*8975f5c5SAndroid Build Coastguard Worker        size_t metalSize = stream->readInt<size_t>();
490*8975f5c5SAndroid Build Coastguard Worker        mUniformBlockConversions.insert(
491*8975f5c5SAndroid Build Coastguard Worker            {blockName, UBOConversionInfo(stdInfo, metalInfo, stdSize, metalSize)});
492*8975f5c5SAndroid Build Coastguard Worker    }
493*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
494*8975f5c5SAndroid Build Coastguard Worker}
495*8975f5c5SAndroid Build Coastguard Worker
496*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::saveDefaultUniformBlocksInfo(gl::BinaryOutputStream *stream)
497*8975f5c5SAndroid Build Coastguard Worker{
498*8975f5c5SAndroid Build Coastguard Worker    // Serializes the uniformLayout data of mDefaultUniformBlocks
499*8975f5c5SAndroid Build Coastguard Worker    for (gl::ShaderType shaderType : gl::AllShaderTypes())
500*8975f5c5SAndroid Build Coastguard Worker    {
501*8975f5c5SAndroid Build Coastguard Worker        stream->writeVector(mDefaultUniformBlocks[shaderType].uniformLayout);
502*8975f5c5SAndroid Build Coastguard Worker    }
503*8975f5c5SAndroid Build Coastguard Worker
504*8975f5c5SAndroid Build Coastguard Worker    // Serializes required uniform block memory sizes
505*8975f5c5SAndroid Build Coastguard Worker    for (gl::ShaderType shaderType : gl::AllShaderTypes())
506*8975f5c5SAndroid Build Coastguard Worker    {
507*8975f5c5SAndroid Build Coastguard Worker        stream->writeInt(mDefaultUniformBlocks[shaderType].uniformData.size());
508*8975f5c5SAndroid Build Coastguard Worker    }
509*8975f5c5SAndroid Build Coastguard Worker}
510*8975f5c5SAndroid Build Coastguard Worker
511*8975f5c5SAndroid Build Coastguard Workerangle::Result ProgramExecutableMtl::loadDefaultUniformBlocksInfo(mtl::Context *context,
512*8975f5c5SAndroid Build Coastguard Worker                                                                 gl::BinaryInputStream *stream)
513*8975f5c5SAndroid Build Coastguard Worker{
514*8975f5c5SAndroid Build Coastguard Worker    gl::ShaderMap<size_t> requiredBufferSize;
515*8975f5c5SAndroid Build Coastguard Worker    requiredBufferSize.fill(0);
516*8975f5c5SAndroid Build Coastguard Worker    // Deserializes the uniformLayout data of mDefaultUniformBlocks
517*8975f5c5SAndroid Build Coastguard Worker    for (gl::ShaderType shaderType : gl::AllShaderTypes())
518*8975f5c5SAndroid Build Coastguard Worker    {
519*8975f5c5SAndroid Build Coastguard Worker        stream->readVector(&mDefaultUniformBlocks[shaderType].uniformLayout);
520*8975f5c5SAndroid Build Coastguard Worker    }
521*8975f5c5SAndroid Build Coastguard Worker
522*8975f5c5SAndroid Build Coastguard Worker    // Deserializes required uniform block memory sizes
523*8975f5c5SAndroid Build Coastguard Worker    for (gl::ShaderType shaderType : gl::AllShaderTypes())
524*8975f5c5SAndroid Build Coastguard Worker    {
525*8975f5c5SAndroid Build Coastguard Worker        requiredBufferSize[shaderType] = stream->readInt<size_t>();
526*8975f5c5SAndroid Build Coastguard Worker    }
527*8975f5c5SAndroid Build Coastguard Worker
528*8975f5c5SAndroid Build Coastguard Worker    return resizeDefaultUniformBlocksMemory(context, requiredBufferSize);
529*8975f5c5SAndroid Build Coastguard Worker}
530*8975f5c5SAndroid Build Coastguard Worker
531*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::saveShaderInternalInfo(gl::BinaryOutputStream *stream)
532*8975f5c5SAndroid Build Coastguard Worker{
533*8975f5c5SAndroid Build Coastguard Worker    for (gl::ShaderType shaderType : gl::AllShaderTypes())
534*8975f5c5SAndroid Build Coastguard Worker    {
535*8975f5c5SAndroid Build Coastguard Worker        stream->writeInt<int>(mMslShaderTranslateInfo[shaderType].hasUBOArgumentBuffer);
536*8975f5c5SAndroid Build Coastguard Worker        for (const mtl::SamplerBinding &binding :
537*8975f5c5SAndroid Build Coastguard Worker             mMslShaderTranslateInfo[shaderType].actualSamplerBindings)
538*8975f5c5SAndroid Build Coastguard Worker        {
539*8975f5c5SAndroid Build Coastguard Worker            stream->writeInt<uint32_t>(binding.textureBinding);
540*8975f5c5SAndroid Build Coastguard Worker            stream->writeInt<uint32_t>(binding.samplerBinding);
541*8975f5c5SAndroid Build Coastguard Worker        }
542*8975f5c5SAndroid Build Coastguard Worker        for (int rwTextureBinding : mMslShaderTranslateInfo[shaderType].actualImageBindings)
543*8975f5c5SAndroid Build Coastguard Worker        {
544*8975f5c5SAndroid Build Coastguard Worker            stream->writeInt<int>(rwTextureBinding);
545*8975f5c5SAndroid Build Coastguard Worker        }
546*8975f5c5SAndroid Build Coastguard Worker
547*8975f5c5SAndroid Build Coastguard Worker        for (uint32_t uboBinding : mMslShaderTranslateInfo[shaderType].actualUBOBindings)
548*8975f5c5SAndroid Build Coastguard Worker        {
549*8975f5c5SAndroid Build Coastguard Worker            stream->writeInt<uint32_t>(uboBinding);
550*8975f5c5SAndroid Build Coastguard Worker        }
551*8975f5c5SAndroid Build Coastguard Worker        stream->writeBool(mMslShaderTranslateInfo[shaderType].hasInvariant);
552*8975f5c5SAndroid Build Coastguard Worker    }
553*8975f5c5SAndroid Build Coastguard Worker    for (size_t xfbBindIndex = 0; xfbBindIndex < mtl::kMaxShaderXFBs; xfbBindIndex++)
554*8975f5c5SAndroid Build Coastguard Worker    {
555*8975f5c5SAndroid Build Coastguard Worker        stream->writeInt(
556*8975f5c5SAndroid Build Coastguard Worker            mMslShaderTranslateInfo[gl::ShaderType::Vertex].actualXFBBindings[xfbBindIndex]);
557*8975f5c5SAndroid Build Coastguard Worker    }
558*8975f5c5SAndroid Build Coastguard Worker
559*8975f5c5SAndroid Build Coastguard Worker    // Write out XFB info.
560*8975f5c5SAndroid Build Coastguard Worker    {
561*8975f5c5SAndroid Build Coastguard Worker        stream->writeInt<int>(mMslXfbOnlyVertexShaderInfo.hasUBOArgumentBuffer);
562*8975f5c5SAndroid Build Coastguard Worker        for (mtl::SamplerBinding &binding : mMslXfbOnlyVertexShaderInfo.actualSamplerBindings)
563*8975f5c5SAndroid Build Coastguard Worker        {
564*8975f5c5SAndroid Build Coastguard Worker            stream->writeInt<uint32_t>(binding.textureBinding);
565*8975f5c5SAndroid Build Coastguard Worker            stream->writeInt<uint32_t>(binding.samplerBinding);
566*8975f5c5SAndroid Build Coastguard Worker        }
567*8975f5c5SAndroid Build Coastguard Worker        for (int rwTextureBinding : mMslXfbOnlyVertexShaderInfo.actualImageBindings)
568*8975f5c5SAndroid Build Coastguard Worker        {
569*8975f5c5SAndroid Build Coastguard Worker            stream->writeInt<int>(rwTextureBinding);
570*8975f5c5SAndroid Build Coastguard Worker        }
571*8975f5c5SAndroid Build Coastguard Worker
572*8975f5c5SAndroid Build Coastguard Worker        for (uint32_t &uboBinding : mMslXfbOnlyVertexShaderInfo.actualUBOBindings)
573*8975f5c5SAndroid Build Coastguard Worker        {
574*8975f5c5SAndroid Build Coastguard Worker            stream->writeInt<uint32_t>(uboBinding);
575*8975f5c5SAndroid Build Coastguard Worker        }
576*8975f5c5SAndroid Build Coastguard Worker        for (size_t xfbBindIndex = 0; xfbBindIndex < mtl::kMaxShaderXFBs; xfbBindIndex++)
577*8975f5c5SAndroid Build Coastguard Worker        {
578*8975f5c5SAndroid Build Coastguard Worker            stream->writeInt(mMslXfbOnlyVertexShaderInfo.actualXFBBindings[xfbBindIndex]);
579*8975f5c5SAndroid Build Coastguard Worker        }
580*8975f5c5SAndroid Build Coastguard Worker    }
581*8975f5c5SAndroid Build Coastguard Worker
582*8975f5c5SAndroid Build Coastguard Worker    stream->writeBool(mProgramHasFlatAttributes);
583*8975f5c5SAndroid Build Coastguard Worker}
584*8975f5c5SAndroid Build Coastguard Worker
585*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::loadShaderInternalInfo(gl::BinaryInputStream *stream)
586*8975f5c5SAndroid Build Coastguard Worker{
587*8975f5c5SAndroid Build Coastguard Worker    for (gl::ShaderType shaderType : gl::AllShaderTypes())
588*8975f5c5SAndroid Build Coastguard Worker    {
589*8975f5c5SAndroid Build Coastguard Worker        mMslShaderTranslateInfo[shaderType].hasUBOArgumentBuffer = stream->readInt<int>() != 0;
590*8975f5c5SAndroid Build Coastguard Worker        for (mtl::SamplerBinding &binding :
591*8975f5c5SAndroid Build Coastguard Worker             mMslShaderTranslateInfo[shaderType].actualSamplerBindings)
592*8975f5c5SAndroid Build Coastguard Worker        {
593*8975f5c5SAndroid Build Coastguard Worker            binding.textureBinding = stream->readInt<uint32_t>();
594*8975f5c5SAndroid Build Coastguard Worker            binding.samplerBinding = stream->readInt<uint32_t>();
595*8975f5c5SAndroid Build Coastguard Worker        }
596*8975f5c5SAndroid Build Coastguard Worker        for (int &rwTextureBinding : mMslShaderTranslateInfo[shaderType].actualImageBindings)
597*8975f5c5SAndroid Build Coastguard Worker        {
598*8975f5c5SAndroid Build Coastguard Worker            rwTextureBinding = stream->readInt<int>();
599*8975f5c5SAndroid Build Coastguard Worker        }
600*8975f5c5SAndroid Build Coastguard Worker
601*8975f5c5SAndroid Build Coastguard Worker        for (uint32_t &uboBinding : mMslShaderTranslateInfo[shaderType].actualUBOBindings)
602*8975f5c5SAndroid Build Coastguard Worker        {
603*8975f5c5SAndroid Build Coastguard Worker            uboBinding = stream->readInt<uint32_t>();
604*8975f5c5SAndroid Build Coastguard Worker        }
605*8975f5c5SAndroid Build Coastguard Worker        mMslShaderTranslateInfo[shaderType].hasInvariant = stream->readBool();
606*8975f5c5SAndroid Build Coastguard Worker    }
607*8975f5c5SAndroid Build Coastguard Worker
608*8975f5c5SAndroid Build Coastguard Worker    for (size_t xfbBindIndex = 0; xfbBindIndex < mtl::kMaxShaderXFBs; xfbBindIndex++)
609*8975f5c5SAndroid Build Coastguard Worker    {
610*8975f5c5SAndroid Build Coastguard Worker        stream->readInt(
611*8975f5c5SAndroid Build Coastguard Worker            &mMslShaderTranslateInfo[gl::ShaderType::Vertex].actualXFBBindings[xfbBindIndex]);
612*8975f5c5SAndroid Build Coastguard Worker    }
613*8975f5c5SAndroid Build Coastguard Worker    // Load Transform Feedback info
614*8975f5c5SAndroid Build Coastguard Worker    {
615*8975f5c5SAndroid Build Coastguard Worker        mMslXfbOnlyVertexShaderInfo.hasUBOArgumentBuffer = stream->readInt<int>() != 0;
616*8975f5c5SAndroid Build Coastguard Worker        for (mtl::SamplerBinding &binding : mMslXfbOnlyVertexShaderInfo.actualSamplerBindings)
617*8975f5c5SAndroid Build Coastguard Worker        {
618*8975f5c5SAndroid Build Coastguard Worker            binding.textureBinding = stream->readInt<uint32_t>();
619*8975f5c5SAndroid Build Coastguard Worker            binding.samplerBinding = stream->readInt<uint32_t>();
620*8975f5c5SAndroid Build Coastguard Worker        }
621*8975f5c5SAndroid Build Coastguard Worker        for (int &rwTextureBinding : mMslXfbOnlyVertexShaderInfo.actualImageBindings)
622*8975f5c5SAndroid Build Coastguard Worker        {
623*8975f5c5SAndroid Build Coastguard Worker            rwTextureBinding = stream->readInt<int>();
624*8975f5c5SAndroid Build Coastguard Worker        }
625*8975f5c5SAndroid Build Coastguard Worker
626*8975f5c5SAndroid Build Coastguard Worker        for (uint32_t &uboBinding : mMslXfbOnlyVertexShaderInfo.actualUBOBindings)
627*8975f5c5SAndroid Build Coastguard Worker        {
628*8975f5c5SAndroid Build Coastguard Worker            uboBinding = stream->readInt<uint32_t>();
629*8975f5c5SAndroid Build Coastguard Worker        }
630*8975f5c5SAndroid Build Coastguard Worker        for (size_t xfbBindIndex = 0; xfbBindIndex < mtl::kMaxShaderXFBs; xfbBindIndex++)
631*8975f5c5SAndroid Build Coastguard Worker        {
632*8975f5c5SAndroid Build Coastguard Worker            stream->readInt(&mMslXfbOnlyVertexShaderInfo.actualXFBBindings[xfbBindIndex]);
633*8975f5c5SAndroid Build Coastguard Worker        }
634*8975f5c5SAndroid Build Coastguard Worker        mMslXfbOnlyVertexShaderInfo.metalLibrary = nullptr;
635*8975f5c5SAndroid Build Coastguard Worker    }
636*8975f5c5SAndroid Build Coastguard Worker
637*8975f5c5SAndroid Build Coastguard Worker    mProgramHasFlatAttributes = stream->readBool();
638*8975f5c5SAndroid Build Coastguard Worker}
639*8975f5c5SAndroid Build Coastguard Worker
640*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::saveTranslatedShaders(gl::BinaryOutputStream *stream)
641*8975f5c5SAndroid Build Coastguard Worker{
642*8975f5c5SAndroid Build Coastguard Worker    auto writeTranslatedSource = [](gl::BinaryOutputStream *stream,
643*8975f5c5SAndroid Build Coastguard Worker                                    const mtl::TranslatedShaderInfo &shaderInfo) {
644*8975f5c5SAndroid Build Coastguard Worker        const std::string &source =
645*8975f5c5SAndroid Build Coastguard Worker            shaderInfo.metalShaderSource ? *shaderInfo.metalShaderSource : std::string();
646*8975f5c5SAndroid Build Coastguard Worker        stream->writeString(source);
647*8975f5c5SAndroid Build Coastguard Worker    };
648*8975f5c5SAndroid Build Coastguard Worker
649*8975f5c5SAndroid Build Coastguard Worker    // Write out shader sources for all shader types
650*8975f5c5SAndroid Build Coastguard Worker    for (const gl::ShaderType shaderType : gl::AllShaderTypes())
651*8975f5c5SAndroid Build Coastguard Worker    {
652*8975f5c5SAndroid Build Coastguard Worker        writeTranslatedSource(stream, mMslShaderTranslateInfo[shaderType]);
653*8975f5c5SAndroid Build Coastguard Worker    }
654*8975f5c5SAndroid Build Coastguard Worker    writeTranslatedSource(stream, mMslXfbOnlyVertexShaderInfo);
655*8975f5c5SAndroid Build Coastguard Worker}
656*8975f5c5SAndroid Build Coastguard Worker
657*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::loadTranslatedShaders(gl::BinaryInputStream *stream)
658*8975f5c5SAndroid Build Coastguard Worker{
659*8975f5c5SAndroid Build Coastguard Worker    auto readTranslatedSource = [](gl::BinaryInputStream *stream,
660*8975f5c5SAndroid Build Coastguard Worker                                   mtl::TranslatedShaderInfo &shaderInfo) {
661*8975f5c5SAndroid Build Coastguard Worker        std::string source = stream->readString();
662*8975f5c5SAndroid Build Coastguard Worker        if (!source.empty())
663*8975f5c5SAndroid Build Coastguard Worker        {
664*8975f5c5SAndroid Build Coastguard Worker            shaderInfo.metalShaderSource = std::make_shared<const std::string>(std::move(source));
665*8975f5c5SAndroid Build Coastguard Worker        }
666*8975f5c5SAndroid Build Coastguard Worker        else
667*8975f5c5SAndroid Build Coastguard Worker        {
668*8975f5c5SAndroid Build Coastguard Worker            shaderInfo.metalShaderSource = nullptr;
669*8975f5c5SAndroid Build Coastguard Worker        }
670*8975f5c5SAndroid Build Coastguard Worker    };
671*8975f5c5SAndroid Build Coastguard Worker
672*8975f5c5SAndroid Build Coastguard Worker    // Read in shader sources for all shader types
673*8975f5c5SAndroid Build Coastguard Worker    for (const gl::ShaderType shaderType : gl::AllShaderTypes())
674*8975f5c5SAndroid Build Coastguard Worker    {
675*8975f5c5SAndroid Build Coastguard Worker        readTranslatedSource(stream, mMslShaderTranslateInfo[shaderType]);
676*8975f5c5SAndroid Build Coastguard Worker    }
677*8975f5c5SAndroid Build Coastguard Worker    readTranslatedSource(stream, mMslXfbOnlyVertexShaderInfo);
678*8975f5c5SAndroid Build Coastguard Worker}
679*8975f5c5SAndroid Build Coastguard Worker
680*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::linkUpdateHasFlatAttributes(
681*8975f5c5SAndroid Build Coastguard Worker    const gl::SharedCompiledShaderState &vertexShader)
682*8975f5c5SAndroid Build Coastguard Worker{
683*8975f5c5SAndroid Build Coastguard Worker    mProgramHasFlatAttributes = false;
684*8975f5c5SAndroid Build Coastguard Worker
685*8975f5c5SAndroid Build Coastguard Worker    const auto &programInputs = mExecutable->getProgramInputs();
686*8975f5c5SAndroid Build Coastguard Worker    for (auto &attribute : programInputs)
687*8975f5c5SAndroid Build Coastguard Worker    {
688*8975f5c5SAndroid Build Coastguard Worker        if (attribute.getInterpolation() == sh::INTERPOLATION_FLAT)
689*8975f5c5SAndroid Build Coastguard Worker        {
690*8975f5c5SAndroid Build Coastguard Worker            mProgramHasFlatAttributes = true;
691*8975f5c5SAndroid Build Coastguard Worker            return;
692*8975f5c5SAndroid Build Coastguard Worker        }
693*8975f5c5SAndroid Build Coastguard Worker    }
694*8975f5c5SAndroid Build Coastguard Worker
695*8975f5c5SAndroid Build Coastguard Worker    const auto &flatVaryings = vertexShader->outputVaryings;
696*8975f5c5SAndroid Build Coastguard Worker    for (auto &attribute : flatVaryings)
697*8975f5c5SAndroid Build Coastguard Worker    {
698*8975f5c5SAndroid Build Coastguard Worker        if (attribute.interpolation == sh::INTERPOLATION_FLAT)
699*8975f5c5SAndroid Build Coastguard Worker        {
700*8975f5c5SAndroid Build Coastguard Worker            mProgramHasFlatAttributes = true;
701*8975f5c5SAndroid Build Coastguard Worker            return;
702*8975f5c5SAndroid Build Coastguard Worker        }
703*8975f5c5SAndroid Build Coastguard Worker    }
704*8975f5c5SAndroid Build Coastguard Worker}
705*8975f5c5SAndroid Build Coastguard Worker
706*8975f5c5SAndroid Build Coastguard Workerangle::Result ProgramExecutableMtl::initDefaultUniformBlocks(
707*8975f5c5SAndroid Build Coastguard Worker    mtl::Context *context,
708*8975f5c5SAndroid Build Coastguard Worker    const gl::ShaderMap<gl::SharedCompiledShaderState> &shaders)
709*8975f5c5SAndroid Build Coastguard Worker{
710*8975f5c5SAndroid Build Coastguard Worker    // Process vertex and fragment uniforms into std140 packing.
711*8975f5c5SAndroid Build Coastguard Worker    gl::ShaderMap<sh::BlockLayoutMap> layoutMap;
712*8975f5c5SAndroid Build Coastguard Worker    gl::ShaderMap<size_t> requiredBufferSize;
713*8975f5c5SAndroid Build Coastguard Worker    requiredBufferSize.fill(0);
714*8975f5c5SAndroid Build Coastguard Worker
715*8975f5c5SAndroid Build Coastguard Worker    for (gl::ShaderType shaderType : gl::kAllGLES2ShaderTypes)
716*8975f5c5SAndroid Build Coastguard Worker    {
717*8975f5c5SAndroid Build Coastguard Worker        const gl::SharedCompiledShaderState &shader = shaders[shaderType];
718*8975f5c5SAndroid Build Coastguard Worker        if (shader)
719*8975f5c5SAndroid Build Coastguard Worker        {
720*8975f5c5SAndroid Build Coastguard Worker            const std::vector<sh::Uniform> &uniforms = shader->uniforms;
721*8975f5c5SAndroid Build Coastguard Worker            InitDefaultUniformBlock(uniforms, &layoutMap[shaderType],
722*8975f5c5SAndroid Build Coastguard Worker                                    &requiredBufferSize[shaderType]);
723*8975f5c5SAndroid Build Coastguard Worker            // Set up block conversion buffer
724*8975f5c5SAndroid Build Coastguard Worker            initUniformBlocksRemapper(shader);
725*8975f5c5SAndroid Build Coastguard Worker        }
726*8975f5c5SAndroid Build Coastguard Worker    }
727*8975f5c5SAndroid Build Coastguard Worker
728*8975f5c5SAndroid Build Coastguard Worker    // Init the default block layout info.
729*8975f5c5SAndroid Build Coastguard Worker    const auto &uniforms         = mExecutable->getUniforms();
730*8975f5c5SAndroid Build Coastguard Worker    const auto &uniformNames     = mExecutable->getUniformNames();
731*8975f5c5SAndroid Build Coastguard Worker    const auto &uniformLocations = mExecutable->getUniformLocations();
732*8975f5c5SAndroid Build Coastguard Worker    for (size_t locSlot = 0; locSlot < uniformLocations.size(); ++locSlot)
733*8975f5c5SAndroid Build Coastguard Worker    {
734*8975f5c5SAndroid Build Coastguard Worker        const gl::VariableLocation &location = uniformLocations[locSlot];
735*8975f5c5SAndroid Build Coastguard Worker        gl::ShaderMap<sh::BlockMemberInfo> layoutInfo;
736*8975f5c5SAndroid Build Coastguard Worker
737*8975f5c5SAndroid Build Coastguard Worker        if (location.used() && !location.ignored)
738*8975f5c5SAndroid Build Coastguard Worker        {
739*8975f5c5SAndroid Build Coastguard Worker            const gl::LinkedUniform &uniform = uniforms[location.index];
740*8975f5c5SAndroid Build Coastguard Worker            if (uniform.isInDefaultBlock() && !uniform.isSampler() && !uniform.isImage())
741*8975f5c5SAndroid Build Coastguard Worker            {
742*8975f5c5SAndroid Build Coastguard Worker                std::string uniformName = uniformNames[location.index];
743*8975f5c5SAndroid Build Coastguard Worker                if (uniform.isArray())
744*8975f5c5SAndroid Build Coastguard Worker                {
745*8975f5c5SAndroid Build Coastguard Worker                    // Gets the uniform name without the [0] at the end.
746*8975f5c5SAndroid Build Coastguard Worker                    uniformName = gl::ParseResourceName(uniformName, nullptr);
747*8975f5c5SAndroid Build Coastguard Worker                }
748*8975f5c5SAndroid Build Coastguard Worker
749*8975f5c5SAndroid Build Coastguard Worker                bool found = false;
750*8975f5c5SAndroid Build Coastguard Worker
751*8975f5c5SAndroid Build Coastguard Worker                for (gl::ShaderType shaderType : gl::kAllGLES2ShaderTypes)
752*8975f5c5SAndroid Build Coastguard Worker                {
753*8975f5c5SAndroid Build Coastguard Worker                    auto it = layoutMap[shaderType].find(uniformName);
754*8975f5c5SAndroid Build Coastguard Worker                    if (it != layoutMap[shaderType].end())
755*8975f5c5SAndroid Build Coastguard Worker                    {
756*8975f5c5SAndroid Build Coastguard Worker                        found                  = true;
757*8975f5c5SAndroid Build Coastguard Worker                        layoutInfo[shaderType] = it->second;
758*8975f5c5SAndroid Build Coastguard Worker                    }
759*8975f5c5SAndroid Build Coastguard Worker                }
760*8975f5c5SAndroid Build Coastguard Worker
761*8975f5c5SAndroid Build Coastguard Worker                ASSERT(found);
762*8975f5c5SAndroid Build Coastguard Worker            }
763*8975f5c5SAndroid Build Coastguard Worker        }
764*8975f5c5SAndroid Build Coastguard Worker
765*8975f5c5SAndroid Build Coastguard Worker        for (gl::ShaderType shaderType : gl::kAllGLES2ShaderTypes)
766*8975f5c5SAndroid Build Coastguard Worker        {
767*8975f5c5SAndroid Build Coastguard Worker            mDefaultUniformBlocks[shaderType].uniformLayout.push_back(layoutInfo[shaderType]);
768*8975f5c5SAndroid Build Coastguard Worker        }
769*8975f5c5SAndroid Build Coastguard Worker    }
770*8975f5c5SAndroid Build Coastguard Worker
771*8975f5c5SAndroid Build Coastguard Worker    return resizeDefaultUniformBlocksMemory(context, requiredBufferSize);
772*8975f5c5SAndroid Build Coastguard Worker}
773*8975f5c5SAndroid Build Coastguard Worker
774*8975f5c5SAndroid Build Coastguard Workerangle::Result ProgramExecutableMtl::resizeDefaultUniformBlocksMemory(
775*8975f5c5SAndroid Build Coastguard Worker    mtl::Context *context,
776*8975f5c5SAndroid Build Coastguard Worker    const gl::ShaderMap<size_t> &requiredBufferSize)
777*8975f5c5SAndroid Build Coastguard Worker{
778*8975f5c5SAndroid Build Coastguard Worker    for (gl::ShaderType shaderType : gl::kAllGLES2ShaderTypes)
779*8975f5c5SAndroid Build Coastguard Worker    {
780*8975f5c5SAndroid Build Coastguard Worker        if (requiredBufferSize[shaderType] > 0)
781*8975f5c5SAndroid Build Coastguard Worker        {
782*8975f5c5SAndroid Build Coastguard Worker            ASSERT(requiredBufferSize[shaderType] <= mtl::kDefaultUniformsMaxSize);
783*8975f5c5SAndroid Build Coastguard Worker
784*8975f5c5SAndroid Build Coastguard Worker            if (!mDefaultUniformBlocks[shaderType].uniformData.resize(
785*8975f5c5SAndroid Build Coastguard Worker                    requiredBufferSize[shaderType]))
786*8975f5c5SAndroid Build Coastguard Worker            {
787*8975f5c5SAndroid Build Coastguard Worker                ANGLE_MTL_CHECK(context, false, GL_OUT_OF_MEMORY);
788*8975f5c5SAndroid Build Coastguard Worker            }
789*8975f5c5SAndroid Build Coastguard Worker
790*8975f5c5SAndroid Build Coastguard Worker            // Initialize uniform buffer memory to zero by default.
791*8975f5c5SAndroid Build Coastguard Worker            mDefaultUniformBlocks[shaderType].uniformData.fill(0);
792*8975f5c5SAndroid Build Coastguard Worker            mDefaultUniformBlocksDirty.set(shaderType);
793*8975f5c5SAndroid Build Coastguard Worker        }
794*8975f5c5SAndroid Build Coastguard Worker    }
795*8975f5c5SAndroid Build Coastguard Worker
796*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
797*8975f5c5SAndroid Build Coastguard Worker}
798*8975f5c5SAndroid Build Coastguard Worker
799*8975f5c5SAndroid Build Coastguard Worker// TODO(angleproject:7979) Upgrade ANGLE Uniform buffer remapper to compute shaders
800*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::initUniformBlocksRemapper(const gl::SharedCompiledShaderState &shader)
801*8975f5c5SAndroid Build Coastguard Worker{
802*8975f5c5SAndroid Build Coastguard Worker    std::unordered_map<std::string, UBOConversionInfo> conversionMap;
803*8975f5c5SAndroid Build Coastguard Worker    const std::vector<sh::InterfaceBlock> ibs = shader->uniformBlocks;
804*8975f5c5SAndroid Build Coastguard Worker    for (size_t i = 0; i < ibs.size(); ++i)
805*8975f5c5SAndroid Build Coastguard Worker    {
806*8975f5c5SAndroid Build Coastguard Worker
807*8975f5c5SAndroid Build Coastguard Worker        const sh::InterfaceBlock &ib = ibs[i];
808*8975f5c5SAndroid Build Coastguard Worker        if (mUniformBlockConversions.find(ib.name) == mUniformBlockConversions.end())
809*8975f5c5SAndroid Build Coastguard Worker        {
810*8975f5c5SAndroid Build Coastguard Worker            mtl::BlockLayoutEncoderMTL metalEncoder;
811*8975f5c5SAndroid Build Coastguard Worker            sh::BlockLayoutEncoder *encoder;
812*8975f5c5SAndroid Build Coastguard Worker            switch (ib.layout)
813*8975f5c5SAndroid Build Coastguard Worker            {
814*8975f5c5SAndroid Build Coastguard Worker                case sh::BLOCKLAYOUT_PACKED:
815*8975f5c5SAndroid Build Coastguard Worker                case sh::BLOCKLAYOUT_SHARED:
816*8975f5c5SAndroid Build Coastguard Worker                case sh::BLOCKLAYOUT_STD140:
817*8975f5c5SAndroid Build Coastguard Worker                {
818*8975f5c5SAndroid Build Coastguard Worker                    Std140BlockLayoutEncoderFactory factory;
819*8975f5c5SAndroid Build Coastguard Worker                    encoder = factory.makeEncoder();
820*8975f5c5SAndroid Build Coastguard Worker                }
821*8975f5c5SAndroid Build Coastguard Worker                break;
822*8975f5c5SAndroid Build Coastguard Worker                case sh::BLOCKLAYOUT_STD430:
823*8975f5c5SAndroid Build Coastguard Worker                {
824*8975f5c5SAndroid Build Coastguard Worker                    Std430BlockLayoutEncoderFactory factory;
825*8975f5c5SAndroid Build Coastguard Worker                    encoder = factory.makeEncoder();
826*8975f5c5SAndroid Build Coastguard Worker                }
827*8975f5c5SAndroid Build Coastguard Worker                break;
828*8975f5c5SAndroid Build Coastguard Worker            }
829*8975f5c5SAndroid Build Coastguard Worker            sh::BlockLayoutMap blockLayoutMapOut, stdMapOut;
830*8975f5c5SAndroid Build Coastguard Worker
831*8975f5c5SAndroid Build Coastguard Worker            sh::GetInterfaceBlockInfo(ib.fields, "", &metalEncoder, &blockLayoutMapOut);
832*8975f5c5SAndroid Build Coastguard Worker            sh::GetInterfaceBlockInfo(ib.fields, "", encoder, &stdMapOut);
833*8975f5c5SAndroid Build Coastguard Worker
834*8975f5c5SAndroid Build Coastguard Worker            auto stdIterator = stdMapOut.begin();
835*8975f5c5SAndroid Build Coastguard Worker            auto mtlIterator = blockLayoutMapOut.begin();
836*8975f5c5SAndroid Build Coastguard Worker
837*8975f5c5SAndroid Build Coastguard Worker            std::vector<sh::BlockMemberInfo> stdConversions, mtlConversions;
838*8975f5c5SAndroid Build Coastguard Worker            while (stdIterator != stdMapOut.end())
839*8975f5c5SAndroid Build Coastguard Worker            {
840*8975f5c5SAndroid Build Coastguard Worker                stdConversions.push_back(stdIterator->second);
841*8975f5c5SAndroid Build Coastguard Worker                mtlConversions.push_back(mtlIterator->second);
842*8975f5c5SAndroid Build Coastguard Worker                stdIterator++;
843*8975f5c5SAndroid Build Coastguard Worker                mtlIterator++;
844*8975f5c5SAndroid Build Coastguard Worker            }
845*8975f5c5SAndroid Build Coastguard Worker            std::sort(stdConversions.begin(), stdConversions.end(), CompareBlockInfo);
846*8975f5c5SAndroid Build Coastguard Worker            std::sort(mtlConversions.begin(), mtlConversions.end(), CompareBlockInfo);
847*8975f5c5SAndroid Build Coastguard Worker
848*8975f5c5SAndroid Build Coastguard Worker            size_t stdSize    = encoder->getCurrentOffset();
849*8975f5c5SAndroid Build Coastguard Worker            size_t metalAlign = GetAlignmentOfUniformGroup(&blockLayoutMapOut);
850*8975f5c5SAndroid Build Coastguard Worker            size_t metalSize  = roundUp(metalEncoder.getCurrentOffset(), metalAlign);
851*8975f5c5SAndroid Build Coastguard Worker
852*8975f5c5SAndroid Build Coastguard Worker            conversionMap.insert(
853*8975f5c5SAndroid Build Coastguard Worker                {ib.name, UBOConversionInfo(stdConversions, mtlConversions, stdSize, metalSize)});
854*8975f5c5SAndroid Build Coastguard Worker            SafeDelete(encoder);
855*8975f5c5SAndroid Build Coastguard Worker        }
856*8975f5c5SAndroid Build Coastguard Worker    }
857*8975f5c5SAndroid Build Coastguard Worker    mUniformBlockConversions.insert(conversionMap.begin(), conversionMap.end());
858*8975f5c5SAndroid Build Coastguard Worker}
859*8975f5c5SAndroid Build Coastguard Worker
860*8975f5c5SAndroid Build Coastguard Workermtl::BufferPool *ProgramExecutableMtl::getBufferPool(ContextMtl *context, gl::ShaderType shaderType)
861*8975f5c5SAndroid Build Coastguard Worker{
862*8975f5c5SAndroid Build Coastguard Worker    auto &pool = mDefaultUniformBufferPools[shaderType];
863*8975f5c5SAndroid Build Coastguard Worker    if (pool == nullptr)
864*8975f5c5SAndroid Build Coastguard Worker    {
865*8975f5c5SAndroid Build Coastguard Worker        DefaultUniformBlockMtl &uniformBlock = mDefaultUniformBlocks[shaderType];
866*8975f5c5SAndroid Build Coastguard Worker
867*8975f5c5SAndroid Build Coastguard Worker        // Size each buffer to hold 10 draw calls worth of uniform updates before creating extra
868*8975f5c5SAndroid Build Coastguard Worker        // buffers. This number was chosen loosely to balance the size of buffers versus the total
869*8975f5c5SAndroid Build Coastguard Worker        // number allocated. Without any sub-allocation, the total buffer count can reach the
870*8975f5c5SAndroid Build Coastguard Worker        // thousands when many draw calls are issued with the same program.
871*8975f5c5SAndroid Build Coastguard Worker        size_t bufferSize =
872*8975f5c5SAndroid Build Coastguard Worker            std::max(uniformBlock.uniformData.size() * 10, mtl::kDefaultUniformsMaxSize * 2);
873*8975f5c5SAndroid Build Coastguard Worker
874*8975f5c5SAndroid Build Coastguard Worker        pool.reset(new mtl::BufferPool(false));
875*8975f5c5SAndroid Build Coastguard Worker
876*8975f5c5SAndroid Build Coastguard Worker        // Allow unbounded growth of the buffer count. Doing a full CPU/GPU sync waiting for new
877*8975f5c5SAndroid Build Coastguard Worker        // uniform uploads has catastrophic performance cost.
878*8975f5c5SAndroid Build Coastguard Worker        pool->initialize(context, bufferSize, mtl::kUniformBufferSettingOffsetMinAlignment, 0);
879*8975f5c5SAndroid Build Coastguard Worker    }
880*8975f5c5SAndroid Build Coastguard Worker    return pool.get();
881*8975f5c5SAndroid Build Coastguard Worker}
882*8975f5c5SAndroid Build Coastguard Worker
883*8975f5c5SAndroid Build Coastguard Workerangle::Result ProgramExecutableMtl::setupDraw(const gl::Context *glContext,
884*8975f5c5SAndroid Build Coastguard Worker                                              mtl::RenderCommandEncoder *cmdEncoder,
885*8975f5c5SAndroid Build Coastguard Worker                                              const mtl::RenderPipelineDesc &pipelineDesc,
886*8975f5c5SAndroid Build Coastguard Worker                                              bool pipelineDescChanged,
887*8975f5c5SAndroid Build Coastguard Worker                                              bool forceTexturesSetting,
888*8975f5c5SAndroid Build Coastguard Worker                                              bool uniformBuffersDirty)
889*8975f5c5SAndroid Build Coastguard Worker{
890*8975f5c5SAndroid Build Coastguard Worker    ContextMtl *context = mtl::GetImpl(glContext);
891*8975f5c5SAndroid Build Coastguard Worker
892*8975f5c5SAndroid Build Coastguard Worker    if (pipelineDescChanged)
893*8975f5c5SAndroid Build Coastguard Worker    {
894*8975f5c5SAndroid Build Coastguard Worker        id<MTLFunction> vertexShader = nil;
895*8975f5c5SAndroid Build Coastguard Worker        ANGLE_TRY(
896*8975f5c5SAndroid Build Coastguard Worker            getSpecializedShader(context, gl::ShaderType::Vertex, pipelineDesc, &vertexShader));
897*8975f5c5SAndroid Build Coastguard Worker
898*8975f5c5SAndroid Build Coastguard Worker        id<MTLFunction> fragmentShader = nil;
899*8975f5c5SAndroid Build Coastguard Worker        ANGLE_TRY(
900*8975f5c5SAndroid Build Coastguard Worker            getSpecializedShader(context, gl::ShaderType::Fragment, pipelineDesc, &fragmentShader));
901*8975f5c5SAndroid Build Coastguard Worker
902*8975f5c5SAndroid Build Coastguard Worker        mtl::AutoObjCPtr<id<MTLRenderPipelineState>> pipelineState;
903*8975f5c5SAndroid Build Coastguard Worker        ANGLE_TRY(context->getPipelineCache().getRenderPipeline(
904*8975f5c5SAndroid Build Coastguard Worker            context, vertexShader, fragmentShader, pipelineDesc, &pipelineState));
905*8975f5c5SAndroid Build Coastguard Worker
906*8975f5c5SAndroid Build Coastguard Worker        cmdEncoder->setRenderPipelineState(pipelineState);
907*8975f5c5SAndroid Build Coastguard Worker
908*8975f5c5SAndroid Build Coastguard Worker        // We need to rebind uniform buffers & textures also
909*8975f5c5SAndroid Build Coastguard Worker        mDefaultUniformBlocksDirty.set();
910*8975f5c5SAndroid Build Coastguard Worker        mSamplerBindingsDirty.set();
911*8975f5c5SAndroid Build Coastguard Worker
912*8975f5c5SAndroid Build Coastguard Worker        // Cache current shader variant references for easier querying.
913*8975f5c5SAndroid Build Coastguard Worker        mCurrentShaderVariants[gl::ShaderType::Vertex] =
914*8975f5c5SAndroid Build Coastguard Worker            &mVertexShaderVariants[pipelineDesc.rasterizationType];
915*8975f5c5SAndroid Build Coastguard Worker
916*8975f5c5SAndroid Build Coastguard Worker        const bool multisampledRendering = pipelineDesc.outputDescriptor.rasterSampleCount > 1;
917*8975f5c5SAndroid Build Coastguard Worker        const bool allowFragDepthWrite =
918*8975f5c5SAndroid Build Coastguard Worker            pipelineDesc.outputDescriptor.depthAttachmentPixelFormat != 0;
919*8975f5c5SAndroid Build Coastguard Worker        mCurrentShaderVariants[gl::ShaderType::Fragment] =
920*8975f5c5SAndroid Build Coastguard Worker            pipelineDesc.rasterizationEnabled()
921*8975f5c5SAndroid Build Coastguard Worker                ? &mFragmentShaderVariants[PipelineParametersToFragmentShaderVariantIndex(
922*8975f5c5SAndroid Build Coastguard Worker                      multisampledRendering, allowFragDepthWrite)]
923*8975f5c5SAndroid Build Coastguard Worker                : nullptr;
924*8975f5c5SAndroid Build Coastguard Worker    }
925*8975f5c5SAndroid Build Coastguard Worker
926*8975f5c5SAndroid Build Coastguard Worker    ANGLE_TRY(commitUniforms(context, cmdEncoder));
927*8975f5c5SAndroid Build Coastguard Worker    ANGLE_TRY(updateTextures(glContext, cmdEncoder, forceTexturesSetting));
928*8975f5c5SAndroid Build Coastguard Worker
929*8975f5c5SAndroid Build Coastguard Worker    if (uniformBuffersDirty || pipelineDescChanged)
930*8975f5c5SAndroid Build Coastguard Worker    {
931*8975f5c5SAndroid Build Coastguard Worker        ANGLE_TRY(updateUniformBuffers(context, cmdEncoder, pipelineDesc));
932*8975f5c5SAndroid Build Coastguard Worker    }
933*8975f5c5SAndroid Build Coastguard Worker
934*8975f5c5SAndroid Build Coastguard Worker    if (pipelineDescChanged)
935*8975f5c5SAndroid Build Coastguard Worker    {
936*8975f5c5SAndroid Build Coastguard Worker        ANGLE_TRY(updateXfbBuffers(context, cmdEncoder, pipelineDesc));
937*8975f5c5SAndroid Build Coastguard Worker    }
938*8975f5c5SAndroid Build Coastguard Worker
939*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
940*8975f5c5SAndroid Build Coastguard Worker}
941*8975f5c5SAndroid Build Coastguard Worker
942*8975f5c5SAndroid Build Coastguard Workerangle::Result ProgramExecutableMtl::getSpecializedShader(
943*8975f5c5SAndroid Build Coastguard Worker    ContextMtl *context,
944*8975f5c5SAndroid Build Coastguard Worker    gl::ShaderType shaderType,
945*8975f5c5SAndroid Build Coastguard Worker    const mtl::RenderPipelineDesc &renderPipelineDesc,
946*8975f5c5SAndroid Build Coastguard Worker    id<MTLFunction> *shaderOut)
947*8975f5c5SAndroid Build Coastguard Worker{
948*8975f5c5SAndroid Build Coastguard Worker    static_assert(YES == 1, "YES should have value of 1");
949*8975f5c5SAndroid Build Coastguard Worker
950*8975f5c5SAndroid Build Coastguard Worker    mtl::TranslatedShaderInfo *translatedMslInfo = &mMslShaderTranslateInfo[shaderType];
951*8975f5c5SAndroid Build Coastguard Worker    ProgramShaderObjVariantMtl *shaderVariant;
952*8975f5c5SAndroid Build Coastguard Worker    mtl::AutoObjCObj<MTLFunctionConstantValues> funcConstants;
953*8975f5c5SAndroid Build Coastguard Worker
954*8975f5c5SAndroid Build Coastguard Worker    if (shaderType == gl::ShaderType::Vertex)
955*8975f5c5SAndroid Build Coastguard Worker    {
956*8975f5c5SAndroid Build Coastguard Worker        // For vertex shader, we need to create 3 variants, one with emulated rasterization
957*8975f5c5SAndroid Build Coastguard Worker        // discard, one with true rasterization discard and one without.
958*8975f5c5SAndroid Build Coastguard Worker        shaderVariant = &mVertexShaderVariants[renderPipelineDesc.rasterizationType];
959*8975f5c5SAndroid Build Coastguard Worker        if (shaderVariant->metalShader)
960*8975f5c5SAndroid Build Coastguard Worker        {
961*8975f5c5SAndroid Build Coastguard Worker            // Already created.
962*8975f5c5SAndroid Build Coastguard Worker            *shaderOut = shaderVariant->metalShader;
963*8975f5c5SAndroid Build Coastguard Worker            return angle::Result::Continue;
964*8975f5c5SAndroid Build Coastguard Worker        }
965*8975f5c5SAndroid Build Coastguard Worker
966*8975f5c5SAndroid Build Coastguard Worker        if (renderPipelineDesc.rasterizationType == mtl::RenderPipelineRasterization::Disabled)
967*8975f5c5SAndroid Build Coastguard Worker        {
968*8975f5c5SAndroid Build Coastguard Worker            // Special case: XFB output only vertex shader.
969*8975f5c5SAndroid Build Coastguard Worker            ASSERT(!mExecutable->getLinkedTransformFeedbackVaryings().empty());
970*8975f5c5SAndroid Build Coastguard Worker            translatedMslInfo = &mMslXfbOnlyVertexShaderInfo;
971*8975f5c5SAndroid Build Coastguard Worker            if (!translatedMslInfo->metalLibrary)
972*8975f5c5SAndroid Build Coastguard Worker            {
973*8975f5c5SAndroid Build Coastguard Worker                // Lazily compile XFB only shader
974*8975f5c5SAndroid Build Coastguard Worker                gl::InfoLog infoLog;
975*8975f5c5SAndroid Build Coastguard Worker                ANGLE_TRY(CreateMslShaderLib(context, infoLog, &mMslXfbOnlyVertexShaderInfo,
976*8975f5c5SAndroid Build Coastguard Worker                                             {{"TRANSFORM_FEEDBACK_ENABLED", "1"}}));
977*8975f5c5SAndroid Build Coastguard Worker                translatedMslInfo->metalLibrary.get().label = @"TransformFeedback";
978*8975f5c5SAndroid Build Coastguard Worker            }
979*8975f5c5SAndroid Build Coastguard Worker        }
980*8975f5c5SAndroid Build Coastguard Worker
981*8975f5c5SAndroid Build Coastguard Worker        ANGLE_MTL_OBJC_SCOPE
982*8975f5c5SAndroid Build Coastguard Worker        {
983*8975f5c5SAndroid Build Coastguard Worker            BOOL emulateDiscard = renderPipelineDesc.rasterizationType ==
984*8975f5c5SAndroid Build Coastguard Worker                                  mtl::RenderPipelineRasterization::EmulatedDiscard;
985*8975f5c5SAndroid Build Coastguard Worker
986*8975f5c5SAndroid Build Coastguard Worker            NSString *discardEnabledStr =
987*8975f5c5SAndroid Build Coastguard Worker                [NSString stringWithUTF8String:sh::mtl::kRasterizerDiscardEnabledConstName];
988*8975f5c5SAndroid Build Coastguard Worker
989*8975f5c5SAndroid Build Coastguard Worker            funcConstants = mtl::adoptObjCObj([[MTLFunctionConstantValues alloc] init]);
990*8975f5c5SAndroid Build Coastguard Worker            [funcConstants setConstantValue:&emulateDiscard
991*8975f5c5SAndroid Build Coastguard Worker                                       type:MTLDataTypeBool
992*8975f5c5SAndroid Build Coastguard Worker                                   withName:discardEnabledStr];
993*8975f5c5SAndroid Build Coastguard Worker        }
994*8975f5c5SAndroid Build Coastguard Worker    }  // if (shaderType == gl::ShaderType::Vertex)
995*8975f5c5SAndroid Build Coastguard Worker    else if (shaderType == gl::ShaderType::Fragment)
996*8975f5c5SAndroid Build Coastguard Worker    {
997*8975f5c5SAndroid Build Coastguard Worker        // For fragment shader, we need to create 4 variants,
998*8975f5c5SAndroid Build Coastguard Worker        // combining multisampled rendering and depth write enabled states.
999*8975f5c5SAndroid Build Coastguard Worker        const bool multisampledRendering =
1000*8975f5c5SAndroid Build Coastguard Worker            renderPipelineDesc.outputDescriptor.rasterSampleCount > 1;
1001*8975f5c5SAndroid Build Coastguard Worker        const bool allowFragDepthWrite =
1002*8975f5c5SAndroid Build Coastguard Worker            renderPipelineDesc.outputDescriptor.depthAttachmentPixelFormat != 0;
1003*8975f5c5SAndroid Build Coastguard Worker        shaderVariant = &mFragmentShaderVariants[PipelineParametersToFragmentShaderVariantIndex(
1004*8975f5c5SAndroid Build Coastguard Worker            multisampledRendering, allowFragDepthWrite)];
1005*8975f5c5SAndroid Build Coastguard Worker        if (shaderVariant->metalShader)
1006*8975f5c5SAndroid Build Coastguard Worker        {
1007*8975f5c5SAndroid Build Coastguard Worker            // Already created.
1008*8975f5c5SAndroid Build Coastguard Worker            *shaderOut = shaderVariant->metalShader;
1009*8975f5c5SAndroid Build Coastguard Worker            return angle::Result::Continue;
1010*8975f5c5SAndroid Build Coastguard Worker        }
1011*8975f5c5SAndroid Build Coastguard Worker
1012*8975f5c5SAndroid Build Coastguard Worker        ANGLE_MTL_OBJC_SCOPE
1013*8975f5c5SAndroid Build Coastguard Worker        {
1014*8975f5c5SAndroid Build Coastguard Worker            NSString *multisampledRenderingStr =
1015*8975f5c5SAndroid Build Coastguard Worker                [NSString stringWithUTF8String:sh::mtl::kMultisampledRenderingConstName];
1016*8975f5c5SAndroid Build Coastguard Worker
1017*8975f5c5SAndroid Build Coastguard Worker            NSString *depthWriteEnabledStr =
1018*8975f5c5SAndroid Build Coastguard Worker                [NSString stringWithUTF8String:sh::mtl::kDepthWriteEnabledConstName];
1019*8975f5c5SAndroid Build Coastguard Worker
1020*8975f5c5SAndroid Build Coastguard Worker            funcConstants = mtl::adoptObjCObj([[MTLFunctionConstantValues alloc] init]);
1021*8975f5c5SAndroid Build Coastguard Worker            [funcConstants setConstantValue:&multisampledRendering
1022*8975f5c5SAndroid Build Coastguard Worker                                       type:MTLDataTypeBool
1023*8975f5c5SAndroid Build Coastguard Worker                                   withName:multisampledRenderingStr];
1024*8975f5c5SAndroid Build Coastguard Worker            [funcConstants setConstantValue:&allowFragDepthWrite
1025*8975f5c5SAndroid Build Coastguard Worker                                       type:MTLDataTypeBool
1026*8975f5c5SAndroid Build Coastguard Worker                                   withName:depthWriteEnabledStr];
1027*8975f5c5SAndroid Build Coastguard Worker        }
1028*8975f5c5SAndroid Build Coastguard Worker
1029*8975f5c5SAndroid Build Coastguard Worker    }  // gl::ShaderType::Fragment
1030*8975f5c5SAndroid Build Coastguard Worker    else
1031*8975f5c5SAndroid Build Coastguard Worker    {
1032*8975f5c5SAndroid Build Coastguard Worker        UNREACHABLE();
1033*8975f5c5SAndroid Build Coastguard Worker        return angle::Result::Stop;
1034*8975f5c5SAndroid Build Coastguard Worker    }
1035*8975f5c5SAndroid Build Coastguard Worker    [funcConstants
1036*8975f5c5SAndroid Build Coastguard Worker        setConstantValue:&(context->getDisplay()->getFeatures().allowSamplerCompareGradient.enabled)
1037*8975f5c5SAndroid Build Coastguard Worker                    type:MTLDataTypeBool
1038*8975f5c5SAndroid Build Coastguard Worker                withName:@"ANGLEUseSampleCompareGradient"];
1039*8975f5c5SAndroid Build Coastguard Worker    [funcConstants
1040*8975f5c5SAndroid Build Coastguard Worker        setConstantValue:&(context->getDisplay()->getFeatures().emulateAlphaToCoverage.enabled)
1041*8975f5c5SAndroid Build Coastguard Worker                    type:MTLDataTypeBool
1042*8975f5c5SAndroid Build Coastguard Worker                withName:@"ANGLEEmulateAlphaToCoverage"];
1043*8975f5c5SAndroid Build Coastguard Worker    [funcConstants
1044*8975f5c5SAndroid Build Coastguard Worker        setConstantValue:&(context->getDisplay()->getFeatures().writeHelperSampleMask.enabled)
1045*8975f5c5SAndroid Build Coastguard Worker                    type:MTLDataTypeBool
1046*8975f5c5SAndroid Build Coastguard Worker                withName:@"ANGLEWriteHelperSampleMask"];
1047*8975f5c5SAndroid Build Coastguard Worker    // Create Metal shader object
1048*8975f5c5SAndroid Build Coastguard Worker    ANGLE_MTL_OBJC_SCOPE
1049*8975f5c5SAndroid Build Coastguard Worker    {
1050*8975f5c5SAndroid Build Coastguard Worker        ANGLE_TRY(CreateMslShader(context, translatedMslInfo->metalLibrary, SHADER_ENTRY_NAME,
1051*8975f5c5SAndroid Build Coastguard Worker                                  funcConstants.get(), &shaderVariant->metalShader));
1052*8975f5c5SAndroid Build Coastguard Worker    }
1053*8975f5c5SAndroid Build Coastguard Worker
1054*8975f5c5SAndroid Build Coastguard Worker    // Store reference to the translated source for easily querying mapped bindings later.
1055*8975f5c5SAndroid Build Coastguard Worker    shaderVariant->translatedSrcInfo = translatedMslInfo;
1056*8975f5c5SAndroid Build Coastguard Worker
1057*8975f5c5SAndroid Build Coastguard Worker    // Initialize argument buffer encoder if required
1058*8975f5c5SAndroid Build Coastguard Worker    if (translatedMslInfo->hasUBOArgumentBuffer)
1059*8975f5c5SAndroid Build Coastguard Worker    {
1060*8975f5c5SAndroid Build Coastguard Worker        InitArgumentBufferEncoder(context, shaderVariant->metalShader,
1061*8975f5c5SAndroid Build Coastguard Worker                                  mtl::kUBOArgumentBufferBindingIndex,
1062*8975f5c5SAndroid Build Coastguard Worker                                  &shaderVariant->uboArgBufferEncoder);
1063*8975f5c5SAndroid Build Coastguard Worker    }
1064*8975f5c5SAndroid Build Coastguard Worker
1065*8975f5c5SAndroid Build Coastguard Worker    *shaderOut = shaderVariant->metalShader;
1066*8975f5c5SAndroid Build Coastguard Worker
1067*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
1068*8975f5c5SAndroid Build Coastguard Worker}
1069*8975f5c5SAndroid Build Coastguard Worker
1070*8975f5c5SAndroid Build Coastguard Workerangle::Result ProgramExecutableMtl::commitUniforms(ContextMtl *context,
1071*8975f5c5SAndroid Build Coastguard Worker                                                   mtl::RenderCommandEncoder *cmdEncoder)
1072*8975f5c5SAndroid Build Coastguard Worker{
1073*8975f5c5SAndroid Build Coastguard Worker    for (gl::ShaderType shaderType : gl::kAllGLES2ShaderTypes)
1074*8975f5c5SAndroid Build Coastguard Worker    {
1075*8975f5c5SAndroid Build Coastguard Worker        if (!mDefaultUniformBlocksDirty[shaderType] || !mCurrentShaderVariants[shaderType])
1076*8975f5c5SAndroid Build Coastguard Worker        {
1077*8975f5c5SAndroid Build Coastguard Worker            continue;
1078*8975f5c5SAndroid Build Coastguard Worker        }
1079*8975f5c5SAndroid Build Coastguard Worker        DefaultUniformBlockMtl &uniformBlock = mDefaultUniformBlocks[shaderType];
1080*8975f5c5SAndroid Build Coastguard Worker
1081*8975f5c5SAndroid Build Coastguard Worker        if (!uniformBlock.uniformData.size())
1082*8975f5c5SAndroid Build Coastguard Worker        {
1083*8975f5c5SAndroid Build Coastguard Worker            continue;
1084*8975f5c5SAndroid Build Coastguard Worker        }
1085*8975f5c5SAndroid Build Coastguard Worker
1086*8975f5c5SAndroid Build Coastguard Worker        // If we exceed the default inline max size, try to allocate a buffer
1087*8975f5c5SAndroid Build Coastguard Worker        bool needsCommitUniform = true;
1088*8975f5c5SAndroid Build Coastguard Worker        if (needsCommitUniform && uniformBlock.uniformData.size() <= mtl::kInlineConstDataMaxSize)
1089*8975f5c5SAndroid Build Coastguard Worker        {
1090*8975f5c5SAndroid Build Coastguard Worker            ASSERT(uniformBlock.uniformData.size() <= mtl::kInlineConstDataMaxSize);
1091*8975f5c5SAndroid Build Coastguard Worker            cmdEncoder->setBytes(shaderType, uniformBlock.uniformData.data(),
1092*8975f5c5SAndroid Build Coastguard Worker                                 uniformBlock.uniformData.size(),
1093*8975f5c5SAndroid Build Coastguard Worker                                 mtl::kDefaultUniformsBindingIndex);
1094*8975f5c5SAndroid Build Coastguard Worker        }
1095*8975f5c5SAndroid Build Coastguard Worker        else if (needsCommitUniform)
1096*8975f5c5SAndroid Build Coastguard Worker        {
1097*8975f5c5SAndroid Build Coastguard Worker            mtl::BufferPool *bufferPool = getBufferPool(context, shaderType);
1098*8975f5c5SAndroid Build Coastguard Worker            bufferPool->releaseInFlightBuffers(context);
1099*8975f5c5SAndroid Build Coastguard Worker
1100*8975f5c5SAndroid Build Coastguard Worker            ASSERT(uniformBlock.uniformData.size() <= mtl::kDefaultUniformsMaxSize);
1101*8975f5c5SAndroid Build Coastguard Worker            mtl::BufferRef mtlBufferOut;
1102*8975f5c5SAndroid Build Coastguard Worker            size_t offsetOut;
1103*8975f5c5SAndroid Build Coastguard Worker            uint8_t *ptrOut;
1104*8975f5c5SAndroid Build Coastguard Worker            // Allocate a new Uniform buffer
1105*8975f5c5SAndroid Build Coastguard Worker            ANGLE_TRY(bufferPool->allocate(context, uniformBlock.uniformData.size(), &ptrOut,
1106*8975f5c5SAndroid Build Coastguard Worker                                           &mtlBufferOut, &offsetOut));
1107*8975f5c5SAndroid Build Coastguard Worker            // Copy the uniform result
1108*8975f5c5SAndroid Build Coastguard Worker            memcpy(ptrOut, uniformBlock.uniformData.data(), uniformBlock.uniformData.size());
1109*8975f5c5SAndroid Build Coastguard Worker            // Commit
1110*8975f5c5SAndroid Build Coastguard Worker            ANGLE_TRY(bufferPool->commit(context));
1111*8975f5c5SAndroid Build Coastguard Worker            // Set buffer
1112*8975f5c5SAndroid Build Coastguard Worker            cmdEncoder->setBuffer(shaderType, mtlBufferOut, (uint32_t)offsetOut,
1113*8975f5c5SAndroid Build Coastguard Worker                                  mtl::kDefaultUniformsBindingIndex);
1114*8975f5c5SAndroid Build Coastguard Worker        }
1115*8975f5c5SAndroid Build Coastguard Worker
1116*8975f5c5SAndroid Build Coastguard Worker        mDefaultUniformBlocksDirty.reset(shaderType);
1117*8975f5c5SAndroid Build Coastguard Worker    }
1118*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
1119*8975f5c5SAndroid Build Coastguard Worker}
1120*8975f5c5SAndroid Build Coastguard Worker
1121*8975f5c5SAndroid Build Coastguard Workerangle::Result ProgramExecutableMtl::updateTextures(const gl::Context *glContext,
1122*8975f5c5SAndroid Build Coastguard Worker                                                   mtl::RenderCommandEncoder *cmdEncoder,
1123*8975f5c5SAndroid Build Coastguard Worker                                                   bool forceUpdate)
1124*8975f5c5SAndroid Build Coastguard Worker{
1125*8975f5c5SAndroid Build Coastguard Worker    ContextMtl *contextMtl                          = mtl::GetImpl(glContext);
1126*8975f5c5SAndroid Build Coastguard Worker    const auto &glState                             = glContext->getState();
1127*8975f5c5SAndroid Build Coastguard Worker    const gl::ActiveTexturesCache &completeTextures = glState.getActiveTexturesCache();
1128*8975f5c5SAndroid Build Coastguard Worker
1129*8975f5c5SAndroid Build Coastguard Worker    for (gl::ShaderType shaderType : gl::kAllGLES2ShaderTypes)
1130*8975f5c5SAndroid Build Coastguard Worker    {
1131*8975f5c5SAndroid Build Coastguard Worker        if ((!mSamplerBindingsDirty[shaderType] && !forceUpdate) ||
1132*8975f5c5SAndroid Build Coastguard Worker            !mCurrentShaderVariants[shaderType])
1133*8975f5c5SAndroid Build Coastguard Worker        {
1134*8975f5c5SAndroid Build Coastguard Worker            continue;
1135*8975f5c5SAndroid Build Coastguard Worker        }
1136*8975f5c5SAndroid Build Coastguard Worker
1137*8975f5c5SAndroid Build Coastguard Worker        const mtl::TranslatedShaderInfo &shaderInfo =
1138*8975f5c5SAndroid Build Coastguard Worker            mCurrentShaderVariants[shaderType]->translatedSrcInfo
1139*8975f5c5SAndroid Build Coastguard Worker                ? *mCurrentShaderVariants[shaderType]->translatedSrcInfo
1140*8975f5c5SAndroid Build Coastguard Worker                : mMslShaderTranslateInfo[shaderType];
1141*8975f5c5SAndroid Build Coastguard Worker        bool hasDepthSampler = false;
1142*8975f5c5SAndroid Build Coastguard Worker
1143*8975f5c5SAndroid Build Coastguard Worker        for (uint32_t textureIndex = 0; textureIndex < mExecutable->getSamplerBindings().size();
1144*8975f5c5SAndroid Build Coastguard Worker             ++textureIndex)
1145*8975f5c5SAndroid Build Coastguard Worker        {
1146*8975f5c5SAndroid Build Coastguard Worker            const gl::SamplerBinding &samplerBinding =
1147*8975f5c5SAndroid Build Coastguard Worker                mExecutable->getSamplerBindings()[textureIndex];
1148*8975f5c5SAndroid Build Coastguard Worker            const mtl::SamplerBinding &mslBinding = shaderInfo.actualSamplerBindings[textureIndex];
1149*8975f5c5SAndroid Build Coastguard Worker            if (mslBinding.textureBinding >= mtl::kMaxShaderSamplers)
1150*8975f5c5SAndroid Build Coastguard Worker            {
1151*8975f5c5SAndroid Build Coastguard Worker                // No binding assigned
1152*8975f5c5SAndroid Build Coastguard Worker                continue;
1153*8975f5c5SAndroid Build Coastguard Worker            }
1154*8975f5c5SAndroid Build Coastguard Worker
1155*8975f5c5SAndroid Build Coastguard Worker            gl::TextureType textureType = samplerBinding.textureType;
1156*8975f5c5SAndroid Build Coastguard Worker
1157*8975f5c5SAndroid Build Coastguard Worker            for (uint32_t arrayElement = 0; arrayElement < samplerBinding.textureUnitsCount;
1158*8975f5c5SAndroid Build Coastguard Worker                 ++arrayElement)
1159*8975f5c5SAndroid Build Coastguard Worker            {
1160*8975f5c5SAndroid Build Coastguard Worker                GLuint textureUnit = samplerBinding.getTextureUnit(
1161*8975f5c5SAndroid Build Coastguard Worker                    mExecutable->getSamplerBoundTextureUnits(), arrayElement);
1162*8975f5c5SAndroid Build Coastguard Worker                gl::Texture *texture = completeTextures[textureUnit];
1163*8975f5c5SAndroid Build Coastguard Worker                gl::Sampler *sampler = contextMtl->getState().getSampler(textureUnit);
1164*8975f5c5SAndroid Build Coastguard Worker                uint32_t textureSlot = mslBinding.textureBinding + arrayElement;
1165*8975f5c5SAndroid Build Coastguard Worker                uint32_t samplerSlot = mslBinding.samplerBinding + arrayElement;
1166*8975f5c5SAndroid Build Coastguard Worker                if (!texture)
1167*8975f5c5SAndroid Build Coastguard Worker                {
1168*8975f5c5SAndroid Build Coastguard Worker                    ANGLE_TRY(contextMtl->getIncompleteTexture(glContext, textureType,
1169*8975f5c5SAndroid Build Coastguard Worker                                                               samplerBinding.format, &texture));
1170*8975f5c5SAndroid Build Coastguard Worker                }
1171*8975f5c5SAndroid Build Coastguard Worker                const gl::SamplerState *samplerState =
1172*8975f5c5SAndroid Build Coastguard Worker                    sampler ? &sampler->getSamplerState() : &texture->getSamplerState();
1173*8975f5c5SAndroid Build Coastguard Worker                TextureMtl *textureMtl = mtl::GetImpl(texture);
1174*8975f5c5SAndroid Build Coastguard Worker                if (samplerBinding.format == gl::SamplerFormat::Shadow)
1175*8975f5c5SAndroid Build Coastguard Worker                {
1176*8975f5c5SAndroid Build Coastguard Worker                    hasDepthSampler                  = true;
1177*8975f5c5SAndroid Build Coastguard Worker                    mShadowCompareModes[textureSlot] = mtl::MslGetShaderShadowCompareMode(
1178*8975f5c5SAndroid Build Coastguard Worker                        samplerState->getCompareMode(), samplerState->getCompareFunc());
1179*8975f5c5SAndroid Build Coastguard Worker                }
1180*8975f5c5SAndroid Build Coastguard Worker                ANGLE_TRY(textureMtl->bindToShader(glContext, cmdEncoder, shaderType, sampler,
1181*8975f5c5SAndroid Build Coastguard Worker                                                   textureSlot, samplerSlot));
1182*8975f5c5SAndroid Build Coastguard Worker            }  // for array elements
1183*8975f5c5SAndroid Build Coastguard Worker        }      // for sampler bindings
1184*8975f5c5SAndroid Build Coastguard Worker
1185*8975f5c5SAndroid Build Coastguard Worker        if (hasDepthSampler)
1186*8975f5c5SAndroid Build Coastguard Worker        {
1187*8975f5c5SAndroid Build Coastguard Worker            cmdEncoder->setData(shaderType, mShadowCompareModes,
1188*8975f5c5SAndroid Build Coastguard Worker                                mtl::kShadowSamplerCompareModesBindingIndex);
1189*8975f5c5SAndroid Build Coastguard Worker        }
1190*8975f5c5SAndroid Build Coastguard Worker
1191*8975f5c5SAndroid Build Coastguard Worker        for (const gl::ImageBinding &imageBinding : mExecutable->getImageBindings())
1192*8975f5c5SAndroid Build Coastguard Worker        {
1193*8975f5c5SAndroid Build Coastguard Worker            if (imageBinding.boundImageUnits.size() != 1)
1194*8975f5c5SAndroid Build Coastguard Worker            {
1195*8975f5c5SAndroid Build Coastguard Worker                UNIMPLEMENTED();
1196*8975f5c5SAndroid Build Coastguard Worker                continue;
1197*8975f5c5SAndroid Build Coastguard Worker            }
1198*8975f5c5SAndroid Build Coastguard Worker
1199*8975f5c5SAndroid Build Coastguard Worker            int glslImageBinding    = imageBinding.boundImageUnits[0];
1200*8975f5c5SAndroid Build Coastguard Worker            int mtlRWTextureBinding = shaderInfo.actualImageBindings[glslImageBinding];
1201*8975f5c5SAndroid Build Coastguard Worker            ASSERT(mtlRWTextureBinding < static_cast<int>(mtl::kMaxShaderImages));
1202*8975f5c5SAndroid Build Coastguard Worker            if (mtlRWTextureBinding < 0)
1203*8975f5c5SAndroid Build Coastguard Worker            {
1204*8975f5c5SAndroid Build Coastguard Worker                continue;  // The program does not have an image bound at this unit.
1205*8975f5c5SAndroid Build Coastguard Worker            }
1206*8975f5c5SAndroid Build Coastguard Worker
1207*8975f5c5SAndroid Build Coastguard Worker            const gl::ImageUnit &imageUnit = glState.getImageUnit(glslImageBinding);
1208*8975f5c5SAndroid Build Coastguard Worker            TextureMtl *textureMtl         = mtl::GetImpl(imageUnit.texture.get());
1209*8975f5c5SAndroid Build Coastguard Worker            if (imageUnit.layered)
1210*8975f5c5SAndroid Build Coastguard Worker            {
1211*8975f5c5SAndroid Build Coastguard Worker                UNIMPLEMENTED();
1212*8975f5c5SAndroid Build Coastguard Worker                continue;
1213*8975f5c5SAndroid Build Coastguard Worker            }
1214*8975f5c5SAndroid Build Coastguard Worker            ANGLE_TRY(textureMtl->bindToShaderImage(
1215*8975f5c5SAndroid Build Coastguard Worker                glContext, cmdEncoder, shaderType, static_cast<uint32_t>(mtlRWTextureBinding),
1216*8975f5c5SAndroid Build Coastguard Worker                imageUnit.level, imageUnit.layer, imageUnit.format));
1217*8975f5c5SAndroid Build Coastguard Worker        }
1218*8975f5c5SAndroid Build Coastguard Worker    }  // for shader types
1219*8975f5c5SAndroid Build Coastguard Worker
1220*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
1221*8975f5c5SAndroid Build Coastguard Worker}
1222*8975f5c5SAndroid Build Coastguard Worker
1223*8975f5c5SAndroid Build Coastguard Workerangle::Result ProgramExecutableMtl::updateUniformBuffers(
1224*8975f5c5SAndroid Build Coastguard Worker    ContextMtl *context,
1225*8975f5c5SAndroid Build Coastguard Worker    mtl::RenderCommandEncoder *cmdEncoder,
1226*8975f5c5SAndroid Build Coastguard Worker    const mtl::RenderPipelineDesc &pipelineDesc)
1227*8975f5c5SAndroid Build Coastguard Worker{
1228*8975f5c5SAndroid Build Coastguard Worker    const std::vector<gl::InterfaceBlock> &blocks = mExecutable->getUniformBlocks();
1229*8975f5c5SAndroid Build Coastguard Worker    if (blocks.empty())
1230*8975f5c5SAndroid Build Coastguard Worker    {
1231*8975f5c5SAndroid Build Coastguard Worker        return angle::Result::Continue;
1232*8975f5c5SAndroid Build Coastguard Worker    }
1233*8975f5c5SAndroid Build Coastguard Worker
1234*8975f5c5SAndroid Build Coastguard Worker    // This array is only used inside this function and its callees.
1235*8975f5c5SAndroid Build Coastguard Worker    ScopedAutoClearVector<uint32_t> scopeArrayClear(&mArgumentBufferRenderStageUsages);
1236*8975f5c5SAndroid Build Coastguard Worker    ScopedAutoClearVector<std::pair<mtl::BufferRef, uint32_t>> scopeArrayClear2(
1237*8975f5c5SAndroid Build Coastguard Worker        &mLegalizedOffsetedUniformBuffers);
1238*8975f5c5SAndroid Build Coastguard Worker    mArgumentBufferRenderStageUsages.resize(blocks.size());
1239*8975f5c5SAndroid Build Coastguard Worker    mLegalizedOffsetedUniformBuffers.resize(blocks.size());
1240*8975f5c5SAndroid Build Coastguard Worker
1241*8975f5c5SAndroid Build Coastguard Worker    ANGLE_TRY(legalizeUniformBufferOffsets(context));
1242*8975f5c5SAndroid Build Coastguard Worker
1243*8975f5c5SAndroid Build Coastguard Worker    const gl::State &glState = context->getState();
1244*8975f5c5SAndroid Build Coastguard Worker
1245*8975f5c5SAndroid Build Coastguard Worker    for (gl::ShaderType shaderType : gl::kAllGLES2ShaderTypes)
1246*8975f5c5SAndroid Build Coastguard Worker    {
1247*8975f5c5SAndroid Build Coastguard Worker        if (!mCurrentShaderVariants[shaderType])
1248*8975f5c5SAndroid Build Coastguard Worker        {
1249*8975f5c5SAndroid Build Coastguard Worker            continue;
1250*8975f5c5SAndroid Build Coastguard Worker        }
1251*8975f5c5SAndroid Build Coastguard Worker
1252*8975f5c5SAndroid Build Coastguard Worker        if (mCurrentShaderVariants[shaderType]->translatedSrcInfo->hasUBOArgumentBuffer)
1253*8975f5c5SAndroid Build Coastguard Worker        {
1254*8975f5c5SAndroid Build Coastguard Worker            ANGLE_TRY(encodeUniformBuffersInfoArgumentBuffer(context, cmdEncoder, shaderType));
1255*8975f5c5SAndroid Build Coastguard Worker        }
1256*8975f5c5SAndroid Build Coastguard Worker        else
1257*8975f5c5SAndroid Build Coastguard Worker        {
1258*8975f5c5SAndroid Build Coastguard Worker            ANGLE_TRY(bindUniformBuffersToDiscreteSlots(context, cmdEncoder, shaderType));
1259*8975f5c5SAndroid Build Coastguard Worker        }
1260*8975f5c5SAndroid Build Coastguard Worker    }  // for shader types
1261*8975f5c5SAndroid Build Coastguard Worker
1262*8975f5c5SAndroid Build Coastguard Worker    // After encode the uniform buffers into an argument buffer, we need to tell Metal that
1263*8975f5c5SAndroid Build Coastguard Worker    // the buffers are being used by what shader stages.
1264*8975f5c5SAndroid Build Coastguard Worker    for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
1265*8975f5c5SAndroid Build Coastguard Worker    {
1266*8975f5c5SAndroid Build Coastguard Worker        const GLuint binding = mExecutable->getUniformBlockBinding(bufferIndex);
1267*8975f5c5SAndroid Build Coastguard Worker        const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
1268*8975f5c5SAndroid Build Coastguard Worker            glState.getIndexedUniformBuffer(binding);
1269*8975f5c5SAndroid Build Coastguard Worker        if (bufferBinding.get() == nullptr)
1270*8975f5c5SAndroid Build Coastguard Worker        {
1271*8975f5c5SAndroid Build Coastguard Worker            continue;
1272*8975f5c5SAndroid Build Coastguard Worker        }
1273*8975f5c5SAndroid Build Coastguard Worker
1274*8975f5c5SAndroid Build Coastguard Worker        // Remove any other stages other than vertex and fragment.
1275*8975f5c5SAndroid Build Coastguard Worker        uint32_t stages = mArgumentBufferRenderStageUsages[bufferIndex] &
1276*8975f5c5SAndroid Build Coastguard Worker                          (MTLRenderStageVertex | MTLRenderStageFragment);
1277*8975f5c5SAndroid Build Coastguard Worker
1278*8975f5c5SAndroid Build Coastguard Worker        if (stages == 0)
1279*8975f5c5SAndroid Build Coastguard Worker        {
1280*8975f5c5SAndroid Build Coastguard Worker            continue;
1281*8975f5c5SAndroid Build Coastguard Worker        }
1282*8975f5c5SAndroid Build Coastguard Worker
1283*8975f5c5SAndroid Build Coastguard Worker        cmdEncoder->useResource(mLegalizedOffsetedUniformBuffers[bufferIndex].first,
1284*8975f5c5SAndroid Build Coastguard Worker                                MTLResourceUsageRead, static_cast<MTLRenderStages>(stages));
1285*8975f5c5SAndroid Build Coastguard Worker    }
1286*8975f5c5SAndroid Build Coastguard Worker
1287*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
1288*8975f5c5SAndroid Build Coastguard Worker}
1289*8975f5c5SAndroid Build Coastguard Worker
1290*8975f5c5SAndroid Build Coastguard Workerangle::Result ProgramExecutableMtl::legalizeUniformBufferOffsets(ContextMtl *context)
1291*8975f5c5SAndroid Build Coastguard Worker{
1292*8975f5c5SAndroid Build Coastguard Worker    const gl::State &glState                      = context->getState();
1293*8975f5c5SAndroid Build Coastguard Worker    const std::vector<gl::InterfaceBlock> &blocks = mExecutable->getUniformBlocks();
1294*8975f5c5SAndroid Build Coastguard Worker
1295*8975f5c5SAndroid Build Coastguard Worker    for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
1296*8975f5c5SAndroid Build Coastguard Worker    {
1297*8975f5c5SAndroid Build Coastguard Worker        const gl::InterfaceBlock &block = blocks[bufferIndex];
1298*8975f5c5SAndroid Build Coastguard Worker        const GLuint binding            = mExecutable->getUniformBlockBinding(bufferIndex);
1299*8975f5c5SAndroid Build Coastguard Worker        const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
1300*8975f5c5SAndroid Build Coastguard Worker            glState.getIndexedUniformBuffer(binding);
1301*8975f5c5SAndroid Build Coastguard Worker
1302*8975f5c5SAndroid Build Coastguard Worker        if (bufferBinding.get() == nullptr)
1303*8975f5c5SAndroid Build Coastguard Worker        {
1304*8975f5c5SAndroid Build Coastguard Worker            continue;
1305*8975f5c5SAndroid Build Coastguard Worker        }
1306*8975f5c5SAndroid Build Coastguard Worker
1307*8975f5c5SAndroid Build Coastguard Worker        BufferMtl *bufferMtl = mtl::GetImpl(bufferBinding.get());
1308*8975f5c5SAndroid Build Coastguard Worker        size_t srcOffset     = std::min<size_t>(bufferBinding.getOffset(), bufferMtl->size());
1309*8975f5c5SAndroid Build Coastguard Worker        ASSERT(mUniformBlockConversions.find(block.name) != mUniformBlockConversions.end());
1310*8975f5c5SAndroid Build Coastguard Worker        const UBOConversionInfo &conversionInfo = mUniformBlockConversions.at(block.name);
1311*8975f5c5SAndroid Build Coastguard Worker
1312*8975f5c5SAndroid Build Coastguard Worker        size_t spaceAvailable  = bufferMtl->size() - srcOffset;
1313*8975f5c5SAndroid Build Coastguard Worker        bool haveSpaceInBuffer = conversionInfo.metalSize() <= spaceAvailable;
1314*8975f5c5SAndroid Build Coastguard Worker        if (conversionInfo.needsConversion() || !haveSpaceInBuffer)
1315*8975f5c5SAndroid Build Coastguard Worker        {
1316*8975f5c5SAndroid Build Coastguard Worker
1317*8975f5c5SAndroid Build Coastguard Worker            UniformConversionBufferMtl *conversion =
1318*8975f5c5SAndroid Build Coastguard Worker                (UniformConversionBufferMtl *)bufferMtl->getUniformConversionBuffer(
1319*8975f5c5SAndroid Build Coastguard Worker                    context, std::pair<size_t, size_t>(bufferIndex, srcOffset),
1320*8975f5c5SAndroid Build Coastguard Worker                    conversionInfo.stdSize());
1321*8975f5c5SAndroid Build Coastguard Worker            // Has the content of the buffer has changed since last conversion?
1322*8975f5c5SAndroid Build Coastguard Worker            if (conversion->dirty)
1323*8975f5c5SAndroid Build Coastguard Worker            {
1324*8975f5c5SAndroid Build Coastguard Worker                const uint8_t *srcBytes = bufferMtl->getBufferDataReadOnly(context);
1325*8975f5c5SAndroid Build Coastguard Worker                srcBytes += conversion->initialSrcOffset();
1326*8975f5c5SAndroid Build Coastguard Worker                size_t sizeToCopy = bufferMtl->size() - conversion->initialSrcOffset();
1327*8975f5c5SAndroid Build Coastguard Worker
1328*8975f5c5SAndroid Build Coastguard Worker                ANGLE_TRY(ConvertUniformBufferData(
1329*8975f5c5SAndroid Build Coastguard Worker                    context, conversionInfo, &conversion->data, srcBytes, sizeToCopy,
1330*8975f5c5SAndroid Build Coastguard Worker                    &conversion->convertedBuffer, &conversion->convertedOffset));
1331*8975f5c5SAndroid Build Coastguard Worker
1332*8975f5c5SAndroid Build Coastguard Worker                conversion->dirty = false;
1333*8975f5c5SAndroid Build Coastguard Worker            }
1334*8975f5c5SAndroid Build Coastguard Worker            // Calculate offset in new block.
1335*8975f5c5SAndroid Build Coastguard Worker            size_t dstOffsetSource = srcOffset - conversion->initialSrcOffset();
1336*8975f5c5SAndroid Build Coastguard Worker            ASSERT(dstOffsetSource % conversionInfo.stdSize() == 0);
1337*8975f5c5SAndroid Build Coastguard Worker            unsigned int numBlocksToOffset =
1338*8975f5c5SAndroid Build Coastguard Worker                (unsigned int)(dstOffsetSource / conversionInfo.stdSize());
1339*8975f5c5SAndroid Build Coastguard Worker            size_t bytesToOffset = numBlocksToOffset * conversionInfo.metalSize();
1340*8975f5c5SAndroid Build Coastguard Worker
1341*8975f5c5SAndroid Build Coastguard Worker            mLegalizedOffsetedUniformBuffers[bufferIndex].first = conversion->convertedBuffer;
1342*8975f5c5SAndroid Build Coastguard Worker            mLegalizedOffsetedUniformBuffers[bufferIndex].second =
1343*8975f5c5SAndroid Build Coastguard Worker                static_cast<uint32_t>(conversion->convertedOffset + bytesToOffset);
1344*8975f5c5SAndroid Build Coastguard Worker            // Ensure that the converted info can fit in the buffer.
1345*8975f5c5SAndroid Build Coastguard Worker            ASSERT(conversion->convertedOffset + bytesToOffset + conversionInfo.metalSize() <=
1346*8975f5c5SAndroid Build Coastguard Worker                   conversion->convertedBuffer->size());
1347*8975f5c5SAndroid Build Coastguard Worker        }
1348*8975f5c5SAndroid Build Coastguard Worker        else
1349*8975f5c5SAndroid Build Coastguard Worker        {
1350*8975f5c5SAndroid Build Coastguard Worker            mLegalizedOffsetedUniformBuffers[bufferIndex].first = bufferMtl->getCurrentBuffer();
1351*8975f5c5SAndroid Build Coastguard Worker            mLegalizedOffsetedUniformBuffers[bufferIndex].second =
1352*8975f5c5SAndroid Build Coastguard Worker                static_cast<uint32_t>(bufferBinding.getOffset());
1353*8975f5c5SAndroid Build Coastguard Worker        }
1354*8975f5c5SAndroid Build Coastguard Worker    }
1355*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
1356*8975f5c5SAndroid Build Coastguard Worker}
1357*8975f5c5SAndroid Build Coastguard Worker
1358*8975f5c5SAndroid Build Coastguard Workerangle::Result ProgramExecutableMtl::bindUniformBuffersToDiscreteSlots(
1359*8975f5c5SAndroid Build Coastguard Worker    ContextMtl *context,
1360*8975f5c5SAndroid Build Coastguard Worker    mtl::RenderCommandEncoder *cmdEncoder,
1361*8975f5c5SAndroid Build Coastguard Worker    gl::ShaderType shaderType)
1362*8975f5c5SAndroid Build Coastguard Worker{
1363*8975f5c5SAndroid Build Coastguard Worker    const gl::State &glState                      = context->getState();
1364*8975f5c5SAndroid Build Coastguard Worker    const std::vector<gl::InterfaceBlock> &blocks = mExecutable->getUniformBlocks();
1365*8975f5c5SAndroid Build Coastguard Worker    const mtl::TranslatedShaderInfo &shaderInfo =
1366*8975f5c5SAndroid Build Coastguard Worker        *mCurrentShaderVariants[shaderType]->translatedSrcInfo;
1367*8975f5c5SAndroid Build Coastguard Worker
1368*8975f5c5SAndroid Build Coastguard Worker    for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
1369*8975f5c5SAndroid Build Coastguard Worker    {
1370*8975f5c5SAndroid Build Coastguard Worker        const gl::InterfaceBlock &block = blocks[bufferIndex];
1371*8975f5c5SAndroid Build Coastguard Worker        const GLuint binding            = mExecutable->getUniformBlockBinding(bufferIndex);
1372*8975f5c5SAndroid Build Coastguard Worker        const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
1373*8975f5c5SAndroid Build Coastguard Worker            glState.getIndexedUniformBuffer(binding);
1374*8975f5c5SAndroid Build Coastguard Worker
1375*8975f5c5SAndroid Build Coastguard Worker        if (bufferBinding.get() == nullptr || !block.activeShaders().test(shaderType))
1376*8975f5c5SAndroid Build Coastguard Worker        {
1377*8975f5c5SAndroid Build Coastguard Worker            continue;
1378*8975f5c5SAndroid Build Coastguard Worker        }
1379*8975f5c5SAndroid Build Coastguard Worker
1380*8975f5c5SAndroid Build Coastguard Worker        uint32_t actualBufferIdx = shaderInfo.actualUBOBindings[bufferIndex];
1381*8975f5c5SAndroid Build Coastguard Worker
1382*8975f5c5SAndroid Build Coastguard Worker        if (actualBufferIdx >= mtl::kMaxShaderBuffers)
1383*8975f5c5SAndroid Build Coastguard Worker        {
1384*8975f5c5SAndroid Build Coastguard Worker            continue;
1385*8975f5c5SAndroid Build Coastguard Worker        }
1386*8975f5c5SAndroid Build Coastguard Worker
1387*8975f5c5SAndroid Build Coastguard Worker        mtl::BufferRef mtlBuffer = mLegalizedOffsetedUniformBuffers[bufferIndex].first;
1388*8975f5c5SAndroid Build Coastguard Worker        uint32_t offset          = mLegalizedOffsetedUniformBuffers[bufferIndex].second;
1389*8975f5c5SAndroid Build Coastguard Worker        cmdEncoder->setBuffer(shaderType, mtlBuffer, offset, actualBufferIdx);
1390*8975f5c5SAndroid Build Coastguard Worker    }
1391*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
1392*8975f5c5SAndroid Build Coastguard Worker}
1393*8975f5c5SAndroid Build Coastguard Worker
1394*8975f5c5SAndroid Build Coastguard Workerangle::Result ProgramExecutableMtl::encodeUniformBuffersInfoArgumentBuffer(
1395*8975f5c5SAndroid Build Coastguard Worker    ContextMtl *context,
1396*8975f5c5SAndroid Build Coastguard Worker    mtl::RenderCommandEncoder *cmdEncoder,
1397*8975f5c5SAndroid Build Coastguard Worker    gl::ShaderType shaderType)
1398*8975f5c5SAndroid Build Coastguard Worker{
1399*8975f5c5SAndroid Build Coastguard Worker    const gl::State &glState                      = context->getState();
1400*8975f5c5SAndroid Build Coastguard Worker    const std::vector<gl::InterfaceBlock> &blocks = mExecutable->getUniformBlocks();
1401*8975f5c5SAndroid Build Coastguard Worker
1402*8975f5c5SAndroid Build Coastguard Worker    ASSERT(mCurrentShaderVariants[shaderType]->translatedSrcInfo);
1403*8975f5c5SAndroid Build Coastguard Worker    const mtl::TranslatedShaderInfo &shaderInfo =
1404*8975f5c5SAndroid Build Coastguard Worker        *mCurrentShaderVariants[shaderType]->translatedSrcInfo;
1405*8975f5c5SAndroid Build Coastguard Worker
1406*8975f5c5SAndroid Build Coastguard Worker    // Encode all uniform buffers into an argument buffer.
1407*8975f5c5SAndroid Build Coastguard Worker    ProgramArgumentBufferEncoderMtl &bufferEncoder =
1408*8975f5c5SAndroid Build Coastguard Worker        mCurrentShaderVariants[shaderType]->uboArgBufferEncoder;
1409*8975f5c5SAndroid Build Coastguard Worker
1410*8975f5c5SAndroid Build Coastguard Worker    mtl::BufferRef argumentBuffer;
1411*8975f5c5SAndroid Build Coastguard Worker    size_t argumentBufferOffset;
1412*8975f5c5SAndroid Build Coastguard Worker    bufferEncoder.bufferPool.releaseInFlightBuffers(context);
1413*8975f5c5SAndroid Build Coastguard Worker    ANGLE_TRY(bufferEncoder.bufferPool.allocate(
1414*8975f5c5SAndroid Build Coastguard Worker        context, bufferEncoder.metalArgBufferEncoder.get().encodedLength, nullptr, &argumentBuffer,
1415*8975f5c5SAndroid Build Coastguard Worker        &argumentBufferOffset));
1416*8975f5c5SAndroid Build Coastguard Worker
1417*8975f5c5SAndroid Build Coastguard Worker    // MTLArgumentEncoder is modifying the buffer indirectly on CPU. We need to call map()
1418*8975f5c5SAndroid Build Coastguard Worker    // so that the buffer's data changes could be flushed to the GPU side later.
1419*8975f5c5SAndroid Build Coastguard Worker    ANGLE_UNUSED_VARIABLE(argumentBuffer->mapWithOpt(context, /*readonly=*/false, /*noSync=*/true));
1420*8975f5c5SAndroid Build Coastguard Worker
1421*8975f5c5SAndroid Build Coastguard Worker    [bufferEncoder.metalArgBufferEncoder setArgumentBuffer:argumentBuffer->get()
1422*8975f5c5SAndroid Build Coastguard Worker                                                    offset:argumentBufferOffset];
1423*8975f5c5SAndroid Build Coastguard Worker
1424*8975f5c5SAndroid Build Coastguard Worker    constexpr gl::ShaderMap<MTLRenderStages> kShaderStageMap = {
1425*8975f5c5SAndroid Build Coastguard Worker        {gl::ShaderType::Vertex, MTLRenderStageVertex},
1426*8975f5c5SAndroid Build Coastguard Worker        {gl::ShaderType::Fragment, MTLRenderStageFragment},
1427*8975f5c5SAndroid Build Coastguard Worker    };
1428*8975f5c5SAndroid Build Coastguard Worker
1429*8975f5c5SAndroid Build Coastguard Worker    auto mtlRenderStage = kShaderStageMap[shaderType];
1430*8975f5c5SAndroid Build Coastguard Worker
1431*8975f5c5SAndroid Build Coastguard Worker    for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
1432*8975f5c5SAndroid Build Coastguard Worker    {
1433*8975f5c5SAndroid Build Coastguard Worker        const gl::InterfaceBlock &block = blocks[bufferIndex];
1434*8975f5c5SAndroid Build Coastguard Worker        const GLuint binding            = mExecutable->getUniformBlockBinding(bufferIndex);
1435*8975f5c5SAndroid Build Coastguard Worker        const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
1436*8975f5c5SAndroid Build Coastguard Worker            glState.getIndexedUniformBuffer(binding);
1437*8975f5c5SAndroid Build Coastguard Worker
1438*8975f5c5SAndroid Build Coastguard Worker        if (bufferBinding.get() == nullptr || !block.activeShaders().test(shaderType))
1439*8975f5c5SAndroid Build Coastguard Worker        {
1440*8975f5c5SAndroid Build Coastguard Worker            continue;
1441*8975f5c5SAndroid Build Coastguard Worker        }
1442*8975f5c5SAndroid Build Coastguard Worker
1443*8975f5c5SAndroid Build Coastguard Worker        mArgumentBufferRenderStageUsages[bufferIndex] |= mtlRenderStage;
1444*8975f5c5SAndroid Build Coastguard Worker
1445*8975f5c5SAndroid Build Coastguard Worker        uint32_t actualBufferIdx = shaderInfo.actualUBOBindings[bufferIndex];
1446*8975f5c5SAndroid Build Coastguard Worker        if (actualBufferIdx >= mtl::kMaxShaderBuffers)
1447*8975f5c5SAndroid Build Coastguard Worker        {
1448*8975f5c5SAndroid Build Coastguard Worker            continue;
1449*8975f5c5SAndroid Build Coastguard Worker        }
1450*8975f5c5SAndroid Build Coastguard Worker
1451*8975f5c5SAndroid Build Coastguard Worker        mtl::BufferRef mtlBuffer = mLegalizedOffsetedUniformBuffers[bufferIndex].first;
1452*8975f5c5SAndroid Build Coastguard Worker        uint32_t offset          = mLegalizedOffsetedUniformBuffers[bufferIndex].second;
1453*8975f5c5SAndroid Build Coastguard Worker        [bufferEncoder.metalArgBufferEncoder setBuffer:mtlBuffer->get()
1454*8975f5c5SAndroid Build Coastguard Worker                                                offset:offset
1455*8975f5c5SAndroid Build Coastguard Worker                                               atIndex:actualBufferIdx];
1456*8975f5c5SAndroid Build Coastguard Worker    }
1457*8975f5c5SAndroid Build Coastguard Worker
1458*8975f5c5SAndroid Build Coastguard Worker    // Flush changes made by MTLArgumentEncoder to GPU.
1459*8975f5c5SAndroid Build Coastguard Worker    argumentBuffer->unmapAndFlushSubset(context, argumentBufferOffset,
1460*8975f5c5SAndroid Build Coastguard Worker                                        bufferEncoder.metalArgBufferEncoder.get().encodedLength);
1461*8975f5c5SAndroid Build Coastguard Worker
1462*8975f5c5SAndroid Build Coastguard Worker    cmdEncoder->setBuffer(shaderType, argumentBuffer, static_cast<uint32_t>(argumentBufferOffset),
1463*8975f5c5SAndroid Build Coastguard Worker                          mtl::kUBOArgumentBufferBindingIndex);
1464*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
1465*8975f5c5SAndroid Build Coastguard Worker}
1466*8975f5c5SAndroid Build Coastguard Worker
1467*8975f5c5SAndroid Build Coastguard Workerangle::Result ProgramExecutableMtl::updateXfbBuffers(ContextMtl *context,
1468*8975f5c5SAndroid Build Coastguard Worker                                                     mtl::RenderCommandEncoder *cmdEncoder,
1469*8975f5c5SAndroid Build Coastguard Worker                                                     const mtl::RenderPipelineDesc &pipelineDesc)
1470*8975f5c5SAndroid Build Coastguard Worker{
1471*8975f5c5SAndroid Build Coastguard Worker    const gl::State &glState                 = context->getState();
1472*8975f5c5SAndroid Build Coastguard Worker    gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
1473*8975f5c5SAndroid Build Coastguard Worker
1474*8975f5c5SAndroid Build Coastguard Worker    if (pipelineDesc.rasterizationEnabled() || !glState.isTransformFeedbackActiveUnpaused() ||
1475*8975f5c5SAndroid Build Coastguard Worker        ANGLE_UNLIKELY(!transformFeedback))
1476*8975f5c5SAndroid Build Coastguard Worker    {
1477*8975f5c5SAndroid Build Coastguard Worker        // XFB output can only be used with rasterization disabled.
1478*8975f5c5SAndroid Build Coastguard Worker        return angle::Result::Continue;
1479*8975f5c5SAndroid Build Coastguard Worker    }
1480*8975f5c5SAndroid Build Coastguard Worker
1481*8975f5c5SAndroid Build Coastguard Worker    size_t xfbBufferCount = glState.getProgramExecutable()->getTransformFeedbackBufferCount();
1482*8975f5c5SAndroid Build Coastguard Worker
1483*8975f5c5SAndroid Build Coastguard Worker    ASSERT(xfbBufferCount > 0);
1484*8975f5c5SAndroid Build Coastguard Worker    ASSERT(mExecutable->getTransformFeedbackBufferMode() != GL_INTERLEAVED_ATTRIBS ||
1485*8975f5c5SAndroid Build Coastguard Worker           xfbBufferCount == 1);
1486*8975f5c5SAndroid Build Coastguard Worker
1487*8975f5c5SAndroid Build Coastguard Worker    for (size_t bufferIndex = 0; bufferIndex < xfbBufferCount; ++bufferIndex)
1488*8975f5c5SAndroid Build Coastguard Worker    {
1489*8975f5c5SAndroid Build Coastguard Worker        uint32_t actualBufferIdx = mMslXfbOnlyVertexShaderInfo.actualXFBBindings[bufferIndex];
1490*8975f5c5SAndroid Build Coastguard Worker
1491*8975f5c5SAndroid Build Coastguard Worker        if (actualBufferIdx >= mtl::kMaxShaderBuffers)
1492*8975f5c5SAndroid Build Coastguard Worker        {
1493*8975f5c5SAndroid Build Coastguard Worker            continue;
1494*8975f5c5SAndroid Build Coastguard Worker        }
1495*8975f5c5SAndroid Build Coastguard Worker
1496*8975f5c5SAndroid Build Coastguard Worker        const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
1497*8975f5c5SAndroid Build Coastguard Worker            transformFeedback->getIndexedBuffer(bufferIndex);
1498*8975f5c5SAndroid Build Coastguard Worker        gl::Buffer *buffer = bufferBinding.get();
1499*8975f5c5SAndroid Build Coastguard Worker        ASSERT((bufferBinding.getOffset() % 4) == 0);
1500*8975f5c5SAndroid Build Coastguard Worker        ASSERT(buffer != nullptr);
1501*8975f5c5SAndroid Build Coastguard Worker
1502*8975f5c5SAndroid Build Coastguard Worker        BufferMtl *bufferMtl = mtl::GetImpl(buffer);
1503*8975f5c5SAndroid Build Coastguard Worker
1504*8975f5c5SAndroid Build Coastguard Worker        // Use offset=0, actual offset will be set in Driver Uniform inside ContextMtl.
1505*8975f5c5SAndroid Build Coastguard Worker        cmdEncoder->setBufferForWrite(gl::ShaderType::Vertex, bufferMtl->getCurrentBuffer(), 0,
1506*8975f5c5SAndroid Build Coastguard Worker                                      actualBufferIdx);
1507*8975f5c5SAndroid Build Coastguard Worker    }
1508*8975f5c5SAndroid Build Coastguard Worker
1509*8975f5c5SAndroid Build Coastguard Worker    return angle::Result::Continue;
1510*8975f5c5SAndroid Build Coastguard Worker}
1511*8975f5c5SAndroid Build Coastguard Worker
1512*8975f5c5SAndroid Build Coastguard Workertemplate <typename T>
1513*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniformImpl(GLint location,
1514*8975f5c5SAndroid Build Coastguard Worker                                          GLsizei count,
1515*8975f5c5SAndroid Build Coastguard Worker                                          const T *v,
1516*8975f5c5SAndroid Build Coastguard Worker                                          GLenum entryPointType)
1517*8975f5c5SAndroid Build Coastguard Worker{
1518*8975f5c5SAndroid Build Coastguard Worker    const std::vector<gl::VariableLocation> &uniformLocations = mExecutable->getUniformLocations();
1519*8975f5c5SAndroid Build Coastguard Worker    const gl::VariableLocation &locationInfo                  = uniformLocations[location];
1520*8975f5c5SAndroid Build Coastguard Worker
1521*8975f5c5SAndroid Build Coastguard Worker    const std::vector<gl::LinkedUniform> &linkedUniforms = mExecutable->getUniforms();
1522*8975f5c5SAndroid Build Coastguard Worker    const gl::LinkedUniform &linkedUniform               = linkedUniforms[locationInfo.index];
1523*8975f5c5SAndroid Build Coastguard Worker
1524*8975f5c5SAndroid Build Coastguard Worker    if (linkedUniform.isSampler())
1525*8975f5c5SAndroid Build Coastguard Worker    {
1526*8975f5c5SAndroid Build Coastguard Worker        // Sampler binding has changed.
1527*8975f5c5SAndroid Build Coastguard Worker        mSamplerBindingsDirty.set();
1528*8975f5c5SAndroid Build Coastguard Worker        return;
1529*8975f5c5SAndroid Build Coastguard Worker    }
1530*8975f5c5SAndroid Build Coastguard Worker
1531*8975f5c5SAndroid Build Coastguard Worker    if (linkedUniform.getType() == entryPointType)
1532*8975f5c5SAndroid Build Coastguard Worker    {
1533*8975f5c5SAndroid Build Coastguard Worker        for (gl::ShaderType shaderType : gl::kAllGLES2ShaderTypes)
1534*8975f5c5SAndroid Build Coastguard Worker        {
1535*8975f5c5SAndroid Build Coastguard Worker            DefaultUniformBlockMtl &uniformBlock  = mDefaultUniformBlocks[shaderType];
1536*8975f5c5SAndroid Build Coastguard Worker            const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
1537*8975f5c5SAndroid Build Coastguard Worker
1538*8975f5c5SAndroid Build Coastguard Worker            // Assume an offset of -1 means the block is unused.
1539*8975f5c5SAndroid Build Coastguard Worker            if (layoutInfo.offset == -1)
1540*8975f5c5SAndroid Build Coastguard Worker            {
1541*8975f5c5SAndroid Build Coastguard Worker                continue;
1542*8975f5c5SAndroid Build Coastguard Worker            }
1543*8975f5c5SAndroid Build Coastguard Worker
1544*8975f5c5SAndroid Build Coastguard Worker            const GLint componentCount    = (GLint)linkedUniform.getElementComponents();
1545*8975f5c5SAndroid Build Coastguard Worker            const GLint baseComponentSize = (GLint)mtl::GetMetalSizeForGLType(
1546*8975f5c5SAndroid Build Coastguard Worker                gl::VariableComponentType(linkedUniform.getType()));
1547*8975f5c5SAndroid Build Coastguard Worker            UpdateDefaultUniformBlockWithElementSize(count, locationInfo.arrayIndex, componentCount,
1548*8975f5c5SAndroid Build Coastguard Worker                                                     v, baseComponentSize, layoutInfo,
1549*8975f5c5SAndroid Build Coastguard Worker                                                     &uniformBlock.uniformData);
1550*8975f5c5SAndroid Build Coastguard Worker            mDefaultUniformBlocksDirty.set(shaderType);
1551*8975f5c5SAndroid Build Coastguard Worker        }
1552*8975f5c5SAndroid Build Coastguard Worker    }
1553*8975f5c5SAndroid Build Coastguard Worker    else
1554*8975f5c5SAndroid Build Coastguard Worker    {
1555*8975f5c5SAndroid Build Coastguard Worker        for (gl::ShaderType shaderType : gl::kAllGLES2ShaderTypes)
1556*8975f5c5SAndroid Build Coastguard Worker        {
1557*8975f5c5SAndroid Build Coastguard Worker            DefaultUniformBlockMtl &uniformBlock  = mDefaultUniformBlocks[shaderType];
1558*8975f5c5SAndroid Build Coastguard Worker            const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
1559*8975f5c5SAndroid Build Coastguard Worker
1560*8975f5c5SAndroid Build Coastguard Worker            // Assume an offset of -1 means the block is unused.
1561*8975f5c5SAndroid Build Coastguard Worker            if (layoutInfo.offset == -1)
1562*8975f5c5SAndroid Build Coastguard Worker            {
1563*8975f5c5SAndroid Build Coastguard Worker                continue;
1564*8975f5c5SAndroid Build Coastguard Worker            }
1565*8975f5c5SAndroid Build Coastguard Worker
1566*8975f5c5SAndroid Build Coastguard Worker            const GLint componentCount = linkedUniform.getElementComponents();
1567*8975f5c5SAndroid Build Coastguard Worker
1568*8975f5c5SAndroid Build Coastguard Worker            ASSERT(linkedUniform.getType() == gl::VariableBoolVectorType(entryPointType));
1569*8975f5c5SAndroid Build Coastguard Worker
1570*8975f5c5SAndroid Build Coastguard Worker            GLint initialArrayOffset =
1571*8975f5c5SAndroid Build Coastguard Worker                locationInfo.arrayIndex * layoutInfo.arrayStride + layoutInfo.offset;
1572*8975f5c5SAndroid Build Coastguard Worker            for (GLint i = 0; i < count; i++)
1573*8975f5c5SAndroid Build Coastguard Worker            {
1574*8975f5c5SAndroid Build Coastguard Worker                GLint elementOffset = i * layoutInfo.arrayStride + initialArrayOffset;
1575*8975f5c5SAndroid Build Coastguard Worker                bool *dest =
1576*8975f5c5SAndroid Build Coastguard Worker                    reinterpret_cast<bool *>(uniformBlock.uniformData.data() + elementOffset);
1577*8975f5c5SAndroid Build Coastguard Worker                const T *source = v + i * componentCount;
1578*8975f5c5SAndroid Build Coastguard Worker
1579*8975f5c5SAndroid Build Coastguard Worker                for (int c = 0; c < componentCount; c++)
1580*8975f5c5SAndroid Build Coastguard Worker                {
1581*8975f5c5SAndroid Build Coastguard Worker                    dest[c] = (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE;
1582*8975f5c5SAndroid Build Coastguard Worker                }
1583*8975f5c5SAndroid Build Coastguard Worker            }
1584*8975f5c5SAndroid Build Coastguard Worker
1585*8975f5c5SAndroid Build Coastguard Worker            mDefaultUniformBlocksDirty.set(shaderType);
1586*8975f5c5SAndroid Build Coastguard Worker        }
1587*8975f5c5SAndroid Build Coastguard Worker    }
1588*8975f5c5SAndroid Build Coastguard Worker}
1589*8975f5c5SAndroid Build Coastguard Worker
1590*8975f5c5SAndroid Build Coastguard Workertemplate <typename T>
1591*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::getUniformImpl(GLint location, T *v, GLenum entryPointType) const
1592*8975f5c5SAndroid Build Coastguard Worker{
1593*8975f5c5SAndroid Build Coastguard Worker    const gl::VariableLocation &locationInfo = mExecutable->getUniformLocations()[location];
1594*8975f5c5SAndroid Build Coastguard Worker    const gl::LinkedUniform &linkedUniform   = mExecutable->getUniforms()[locationInfo.index];
1595*8975f5c5SAndroid Build Coastguard Worker
1596*8975f5c5SAndroid Build Coastguard Worker    ASSERT(!linkedUniform.isSampler());
1597*8975f5c5SAndroid Build Coastguard Worker
1598*8975f5c5SAndroid Build Coastguard Worker    const gl::ShaderType shaderType = linkedUniform.getFirstActiveShaderType();
1599*8975f5c5SAndroid Build Coastguard Worker    ASSERT(shaderType != gl::ShaderType::InvalidEnum);
1600*8975f5c5SAndroid Build Coastguard Worker
1601*8975f5c5SAndroid Build Coastguard Worker    const DefaultUniformBlockMtl &uniformBlock = mDefaultUniformBlocks[shaderType];
1602*8975f5c5SAndroid Build Coastguard Worker    const sh::BlockMemberInfo &layoutInfo      = uniformBlock.uniformLayout[location];
1603*8975f5c5SAndroid Build Coastguard Worker
1604*8975f5c5SAndroid Build Coastguard Worker    ASSERT(linkedUniform.getUniformTypeInfo().componentType == entryPointType ||
1605*8975f5c5SAndroid Build Coastguard Worker           linkedUniform.getUniformTypeInfo().componentType ==
1606*8975f5c5SAndroid Build Coastguard Worker               gl::VariableBoolVectorType(entryPointType));
1607*8975f5c5SAndroid Build Coastguard Worker    const GLint baseComponentSize =
1608*8975f5c5SAndroid Build Coastguard Worker        (GLint)mtl::GetMetalSizeForGLType(gl::VariableComponentType(linkedUniform.getType()));
1609*8975f5c5SAndroid Build Coastguard Worker
1610*8975f5c5SAndroid Build Coastguard Worker    if (gl::IsMatrixType(linkedUniform.getType()))
1611*8975f5c5SAndroid Build Coastguard Worker    {
1612*8975f5c5SAndroid Build Coastguard Worker        const uint8_t *ptrToElement = uniformBlock.uniformData.data() + layoutInfo.offset +
1613*8975f5c5SAndroid Build Coastguard Worker                                      (locationInfo.arrayIndex * layoutInfo.arrayStride);
1614*8975f5c5SAndroid Build Coastguard Worker        mtl::GetMatrixUniformMetal(linkedUniform.getType(), v,
1615*8975f5c5SAndroid Build Coastguard Worker                                   reinterpret_cast<const T *>(ptrToElement), false);
1616*8975f5c5SAndroid Build Coastguard Worker    }
1617*8975f5c5SAndroid Build Coastguard Worker    // Decompress bool from one byte to four bytes because bool values in GLSL
1618*8975f5c5SAndroid Build Coastguard Worker    // are uint-sized: ES 3.0 Section 2.12.6.3 "Uniform Buffer Object Storage".
1619*8975f5c5SAndroid Build Coastguard Worker    else if (gl::VariableComponentType(linkedUniform.getType()) == GL_BOOL)
1620*8975f5c5SAndroid Build Coastguard Worker    {
1621*8975f5c5SAndroid Build Coastguard Worker        bool bVals[4] = {0};
1622*8975f5c5SAndroid Build Coastguard Worker        ReadFromDefaultUniformBlockWithElementSize(
1623*8975f5c5SAndroid Build Coastguard Worker            linkedUniform.getElementComponents(), locationInfo.arrayIndex, bVals, baseComponentSize,
1624*8975f5c5SAndroid Build Coastguard Worker            layoutInfo, &uniformBlock.uniformData);
1625*8975f5c5SAndroid Build Coastguard Worker        for (int bCol = 0; bCol < linkedUniform.getElementComponents(); ++bCol)
1626*8975f5c5SAndroid Build Coastguard Worker        {
1627*8975f5c5SAndroid Build Coastguard Worker            unsigned int data = bVals[bCol];
1628*8975f5c5SAndroid Build Coastguard Worker            *(v + bCol)       = static_cast<T>(data);
1629*8975f5c5SAndroid Build Coastguard Worker        }
1630*8975f5c5SAndroid Build Coastguard Worker    }
1631*8975f5c5SAndroid Build Coastguard Worker    else
1632*8975f5c5SAndroid Build Coastguard Worker    {
1633*8975f5c5SAndroid Build Coastguard Worker
1634*8975f5c5SAndroid Build Coastguard Worker        assert(baseComponentSize == sizeof(T));
1635*8975f5c5SAndroid Build Coastguard Worker        ReadFromDefaultUniformBlockWithElementSize(linkedUniform.getElementComponents(),
1636*8975f5c5SAndroid Build Coastguard Worker                                                   locationInfo.arrayIndex, v, baseComponentSize,
1637*8975f5c5SAndroid Build Coastguard Worker                                                   layoutInfo, &uniformBlock.uniformData);
1638*8975f5c5SAndroid Build Coastguard Worker    }
1639*8975f5c5SAndroid Build Coastguard Worker}
1640*8975f5c5SAndroid Build Coastguard Worker
1641*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
1642*8975f5c5SAndroid Build Coastguard Worker{
1643*8975f5c5SAndroid Build Coastguard Worker    setUniformImpl(location, count, v, GL_FLOAT);
1644*8975f5c5SAndroid Build Coastguard Worker}
1645*8975f5c5SAndroid Build Coastguard Worker
1646*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
1647*8975f5c5SAndroid Build Coastguard Worker{
1648*8975f5c5SAndroid Build Coastguard Worker    setUniformImpl(location, count, v, GL_FLOAT_VEC2);
1649*8975f5c5SAndroid Build Coastguard Worker}
1650*8975f5c5SAndroid Build Coastguard Worker
1651*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
1652*8975f5c5SAndroid Build Coastguard Worker{
1653*8975f5c5SAndroid Build Coastguard Worker    setUniformImpl(location, count, v, GL_FLOAT_VEC3);
1654*8975f5c5SAndroid Build Coastguard Worker}
1655*8975f5c5SAndroid Build Coastguard Worker
1656*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
1657*8975f5c5SAndroid Build Coastguard Worker{
1658*8975f5c5SAndroid Build Coastguard Worker    setUniformImpl(location, count, v, GL_FLOAT_VEC4);
1659*8975f5c5SAndroid Build Coastguard Worker}
1660*8975f5c5SAndroid Build Coastguard Worker
1661*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniform1iv(GLint startLocation, GLsizei count, const GLint *v)
1662*8975f5c5SAndroid Build Coastguard Worker{
1663*8975f5c5SAndroid Build Coastguard Worker    setUniformImpl(startLocation, count, v, GL_INT);
1664*8975f5c5SAndroid Build Coastguard Worker}
1665*8975f5c5SAndroid Build Coastguard Worker
1666*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniform2iv(GLint location, GLsizei count, const GLint *v)
1667*8975f5c5SAndroid Build Coastguard Worker{
1668*8975f5c5SAndroid Build Coastguard Worker    setUniformImpl(location, count, v, GL_INT_VEC2);
1669*8975f5c5SAndroid Build Coastguard Worker}
1670*8975f5c5SAndroid Build Coastguard Worker
1671*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniform3iv(GLint location, GLsizei count, const GLint *v)
1672*8975f5c5SAndroid Build Coastguard Worker{
1673*8975f5c5SAndroid Build Coastguard Worker    setUniformImpl(location, count, v, GL_INT_VEC3);
1674*8975f5c5SAndroid Build Coastguard Worker}
1675*8975f5c5SAndroid Build Coastguard Worker
1676*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniform4iv(GLint location, GLsizei count, const GLint *v)
1677*8975f5c5SAndroid Build Coastguard Worker{
1678*8975f5c5SAndroid Build Coastguard Worker    setUniformImpl(location, count, v, GL_INT_VEC4);
1679*8975f5c5SAndroid Build Coastguard Worker}
1680*8975f5c5SAndroid Build Coastguard Worker
1681*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
1682*8975f5c5SAndroid Build Coastguard Worker{
1683*8975f5c5SAndroid Build Coastguard Worker    setUniformImpl(location, count, v, GL_UNSIGNED_INT);
1684*8975f5c5SAndroid Build Coastguard Worker}
1685*8975f5c5SAndroid Build Coastguard Worker
1686*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
1687*8975f5c5SAndroid Build Coastguard Worker{
1688*8975f5c5SAndroid Build Coastguard Worker    setUniformImpl(location, count, v, GL_UNSIGNED_INT_VEC2);
1689*8975f5c5SAndroid Build Coastguard Worker}
1690*8975f5c5SAndroid Build Coastguard Worker
1691*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
1692*8975f5c5SAndroid Build Coastguard Worker{
1693*8975f5c5SAndroid Build Coastguard Worker    setUniformImpl(location, count, v, GL_UNSIGNED_INT_VEC3);
1694*8975f5c5SAndroid Build Coastguard Worker}
1695*8975f5c5SAndroid Build Coastguard Worker
1696*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
1697*8975f5c5SAndroid Build Coastguard Worker{
1698*8975f5c5SAndroid Build Coastguard Worker    setUniformImpl(location, count, v, GL_UNSIGNED_INT_VEC4);
1699*8975f5c5SAndroid Build Coastguard Worker}
1700*8975f5c5SAndroid Build Coastguard Worker
1701*8975f5c5SAndroid Build Coastguard Workertemplate <int cols, int rows>
1702*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniformMatrixfv(GLint location,
1703*8975f5c5SAndroid Build Coastguard Worker                                              GLsizei count,
1704*8975f5c5SAndroid Build Coastguard Worker                                              GLboolean transpose,
1705*8975f5c5SAndroid Build Coastguard Worker                                              const GLfloat *value)
1706*8975f5c5SAndroid Build Coastguard Worker{
1707*8975f5c5SAndroid Build Coastguard Worker    const gl::VariableLocation &locationInfo = mExecutable->getUniformLocations()[location];
1708*8975f5c5SAndroid Build Coastguard Worker    const gl::LinkedUniform &linkedUniform   = mExecutable->getUniforms()[locationInfo.index];
1709*8975f5c5SAndroid Build Coastguard Worker
1710*8975f5c5SAndroid Build Coastguard Worker    for (gl::ShaderType shaderType : gl::kAllGLES2ShaderTypes)
1711*8975f5c5SAndroid Build Coastguard Worker    {
1712*8975f5c5SAndroid Build Coastguard Worker        DefaultUniformBlockMtl &uniformBlock  = mDefaultUniformBlocks[shaderType];
1713*8975f5c5SAndroid Build Coastguard Worker        const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
1714*8975f5c5SAndroid Build Coastguard Worker
1715*8975f5c5SAndroid Build Coastguard Worker        // Assume an offset of -1 means the block is unused.
1716*8975f5c5SAndroid Build Coastguard Worker        if (layoutInfo.offset == -1)
1717*8975f5c5SAndroid Build Coastguard Worker        {
1718*8975f5c5SAndroid Build Coastguard Worker            continue;
1719*8975f5c5SAndroid Build Coastguard Worker        }
1720*8975f5c5SAndroid Build Coastguard Worker
1721*8975f5c5SAndroid Build Coastguard Worker        mtl::SetFloatUniformMatrixMetal<cols, rows>::Run(
1722*8975f5c5SAndroid Build Coastguard Worker            locationInfo.arrayIndex, linkedUniform.getBasicTypeElementCount(), count, transpose,
1723*8975f5c5SAndroid Build Coastguard Worker            value, uniformBlock.uniformData.data() + layoutInfo.offset);
1724*8975f5c5SAndroid Build Coastguard Worker
1725*8975f5c5SAndroid Build Coastguard Worker        mDefaultUniformBlocksDirty.set(shaderType);
1726*8975f5c5SAndroid Build Coastguard Worker    }
1727*8975f5c5SAndroid Build Coastguard Worker}
1728*8975f5c5SAndroid Build Coastguard Worker
1729*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniformMatrix2fv(GLint location,
1730*8975f5c5SAndroid Build Coastguard Worker                                               GLsizei count,
1731*8975f5c5SAndroid Build Coastguard Worker                                               GLboolean transpose,
1732*8975f5c5SAndroid Build Coastguard Worker                                               const GLfloat *value)
1733*8975f5c5SAndroid Build Coastguard Worker{
1734*8975f5c5SAndroid Build Coastguard Worker    setUniformMatrixfv<2, 2>(location, count, transpose, value);
1735*8975f5c5SAndroid Build Coastguard Worker}
1736*8975f5c5SAndroid Build Coastguard Worker
1737*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniformMatrix3fv(GLint location,
1738*8975f5c5SAndroid Build Coastguard Worker                                               GLsizei count,
1739*8975f5c5SAndroid Build Coastguard Worker                                               GLboolean transpose,
1740*8975f5c5SAndroid Build Coastguard Worker                                               const GLfloat *value)
1741*8975f5c5SAndroid Build Coastguard Worker{
1742*8975f5c5SAndroid Build Coastguard Worker    setUniformMatrixfv<3, 3>(location, count, transpose, value);
1743*8975f5c5SAndroid Build Coastguard Worker}
1744*8975f5c5SAndroid Build Coastguard Worker
1745*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniformMatrix4fv(GLint location,
1746*8975f5c5SAndroid Build Coastguard Worker                                               GLsizei count,
1747*8975f5c5SAndroid Build Coastguard Worker                                               GLboolean transpose,
1748*8975f5c5SAndroid Build Coastguard Worker                                               const GLfloat *value)
1749*8975f5c5SAndroid Build Coastguard Worker{
1750*8975f5c5SAndroid Build Coastguard Worker    setUniformMatrixfv<4, 4>(location, count, transpose, value);
1751*8975f5c5SAndroid Build Coastguard Worker}
1752*8975f5c5SAndroid Build Coastguard Worker
1753*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniformMatrix2x3fv(GLint location,
1754*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei count,
1755*8975f5c5SAndroid Build Coastguard Worker                                                 GLboolean transpose,
1756*8975f5c5SAndroid Build Coastguard Worker                                                 const GLfloat *value)
1757*8975f5c5SAndroid Build Coastguard Worker{
1758*8975f5c5SAndroid Build Coastguard Worker    setUniformMatrixfv<2, 3>(location, count, transpose, value);
1759*8975f5c5SAndroid Build Coastguard Worker}
1760*8975f5c5SAndroid Build Coastguard Worker
1761*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniformMatrix3x2fv(GLint location,
1762*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei count,
1763*8975f5c5SAndroid Build Coastguard Worker                                                 GLboolean transpose,
1764*8975f5c5SAndroid Build Coastguard Worker                                                 const GLfloat *value)
1765*8975f5c5SAndroid Build Coastguard Worker{
1766*8975f5c5SAndroid Build Coastguard Worker    setUniformMatrixfv<3, 2>(location, count, transpose, value);
1767*8975f5c5SAndroid Build Coastguard Worker}
1768*8975f5c5SAndroid Build Coastguard Worker
1769*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniformMatrix2x4fv(GLint location,
1770*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei count,
1771*8975f5c5SAndroid Build Coastguard Worker                                                 GLboolean transpose,
1772*8975f5c5SAndroid Build Coastguard Worker                                                 const GLfloat *value)
1773*8975f5c5SAndroid Build Coastguard Worker{
1774*8975f5c5SAndroid Build Coastguard Worker    setUniformMatrixfv<2, 4>(location, count, transpose, value);
1775*8975f5c5SAndroid Build Coastguard Worker}
1776*8975f5c5SAndroid Build Coastguard Worker
1777*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniformMatrix4x2fv(GLint location,
1778*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei count,
1779*8975f5c5SAndroid Build Coastguard Worker                                                 GLboolean transpose,
1780*8975f5c5SAndroid Build Coastguard Worker                                                 const GLfloat *value)
1781*8975f5c5SAndroid Build Coastguard Worker{
1782*8975f5c5SAndroid Build Coastguard Worker    setUniformMatrixfv<4, 2>(location, count, transpose, value);
1783*8975f5c5SAndroid Build Coastguard Worker}
1784*8975f5c5SAndroid Build Coastguard Worker
1785*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniformMatrix3x4fv(GLint location,
1786*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei count,
1787*8975f5c5SAndroid Build Coastguard Worker                                                 GLboolean transpose,
1788*8975f5c5SAndroid Build Coastguard Worker                                                 const GLfloat *value)
1789*8975f5c5SAndroid Build Coastguard Worker{
1790*8975f5c5SAndroid Build Coastguard Worker    setUniformMatrixfv<3, 4>(location, count, transpose, value);
1791*8975f5c5SAndroid Build Coastguard Worker}
1792*8975f5c5SAndroid Build Coastguard Worker
1793*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::setUniformMatrix4x3fv(GLint location,
1794*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei count,
1795*8975f5c5SAndroid Build Coastguard Worker                                                 GLboolean transpose,
1796*8975f5c5SAndroid Build Coastguard Worker                                                 const GLfloat *value)
1797*8975f5c5SAndroid Build Coastguard Worker{
1798*8975f5c5SAndroid Build Coastguard Worker    setUniformMatrixfv<4, 3>(location, count, transpose, value);
1799*8975f5c5SAndroid Build Coastguard Worker}
1800*8975f5c5SAndroid Build Coastguard Worker
1801*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::getUniformfv(const gl::Context *context,
1802*8975f5c5SAndroid Build Coastguard Worker                                        GLint location,
1803*8975f5c5SAndroid Build Coastguard Worker                                        GLfloat *params) const
1804*8975f5c5SAndroid Build Coastguard Worker{
1805*8975f5c5SAndroid Build Coastguard Worker    getUniformImpl(location, params, GL_FLOAT);
1806*8975f5c5SAndroid Build Coastguard Worker}
1807*8975f5c5SAndroid Build Coastguard Worker
1808*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::getUniformiv(const gl::Context *context,
1809*8975f5c5SAndroid Build Coastguard Worker                                        GLint location,
1810*8975f5c5SAndroid Build Coastguard Worker                                        GLint *params) const
1811*8975f5c5SAndroid Build Coastguard Worker{
1812*8975f5c5SAndroid Build Coastguard Worker    getUniformImpl(location, params, GL_INT);
1813*8975f5c5SAndroid Build Coastguard Worker}
1814*8975f5c5SAndroid Build Coastguard Worker
1815*8975f5c5SAndroid Build Coastguard Workervoid ProgramExecutableMtl::getUniformuiv(const gl::Context *context,
1816*8975f5c5SAndroid Build Coastguard Worker                                         GLint location,
1817*8975f5c5SAndroid Build Coastguard Worker                                         GLuint *params) const
1818*8975f5c5SAndroid Build Coastguard Worker{
1819*8975f5c5SAndroid Build Coastguard Worker    getUniformImpl(location, params, GL_UNSIGNED_INT);
1820*8975f5c5SAndroid Build Coastguard Worker}
1821*8975f5c5SAndroid Build Coastguard Worker}  // namespace rx
1822