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