1*8975f5c5SAndroid Build Coastguard Worker// 2*8975f5c5SAndroid Build Coastguard Worker// Copyright 2019 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// ContextMtl.mm: 7*8975f5c5SAndroid Build Coastguard Worker// Implements the class methods for ContextMtl. 8*8975f5c5SAndroid Build Coastguard Worker// 9*8975f5c5SAndroid Build Coastguard Worker 10*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/ContextMtl.h" 11*8975f5c5SAndroid Build Coastguard Worker 12*8975f5c5SAndroid Build Coastguard Worker#include <TargetConditionals.h> 13*8975f5c5SAndroid Build Coastguard Worker#include <cstdint> 14*8975f5c5SAndroid Build Coastguard Worker 15*8975f5c5SAndroid Build Coastguard Worker#include "GLSLANG/ShaderLang.h" 16*8975f5c5SAndroid Build Coastguard Worker#include "common/debug.h" 17*8975f5c5SAndroid Build Coastguard Worker#include "image_util/loadimage.h" 18*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/Display.h" 19*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/Query.h" 20*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/TransformFeedback.h" 21*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/OverlayImpl.h" 22*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/BufferMtl.h" 23*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/CompilerMtl.h" 24*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/DisplayMtl.h" 25*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/FrameBufferMtl.h" 26*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/ProgramExecutableMtl.h" 27*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/ProgramMtl.h" 28*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/QueryMtl.h" 29*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/RenderBufferMtl.h" 30*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/RenderTargetMtl.h" 31*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/SamplerMtl.h" 32*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/ShaderMtl.h" 33*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/SyncMtl.h" 34*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/TextureMtl.h" 35*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/TransformFeedbackMtl.h" 36*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/VertexArrayMtl.h" 37*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/mtl_command_buffer.h" 38*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/mtl_common.h" 39*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/mtl_context_device.h" 40*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/mtl_format_utils.h" 41*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/metal/mtl_utils.h" 42*8975f5c5SAndroid Build Coastguard Worker 43*8975f5c5SAndroid Build Coastguard Workernamespace rx 44*8975f5c5SAndroid Build Coastguard Worker{ 45*8975f5c5SAndroid Build Coastguard Worker 46*8975f5c5SAndroid Build Coastguard Workernamespace 47*8975f5c5SAndroid Build Coastguard Worker{ 48*8975f5c5SAndroid Build Coastguard Worker#if TARGET_OS_OSX 49*8975f5c5SAndroid Build Coastguard Worker// Unlimited triangle fan buffers 50*8975f5c5SAndroid Build Coastguard Workerconstexpr uint32_t kMaxTriFanLineLoopBuffersPerFrame = 0; 51*8975f5c5SAndroid Build Coastguard Worker#else 52*8975f5c5SAndroid Build Coastguard Worker// Allow up to 10 buffers for trifan/line loop generation without stalling the GPU. 53*8975f5c5SAndroid Build Coastguard Workerconstexpr uint32_t kMaxTriFanLineLoopBuffersPerFrame = 10; 54*8975f5c5SAndroid Build Coastguard Worker#endif 55*8975f5c5SAndroid Build Coastguard Worker 56*8975f5c5SAndroid Build Coastguard Worker#define ANGLE_MTL_XFB_DRAW(DRAW_PROC) \ 57*8975f5c5SAndroid Build Coastguard Worker if (!mState.isTransformFeedbackActiveUnpaused()) \ 58*8975f5c5SAndroid Build Coastguard Worker { \ 59*8975f5c5SAndroid Build Coastguard Worker /* Normal draw call */ \ 60*8975f5c5SAndroid Build Coastguard Worker DRAW_PROC(false); \ 61*8975f5c5SAndroid Build Coastguard Worker } \ 62*8975f5c5SAndroid Build Coastguard Worker else \ 63*8975f5c5SAndroid Build Coastguard Worker { \ 64*8975f5c5SAndroid Build Coastguard Worker /* First pass: write to XFB buffers in vertex shader, fragment shader inactive */ \ 65*8975f5c5SAndroid Build Coastguard Worker bool rasterizationNotDisabled = \ 66*8975f5c5SAndroid Build Coastguard Worker mRenderPipelineDesc.rasterizationType != mtl::RenderPipelineRasterization::Disabled; \ 67*8975f5c5SAndroid Build Coastguard Worker if (rasterizationNotDisabled) \ 68*8975f5c5SAndroid Build Coastguard Worker { \ 69*8975f5c5SAndroid Build Coastguard Worker invalidateRenderPipeline(); \ 70*8975f5c5SAndroid Build Coastguard Worker } \ 71*8975f5c5SAndroid Build Coastguard Worker DRAW_PROC(true); \ 72*8975f5c5SAndroid Build Coastguard Worker if (rasterizationNotDisabled) \ 73*8975f5c5SAndroid Build Coastguard Worker { \ 74*8975f5c5SAndroid Build Coastguard Worker /* Second pass: full rasterization: vertex shader + fragment shader are active. \ 75*8975f5c5SAndroid Build Coastguard Worker Vertex shader writes to stage output but won't write to XFB buffers */ \ 76*8975f5c5SAndroid Build Coastguard Worker invalidateRenderPipeline(); \ 77*8975f5c5SAndroid Build Coastguard Worker DRAW_PROC(false); \ 78*8975f5c5SAndroid Build Coastguard Worker } \ 79*8975f5c5SAndroid Build Coastguard Worker } 80*8975f5c5SAndroid Build Coastguard Worker 81*8975f5c5SAndroid Build Coastguard Workerangle::Result AllocateTriangleFanBufferFromPool(ContextMtl *context, 82*8975f5c5SAndroid Build Coastguard Worker GLsizei vertexCount, 83*8975f5c5SAndroid Build Coastguard Worker mtl::BufferPool *pool, 84*8975f5c5SAndroid Build Coastguard Worker mtl::BufferRef *bufferOut, 85*8975f5c5SAndroid Build Coastguard Worker uint32_t *offsetOut, 86*8975f5c5SAndroid Build Coastguard Worker uint32_t *numElemsOut) 87*8975f5c5SAndroid Build Coastguard Worker{ 88*8975f5c5SAndroid Build Coastguard Worker uint32_t numIndices; 89*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mtl::GetTriangleFanIndicesCount(context, vertexCount, &numIndices)); 90*8975f5c5SAndroid Build Coastguard Worker 91*8975f5c5SAndroid Build Coastguard Worker size_t offset; 92*8975f5c5SAndroid Build Coastguard Worker pool->releaseInFlightBuffers(context); 93*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(pool->allocate(context, numIndices * sizeof(uint32_t), nullptr, bufferOut, &offset, 94*8975f5c5SAndroid Build Coastguard Worker nullptr)); 95*8975f5c5SAndroid Build Coastguard Worker 96*8975f5c5SAndroid Build Coastguard Worker *offsetOut = static_cast<uint32_t>(offset); 97*8975f5c5SAndroid Build Coastguard Worker *numElemsOut = numIndices; 98*8975f5c5SAndroid Build Coastguard Worker 99*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 100*8975f5c5SAndroid Build Coastguard Worker} 101*8975f5c5SAndroid Build Coastguard Worker 102*8975f5c5SAndroid Build Coastguard Workerangle::Result AllocateBufferFromPool(ContextMtl *context, 103*8975f5c5SAndroid Build Coastguard Worker GLsizei indicesToReserve, 104*8975f5c5SAndroid Build Coastguard Worker mtl::BufferPool *pool, 105*8975f5c5SAndroid Build Coastguard Worker mtl::BufferRef *bufferOut, 106*8975f5c5SAndroid Build Coastguard Worker uint32_t *offsetOut) 107*8975f5c5SAndroid Build Coastguard Worker{ 108*8975f5c5SAndroid Build Coastguard Worker size_t offset; 109*8975f5c5SAndroid Build Coastguard Worker pool->releaseInFlightBuffers(context); 110*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(pool->allocate(context, indicesToReserve * sizeof(uint32_t), nullptr, bufferOut, 111*8975f5c5SAndroid Build Coastguard Worker &offset, nullptr)); 112*8975f5c5SAndroid Build Coastguard Worker 113*8975f5c5SAndroid Build Coastguard Worker *offsetOut = static_cast<uint32_t>(offset); 114*8975f5c5SAndroid Build Coastguard Worker 115*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 116*8975f5c5SAndroid Build Coastguard Worker} 117*8975f5c5SAndroid Build Coastguard Worker 118*8975f5c5SAndroid Build Coastguard Workerbool NeedToInvertDepthRange(float near, float far) 119*8975f5c5SAndroid Build Coastguard Worker{ 120*8975f5c5SAndroid Build Coastguard Worker return near > far; 121*8975f5c5SAndroid Build Coastguard Worker} 122*8975f5c5SAndroid Build Coastguard Worker 123*8975f5c5SAndroid Build Coastguard Workerbool IsTransformFeedbackOnly(const gl::State &glState) 124*8975f5c5SAndroid Build Coastguard Worker{ 125*8975f5c5SAndroid Build Coastguard Worker return glState.isTransformFeedbackActiveUnpaused() && glState.isRasterizerDiscardEnabled(); 126*8975f5c5SAndroid Build Coastguard Worker} 127*8975f5c5SAndroid Build Coastguard Worker 128*8975f5c5SAndroid Build Coastguard Workerstd::string ConvertMarkerToString(GLsizei length, const char *marker) 129*8975f5c5SAndroid Build Coastguard Worker{ 130*8975f5c5SAndroid Build Coastguard Worker std::string cppString; 131*8975f5c5SAndroid Build Coastguard Worker if (length == 0) 132*8975f5c5SAndroid Build Coastguard Worker { 133*8975f5c5SAndroid Build Coastguard Worker cppString = marker; 134*8975f5c5SAndroid Build Coastguard Worker } 135*8975f5c5SAndroid Build Coastguard Worker else 136*8975f5c5SAndroid Build Coastguard Worker { 137*8975f5c5SAndroid Build Coastguard Worker cppString.assign(marker, length); 138*8975f5c5SAndroid Build Coastguard Worker } 139*8975f5c5SAndroid Build Coastguard Worker return cppString; 140*8975f5c5SAndroid Build Coastguard Worker} 141*8975f5c5SAndroid Build Coastguard Worker 142*8975f5c5SAndroid Build Coastguard Worker// This class constructs line loop's last segment buffer inside begin() method 143*8975f5c5SAndroid Build Coastguard Worker// and perform the draw of the line loop's last segment inside destructor 144*8975f5c5SAndroid Build Coastguard Workerclass LineLoopLastSegmentHelper 145*8975f5c5SAndroid Build Coastguard Worker{ 146*8975f5c5SAndroid Build Coastguard Worker public: 147*8975f5c5SAndroid Build Coastguard Worker LineLoopLastSegmentHelper() {} 148*8975f5c5SAndroid Build Coastguard Worker 149*8975f5c5SAndroid Build Coastguard Worker ~LineLoopLastSegmentHelper() 150*8975f5c5SAndroid Build Coastguard Worker { 151*8975f5c5SAndroid Build Coastguard Worker if (!mLineLoopIndexBuffer) 152*8975f5c5SAndroid Build Coastguard Worker { 153*8975f5c5SAndroid Build Coastguard Worker return; 154*8975f5c5SAndroid Build Coastguard Worker } 155*8975f5c5SAndroid Build Coastguard Worker 156*8975f5c5SAndroid Build Coastguard Worker // Draw last segment of line loop here 157*8975f5c5SAndroid Build Coastguard Worker mtl::RenderCommandEncoder *encoder = mContextMtl->getRenderCommandEncoder(); 158*8975f5c5SAndroid Build Coastguard Worker ASSERT(encoder); 159*8975f5c5SAndroid Build Coastguard Worker encoder->drawIndexed(MTLPrimitiveTypeLine, 2, MTLIndexTypeUInt32, mLineLoopIndexBuffer, 0); 160*8975f5c5SAndroid Build Coastguard Worker } 161*8975f5c5SAndroid Build Coastguard Worker 162*8975f5c5SAndroid Build Coastguard Worker angle::Result begin(const gl::Context *context, 163*8975f5c5SAndroid Build Coastguard Worker mtl::BufferPool *indexBufferPool, 164*8975f5c5SAndroid Build Coastguard Worker GLint firstVertex, 165*8975f5c5SAndroid Build Coastguard Worker GLsizei vertexOrIndexCount, 166*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType indexTypeOrNone, 167*8975f5c5SAndroid Build Coastguard Worker const void *indices) 168*8975f5c5SAndroid Build Coastguard Worker { 169*8975f5c5SAndroid Build Coastguard Worker mContextMtl = mtl::GetImpl(context); 170*8975f5c5SAndroid Build Coastguard Worker 171*8975f5c5SAndroid Build Coastguard Worker indexBufferPool->releaseInFlightBuffers(mContextMtl); 172*8975f5c5SAndroid Build Coastguard Worker 173*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(indexBufferPool->allocate(mContextMtl, 2 * sizeof(uint32_t), nullptr, 174*8975f5c5SAndroid Build Coastguard Worker &mLineLoopIndexBuffer, nullptr, nullptr)); 175*8975f5c5SAndroid Build Coastguard Worker 176*8975f5c5SAndroid Build Coastguard Worker if (indexTypeOrNone == gl::DrawElementsType::InvalidEnum) 177*8975f5c5SAndroid Build Coastguard Worker { 178*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mContextMtl->getDisplay()->getUtils().generateLineLoopLastSegment( 179*8975f5c5SAndroid Build Coastguard Worker mContextMtl, firstVertex, firstVertex + vertexOrIndexCount - 1, 180*8975f5c5SAndroid Build Coastguard Worker mLineLoopIndexBuffer, 0)); 181*8975f5c5SAndroid Build Coastguard Worker } 182*8975f5c5SAndroid Build Coastguard Worker else 183*8975f5c5SAndroid Build Coastguard Worker { 184*8975f5c5SAndroid Build Coastguard Worker ASSERT(firstVertex == 0); 185*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY( 186*8975f5c5SAndroid Build Coastguard Worker mContextMtl->getDisplay()->getUtils().generateLineLoopLastSegmentFromElementsArray( 187*8975f5c5SAndroid Build Coastguard Worker mContextMtl, 188*8975f5c5SAndroid Build Coastguard Worker {indexTypeOrNone, vertexOrIndexCount, indices, mLineLoopIndexBuffer, 0})); 189*8975f5c5SAndroid Build Coastguard Worker } 190*8975f5c5SAndroid Build Coastguard Worker 191*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(indexBufferPool->commit(mContextMtl)); 192*8975f5c5SAndroid Build Coastguard Worker 193*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 194*8975f5c5SAndroid Build Coastguard Worker } 195*8975f5c5SAndroid Build Coastguard Worker 196*8975f5c5SAndroid Build Coastguard Worker private: 197*8975f5c5SAndroid Build Coastguard Worker ContextMtl *mContextMtl = nullptr; 198*8975f5c5SAndroid Build Coastguard Worker mtl::BufferRef mLineLoopIndexBuffer; 199*8975f5c5SAndroid Build Coastguard Worker}; 200*8975f5c5SAndroid Build Coastguard Worker 201*8975f5c5SAndroid Build Coastguard WorkerGLint GetOwnershipIdentity(const egl::AttributeMap &attribs) 202*8975f5c5SAndroid Build Coastguard Worker{ 203*8975f5c5SAndroid Build Coastguard Worker return attribs.getAsInt(EGL_CONTEXT_METAL_OWNERSHIP_IDENTITY_ANGLE, 0); 204*8975f5c5SAndroid Build Coastguard Worker} 205*8975f5c5SAndroid Build Coastguard Worker 206*8975f5c5SAndroid Build Coastguard Worker} // namespace 207*8975f5c5SAndroid Build Coastguard Worker 208*8975f5c5SAndroid Build Coastguard WorkerContextMtl::ContextMtl(const gl::State &state, 209*8975f5c5SAndroid Build Coastguard Worker gl::ErrorSet *errorSet, 210*8975f5c5SAndroid Build Coastguard Worker const egl::AttributeMap &attribs, 211*8975f5c5SAndroid Build Coastguard Worker DisplayMtl *display) 212*8975f5c5SAndroid Build Coastguard Worker : ContextImpl(state, errorSet), 213*8975f5c5SAndroid Build Coastguard Worker mtl::Context(display), 214*8975f5c5SAndroid Build Coastguard Worker mCmdBuffer(&display->cmdQueue()), 215*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder(&mCmdBuffer, 216*8975f5c5SAndroid Build Coastguard Worker mOcclusionQueryPool, 217*8975f5c5SAndroid Build Coastguard Worker display->getFeatures().emulateDontCareLoadWithRandomClear.enabled), 218*8975f5c5SAndroid Build Coastguard Worker mBlitEncoder(&mCmdBuffer), 219*8975f5c5SAndroid Build Coastguard Worker mComputeEncoder(&mCmdBuffer), 220*8975f5c5SAndroid Build Coastguard Worker mDriverUniforms{}, 221*8975f5c5SAndroid Build Coastguard Worker mProvokingVertexHelper(this), 222*8975f5c5SAndroid Build Coastguard Worker mContextDevice(GetOwnershipIdentity(attribs)) 223*8975f5c5SAndroid Build Coastguard Worker{} 224*8975f5c5SAndroid Build Coastguard Worker 225*8975f5c5SAndroid Build Coastguard WorkerContextMtl::~ContextMtl() {} 226*8975f5c5SAndroid Build Coastguard Worker 227*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::initialize(const angle::ImageLoadContext &imageLoadContext) 228*8975f5c5SAndroid Build Coastguard Worker{ 229*8975f5c5SAndroid Build Coastguard Worker for (mtl::BlendDesc &blendDesc : mBlendDescArray) 230*8975f5c5SAndroid Build Coastguard Worker { 231*8975f5c5SAndroid Build Coastguard Worker blendDesc.reset(); 232*8975f5c5SAndroid Build Coastguard Worker } 233*8975f5c5SAndroid Build Coastguard Worker 234*8975f5c5SAndroid Build Coastguard Worker mWriteMaskArray.fill(MTLColorWriteMaskAll); 235*8975f5c5SAndroid Build Coastguard Worker 236*8975f5c5SAndroid Build Coastguard Worker mDepthStencilDesc.reset(); 237*8975f5c5SAndroid Build Coastguard Worker 238*8975f5c5SAndroid Build Coastguard Worker mTriFanIndexBuffer.initialize(this, 0, mtl::kIndexBufferOffsetAlignment, 239*8975f5c5SAndroid Build Coastguard Worker kMaxTriFanLineLoopBuffersPerFrame); 240*8975f5c5SAndroid Build Coastguard Worker mLineLoopIndexBuffer.initialize(this, 0, mtl::kIndexBufferOffsetAlignment, 241*8975f5c5SAndroid Build Coastguard Worker kMaxTriFanLineLoopBuffersPerFrame); 242*8975f5c5SAndroid Build Coastguard Worker mLineLoopLastSegmentIndexBuffer.initialize(this, 2 * sizeof(uint32_t), 243*8975f5c5SAndroid Build Coastguard Worker mtl::kIndexBufferOffsetAlignment, 244*8975f5c5SAndroid Build Coastguard Worker kMaxTriFanLineLoopBuffersPerFrame); 245*8975f5c5SAndroid Build Coastguard Worker 246*8975f5c5SAndroid Build Coastguard Worker mContextDevice.set(mDisplay->getMetalDevice()); 247*8975f5c5SAndroid Build Coastguard Worker 248*8975f5c5SAndroid Build Coastguard Worker mImageLoadContext = imageLoadContext; 249*8975f5c5SAndroid Build Coastguard Worker 250*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 251*8975f5c5SAndroid Build Coastguard Worker} 252*8975f5c5SAndroid Build Coastguard Worker 253*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::onDestroy(const gl::Context *context) 254*8975f5c5SAndroid Build Coastguard Worker{ 255*8975f5c5SAndroid Build Coastguard Worker mTriFanIndexBuffer.destroy(this); 256*8975f5c5SAndroid Build Coastguard Worker mLineLoopIndexBuffer.destroy(this); 257*8975f5c5SAndroid Build Coastguard Worker mLineLoopLastSegmentIndexBuffer.destroy(this); 258*8975f5c5SAndroid Build Coastguard Worker mOcclusionQueryPool.destroy(this); 259*8975f5c5SAndroid Build Coastguard Worker 260*8975f5c5SAndroid Build Coastguard Worker mIncompleteTextures.onDestroy(context); 261*8975f5c5SAndroid Build Coastguard Worker mProvokingVertexHelper.onDestroy(this); 262*8975f5c5SAndroid Build Coastguard Worker mDummyXFBRenderTexture = nullptr; 263*8975f5c5SAndroid Build Coastguard Worker 264*8975f5c5SAndroid Build Coastguard Worker mContextDevice.reset(); 265*8975f5c5SAndroid Build Coastguard Worker} 266*8975f5c5SAndroid Build Coastguard Worker 267*8975f5c5SAndroid Build Coastguard Worker// Flush and finish. 268*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::flush(const gl::Context *context) 269*8975f5c5SAndroid Build Coastguard Worker{ 270*8975f5c5SAndroid Build Coastguard Worker // MTLSharedEvent is available on these platforms, and callers 271*8975f5c5SAndroid Build Coastguard Worker // are expected to use the EGL_ANGLE_metal_shared_event_sync 272*8975f5c5SAndroid Build Coastguard Worker // extension to synchronize with ANGLE's Metal backend, if 273*8975f5c5SAndroid Build Coastguard Worker // needed. This is typically required if two MTLDevices are 274*8975f5c5SAndroid Build Coastguard Worker // operating on the same IOSurface. 275*8975f5c5SAndroid Build Coastguard Worker flushCommandBuffer(mtl::NoWait); 276*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 277*8975f5c5SAndroid Build Coastguard Worker} 278*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::finish(const gl::Context *context) 279*8975f5c5SAndroid Build Coastguard Worker{ 280*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(finishCommandBuffer()); 281*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 282*8975f5c5SAndroid Build Coastguard Worker} 283*8975f5c5SAndroid Build Coastguard Worker 284*8975f5c5SAndroid Build Coastguard WorkerANGLE_INLINE angle::Result ContextMtl::resyncDrawFramebufferIfNeeded(const gl::Context *context) 285*8975f5c5SAndroid Build Coastguard Worker{ 286*8975f5c5SAndroid Build Coastguard Worker // Resync the draw framebuffer if 287*8975f5c5SAndroid Build Coastguard Worker // - it has incompatible attachments; OR 288*8975f5c5SAndroid Build Coastguard Worker // - it had incompatible attachments during the previous operation. 289*8975f5c5SAndroid Build Coastguard Worker if (ANGLE_UNLIKELY(mIncompatibleAttachments.any() || mForceResyncDrawFramebuffer)) 290*8975f5c5SAndroid Build Coastguard Worker { 291*8975f5c5SAndroid Build Coastguard Worker if (mIncompatibleAttachments.any()) 292*8975f5c5SAndroid Build Coastguard Worker { 293*8975f5c5SAndroid Build Coastguard Worker ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW, 294*8975f5c5SAndroid Build Coastguard Worker "Resyncing the draw framebuffer because it has active attachments " 295*8975f5c5SAndroid Build Coastguard Worker "incompatible with the current program outputs."); 296*8975f5c5SAndroid Build Coastguard Worker } 297*8975f5c5SAndroid Build Coastguard Worker 298*8975f5c5SAndroid Build Coastguard Worker // Ensure sync on the next operation if the current state has incompatible attachments. 299*8975f5c5SAndroid Build Coastguard Worker mForceResyncDrawFramebuffer = mIncompatibleAttachments.any(); 300*8975f5c5SAndroid Build Coastguard Worker 301*8975f5c5SAndroid Build Coastguard Worker FramebufferMtl *fbo = mtl::GetImpl(getState().getDrawFramebuffer()); 302*8975f5c5SAndroid Build Coastguard Worker ASSERT(fbo != nullptr); 303*8975f5c5SAndroid Build Coastguard Worker return fbo->syncState(context, GL_DRAW_FRAMEBUFFER, gl::Framebuffer::DirtyBits(), 304*8975f5c5SAndroid Build Coastguard Worker gl::Command::Draw); 305*8975f5c5SAndroid Build Coastguard Worker } 306*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 307*8975f5c5SAndroid Build Coastguard Worker} 308*8975f5c5SAndroid Build Coastguard Worker 309*8975f5c5SAndroid Build Coastguard Worker// Drawing methods. 310*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawTriFanArraysWithBaseVertex(const gl::Context *context, 311*8975f5c5SAndroid Build Coastguard Worker GLint first, 312*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 313*8975f5c5SAndroid Build Coastguard Worker GLsizei instances, 314*8975f5c5SAndroid Build Coastguard Worker GLuint baseInstance) 315*8975f5c5SAndroid Build Coastguard Worker{ 316*8975f5c5SAndroid Build Coastguard Worker ASSERT((getDisplay()->getFeatures().hasBaseVertexInstancedDraw.enabled)); 317*8975f5c5SAndroid Build Coastguard Worker 318*8975f5c5SAndroid Build Coastguard Worker uint32_t genIndicesCount; 319*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mtl::GetTriangleFanIndicesCount(this, count, &genIndicesCount)); 320*8975f5c5SAndroid Build Coastguard Worker 321*8975f5c5SAndroid Build Coastguard Worker size_t indexBufferSize = genIndicesCount * sizeof(uint32_t); 322*8975f5c5SAndroid Build Coastguard Worker // We can reuse the previously generated index buffer if it has more than enough indices 323*8975f5c5SAndroid Build Coastguard Worker // data already. 324*8975f5c5SAndroid Build Coastguard Worker if (mTriFanArraysIndexBuffer == nullptr || mTriFanArraysIndexBuffer->size() < indexBufferSize) 325*8975f5c5SAndroid Build Coastguard Worker { 326*8975f5c5SAndroid Build Coastguard Worker // Re-generate a new index buffer, which the first index will be zero. 327*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY( 328*8975f5c5SAndroid Build Coastguard Worker mtl::Buffer::MakeBuffer(this, indexBufferSize, nullptr, &mTriFanArraysIndexBuffer)); 329*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(getDisplay()->getUtils().generateTriFanBufferFromArrays( 330*8975f5c5SAndroid Build Coastguard Worker this, {0, static_cast<uint32_t>(count), mTriFanArraysIndexBuffer, 0})); 331*8975f5c5SAndroid Build Coastguard Worker } 332*8975f5c5SAndroid Build Coastguard Worker 333*8975f5c5SAndroid Build Coastguard Worker ASSERT(!getState().isTransformFeedbackActiveUnpaused()); 334*8975f5c5SAndroid Build Coastguard Worker bool isNoOp = false; 335*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setupDraw(context, gl::PrimitiveMode::TriangleFan, first, count, instances, 336*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType::InvalidEnum, reinterpret_cast<const void *>(0), false, 337*8975f5c5SAndroid Build Coastguard Worker &isNoOp)); 338*8975f5c5SAndroid Build Coastguard Worker if (!isNoOp) 339*8975f5c5SAndroid Build Coastguard Worker { 340*8975f5c5SAndroid Build Coastguard Worker // Draw with the zero starting index buffer, shift the vertex index using baseVertex 341*8975f5c5SAndroid Build Coastguard Worker // instanced draw: 342*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.drawIndexedInstancedBaseVertexBaseInstance( 343*8975f5c5SAndroid Build Coastguard Worker MTLPrimitiveTypeTriangle, genIndicesCount, MTLIndexTypeUInt32, mTriFanArraysIndexBuffer, 344*8975f5c5SAndroid Build Coastguard Worker 0, instances, first, baseInstance); 345*8975f5c5SAndroid Build Coastguard Worker } 346*8975f5c5SAndroid Build Coastguard Worker 347*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 348*8975f5c5SAndroid Build Coastguard Worker} 349*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawTriFanArraysLegacy(const gl::Context *context, 350*8975f5c5SAndroid Build Coastguard Worker GLint first, 351*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 352*8975f5c5SAndroid Build Coastguard Worker GLsizei instances) 353*8975f5c5SAndroid Build Coastguard Worker{ 354*8975f5c5SAndroid Build Coastguard Worker // Legacy method is only used for GPU lacking instanced base vertex draw capabilities. 355*8975f5c5SAndroid Build Coastguard Worker mtl::BufferRef genIdxBuffer; 356*8975f5c5SAndroid Build Coastguard Worker uint32_t genIdxBufferOffset; 357*8975f5c5SAndroid Build Coastguard Worker uint32_t genIndicesCount; 358*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(AllocateTriangleFanBufferFromPool(this, count, &mTriFanIndexBuffer, &genIdxBuffer, 359*8975f5c5SAndroid Build Coastguard Worker &genIdxBufferOffset, &genIndicesCount)); 360*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(getDisplay()->getUtils().generateTriFanBufferFromArrays( 361*8975f5c5SAndroid Build Coastguard Worker this, {static_cast<uint32_t>(first), static_cast<uint32_t>(count), genIdxBuffer, 362*8975f5c5SAndroid Build Coastguard Worker genIdxBufferOffset})); 363*8975f5c5SAndroid Build Coastguard Worker 364*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mTriFanIndexBuffer.commit(this)); 365*8975f5c5SAndroid Build Coastguard Worker 366*8975f5c5SAndroid Build Coastguard Worker ASSERT(!getState().isTransformFeedbackActiveUnpaused()); 367*8975f5c5SAndroid Build Coastguard Worker bool isNoOp = false; 368*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setupDraw(context, gl::PrimitiveMode::TriangleFan, first, count, instances, 369*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType::InvalidEnum, reinterpret_cast<const void *>(0), false, 370*8975f5c5SAndroid Build Coastguard Worker &isNoOp)); 371*8975f5c5SAndroid Build Coastguard Worker if (!isNoOp) 372*8975f5c5SAndroid Build Coastguard Worker { 373*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.drawIndexedInstanced(MTLPrimitiveTypeTriangle, genIndicesCount, 374*8975f5c5SAndroid Build Coastguard Worker MTLIndexTypeUInt32, genIdxBuffer, genIdxBufferOffset, 375*8975f5c5SAndroid Build Coastguard Worker instances); 376*8975f5c5SAndroid Build Coastguard Worker } 377*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 378*8975f5c5SAndroid Build Coastguard Worker} 379*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawTriFanArrays(const gl::Context *context, 380*8975f5c5SAndroid Build Coastguard Worker GLint first, 381*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 382*8975f5c5SAndroid Build Coastguard Worker GLsizei instances, 383*8975f5c5SAndroid Build Coastguard Worker GLuint baseInstance) 384*8975f5c5SAndroid Build Coastguard Worker{ 385*8975f5c5SAndroid Build Coastguard Worker if (count <= 3 && baseInstance == 0) 386*8975f5c5SAndroid Build Coastguard Worker { 387*8975f5c5SAndroid Build Coastguard Worker return drawArraysImpl(context, gl::PrimitiveMode::Triangles, first, count, instances, 0); 388*8975f5c5SAndroid Build Coastguard Worker } 389*8975f5c5SAndroid Build Coastguard Worker if (getDisplay()->getFeatures().hasBaseVertexInstancedDraw.enabled) 390*8975f5c5SAndroid Build Coastguard Worker { 391*8975f5c5SAndroid Build Coastguard Worker return drawTriFanArraysWithBaseVertex(context, first, count, instances, baseInstance); 392*8975f5c5SAndroid Build Coastguard Worker } 393*8975f5c5SAndroid Build Coastguard Worker return drawTriFanArraysLegacy(context, first, count, instances); 394*8975f5c5SAndroid Build Coastguard Worker} 395*8975f5c5SAndroid Build Coastguard Worker 396*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawLineLoopArraysNonInstanced(const gl::Context *context, 397*8975f5c5SAndroid Build Coastguard Worker GLint first, 398*8975f5c5SAndroid Build Coastguard Worker GLsizei count) 399*8975f5c5SAndroid Build Coastguard Worker{ 400*8975f5c5SAndroid Build Coastguard Worker // Generate line loop's last segment. It will be rendered when this function exits. 401*8975f5c5SAndroid Build Coastguard Worker LineLoopLastSegmentHelper lineloopHelper; 402*8975f5c5SAndroid Build Coastguard Worker // Line loop helper needs to generate last segment indices before rendering command encoder 403*8975f5c5SAndroid Build Coastguard Worker // starts. 404*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(lineloopHelper.begin(context, &mLineLoopLastSegmentIndexBuffer, first, count, 405*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType::InvalidEnum, nullptr)); 406*8975f5c5SAndroid Build Coastguard Worker 407*8975f5c5SAndroid Build Coastguard Worker return drawArraysImpl(context, gl::PrimitiveMode::LineStrip, first, count, 0, 0); 408*8975f5c5SAndroid Build Coastguard Worker} 409*8975f5c5SAndroid Build Coastguard Worker 410*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawLineLoopArrays(const gl::Context *context, 411*8975f5c5SAndroid Build Coastguard Worker GLint first, 412*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 413*8975f5c5SAndroid Build Coastguard Worker GLsizei instances, 414*8975f5c5SAndroid Build Coastguard Worker GLuint baseInstance) 415*8975f5c5SAndroid Build Coastguard Worker{ 416*8975f5c5SAndroid Build Coastguard Worker if (instances <= 1 && baseInstance == 0) 417*8975f5c5SAndroid Build Coastguard Worker { 418*8975f5c5SAndroid Build Coastguard Worker return drawLineLoopArraysNonInstanced(context, first, count); 419*8975f5c5SAndroid Build Coastguard Worker } 420*8975f5c5SAndroid Build Coastguard Worker 421*8975f5c5SAndroid Build Coastguard Worker mtl::BufferRef genIdxBuffer; 422*8975f5c5SAndroid Build Coastguard Worker uint32_t genIdxBufferOffset; 423*8975f5c5SAndroid Build Coastguard Worker uint32_t genIndicesCount = count + 1; 424*8975f5c5SAndroid Build Coastguard Worker 425*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(AllocateBufferFromPool(this, genIndicesCount, &mLineLoopIndexBuffer, &genIdxBuffer, 426*8975f5c5SAndroid Build Coastguard Worker &genIdxBufferOffset)); 427*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(getDisplay()->getUtils().generateLineLoopBufferFromArrays( 428*8975f5c5SAndroid Build Coastguard Worker this, {static_cast<uint32_t>(first), static_cast<uint32_t>(count), genIdxBuffer, 429*8975f5c5SAndroid Build Coastguard Worker genIdxBufferOffset})); 430*8975f5c5SAndroid Build Coastguard Worker 431*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mLineLoopIndexBuffer.commit(this)); 432*8975f5c5SAndroid Build Coastguard Worker 433*8975f5c5SAndroid Build Coastguard Worker ASSERT(!getState().isTransformFeedbackActiveUnpaused()); 434*8975f5c5SAndroid Build Coastguard Worker bool isNoOp = false; 435*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setupDraw(context, gl::PrimitiveMode::LineLoop, first, count, instances, 436*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType::InvalidEnum, nullptr, false, &isNoOp)); 437*8975f5c5SAndroid Build Coastguard Worker if (!isNoOp) 438*8975f5c5SAndroid Build Coastguard Worker { 439*8975f5c5SAndroid Build Coastguard Worker if (baseInstance == 0) 440*8975f5c5SAndroid Build Coastguard Worker { 441*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.drawIndexedInstanced(MTLPrimitiveTypeLineStrip, genIndicesCount, 442*8975f5c5SAndroid Build Coastguard Worker MTLIndexTypeUInt32, genIdxBuffer, 443*8975f5c5SAndroid Build Coastguard Worker genIdxBufferOffset, instances); 444*8975f5c5SAndroid Build Coastguard Worker } 445*8975f5c5SAndroid Build Coastguard Worker else 446*8975f5c5SAndroid Build Coastguard Worker { 447*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.drawIndexedInstancedBaseVertexBaseInstance( 448*8975f5c5SAndroid Build Coastguard Worker MTLPrimitiveTypeLineStrip, genIndicesCount, MTLIndexTypeUInt32, genIdxBuffer, 449*8975f5c5SAndroid Build Coastguard Worker genIdxBufferOffset, instances, 0, baseInstance); 450*8975f5c5SAndroid Build Coastguard Worker } 451*8975f5c5SAndroid Build Coastguard Worker } 452*8975f5c5SAndroid Build Coastguard Worker 453*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 454*8975f5c5SAndroid Build Coastguard Worker} 455*8975f5c5SAndroid Build Coastguard Worker 456*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawArraysImpl(const gl::Context *context, 457*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 458*8975f5c5SAndroid Build Coastguard Worker GLint first, 459*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 460*8975f5c5SAndroid Build Coastguard Worker GLsizei instances, 461*8975f5c5SAndroid Build Coastguard Worker GLuint baseInstance) 462*8975f5c5SAndroid Build Coastguard Worker{ 463*8975f5c5SAndroid Build Coastguard Worker // Real instances count. Zero means this is not instanced draw. 464*8975f5c5SAndroid Build Coastguard Worker GLsizei instanceCount = instances ? instances : 1; 465*8975f5c5SAndroid Build Coastguard Worker 466*8975f5c5SAndroid Build Coastguard Worker if (mCullAllPolygons && gl::IsPolygonMode(mode)) 467*8975f5c5SAndroid Build Coastguard Worker { 468*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 469*8975f5c5SAndroid Build Coastguard Worker } 470*8975f5c5SAndroid Build Coastguard Worker if (requiresIndexRewrite(context->getState(), mode)) 471*8975f5c5SAndroid Build Coastguard Worker { 472*8975f5c5SAndroid Build Coastguard Worker return drawArraysProvokingVertexImpl(context, mode, first, count, instances, baseInstance); 473*8975f5c5SAndroid Build Coastguard Worker } 474*8975f5c5SAndroid Build Coastguard Worker if (mode == gl::PrimitiveMode::TriangleFan) 475*8975f5c5SAndroid Build Coastguard Worker { 476*8975f5c5SAndroid Build Coastguard Worker return drawTriFanArrays(context, first, count, instanceCount, baseInstance); 477*8975f5c5SAndroid Build Coastguard Worker } 478*8975f5c5SAndroid Build Coastguard Worker else if (mode == gl::PrimitiveMode::LineLoop) 479*8975f5c5SAndroid Build Coastguard Worker { 480*8975f5c5SAndroid Build Coastguard Worker return drawLineLoopArrays(context, first, count, instanceCount, baseInstance); 481*8975f5c5SAndroid Build Coastguard Worker } 482*8975f5c5SAndroid Build Coastguard Worker 483*8975f5c5SAndroid Build Coastguard Worker MTLPrimitiveType mtlType = mtl::GetPrimitiveType(mode); 484*8975f5c5SAndroid Build Coastguard Worker 485*8975f5c5SAndroid Build Coastguard Worker#define DRAW_GENERIC_ARRAY(xfbPass) \ 486*8975f5c5SAndroid Build Coastguard Worker { \ 487*8975f5c5SAndroid Build Coastguard Worker bool isNoOp = false; \ 488*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setupDraw(context, mode, first, count, instances, \ 489*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType::InvalidEnum, nullptr, xfbPass, &isNoOp)); \ 490*8975f5c5SAndroid Build Coastguard Worker if (!isNoOp) \ 491*8975f5c5SAndroid Build Coastguard Worker { \ 492*8975f5c5SAndroid Build Coastguard Worker \ 493*8975f5c5SAndroid Build Coastguard Worker if (instances == 0) \ 494*8975f5c5SAndroid Build Coastguard Worker { \ 495*8975f5c5SAndroid Build Coastguard Worker /* This method is called from normal drawArrays() */ \ 496*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.draw(mtlType, first, count); \ 497*8975f5c5SAndroid Build Coastguard Worker } \ 498*8975f5c5SAndroid Build Coastguard Worker else \ 499*8975f5c5SAndroid Build Coastguard Worker { \ 500*8975f5c5SAndroid Build Coastguard Worker if (baseInstance == 0) \ 501*8975f5c5SAndroid Build Coastguard Worker { \ 502*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.drawInstanced(mtlType, first, count, instanceCount); \ 503*8975f5c5SAndroid Build Coastguard Worker } \ 504*8975f5c5SAndroid Build Coastguard Worker else \ 505*8975f5c5SAndroid Build Coastguard Worker { \ 506*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.drawInstancedBaseInstance(mtlType, first, count, instanceCount, \ 507*8975f5c5SAndroid Build Coastguard Worker baseInstance); \ 508*8975f5c5SAndroid Build Coastguard Worker } \ 509*8975f5c5SAndroid Build Coastguard Worker } \ 510*8975f5c5SAndroid Build Coastguard Worker } \ 511*8975f5c5SAndroid Build Coastguard Worker } 512*8975f5c5SAndroid Build Coastguard Worker 513*8975f5c5SAndroid Build Coastguard Worker ANGLE_MTL_XFB_DRAW(DRAW_GENERIC_ARRAY) 514*8975f5c5SAndroid Build Coastguard Worker 515*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 516*8975f5c5SAndroid Build Coastguard Worker} 517*8975f5c5SAndroid Build Coastguard Worker 518*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawArrays(const gl::Context *context, 519*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 520*8975f5c5SAndroid Build Coastguard Worker GLint first, 521*8975f5c5SAndroid Build Coastguard Worker GLsizei count) 522*8975f5c5SAndroid Build Coastguard Worker{ 523*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(resyncDrawFramebufferIfNeeded(context)); 524*8975f5c5SAndroid Build Coastguard Worker return drawArraysImpl(context, mode, first, count, 0, 0); 525*8975f5c5SAndroid Build Coastguard Worker} 526*8975f5c5SAndroid Build Coastguard Worker 527*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawArraysInstanced(const gl::Context *context, 528*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 529*8975f5c5SAndroid Build Coastguard Worker GLint first, 530*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 531*8975f5c5SAndroid Build Coastguard Worker GLsizei instances) 532*8975f5c5SAndroid Build Coastguard Worker{ 533*8975f5c5SAndroid Build Coastguard Worker // Instanced draw calls with zero instances are skipped in the frontend. 534*8975f5c5SAndroid Build Coastguard Worker // The drawArraysImpl function would treat them as non-instanced. 535*8975f5c5SAndroid Build Coastguard Worker ASSERT(instances > 0); 536*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(resyncDrawFramebufferIfNeeded(context)); 537*8975f5c5SAndroid Build Coastguard Worker return drawArraysImpl(context, mode, first, count, instances, 0); 538*8975f5c5SAndroid Build Coastguard Worker} 539*8975f5c5SAndroid Build Coastguard Worker 540*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawArraysInstancedBaseInstance(const gl::Context *context, 541*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 542*8975f5c5SAndroid Build Coastguard Worker GLint first, 543*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 544*8975f5c5SAndroid Build Coastguard Worker GLsizei instanceCount, 545*8975f5c5SAndroid Build Coastguard Worker GLuint baseInstance) 546*8975f5c5SAndroid Build Coastguard Worker{ 547*8975f5c5SAndroid Build Coastguard Worker // Instanced draw calls with zero instances are skipped in the frontend. 548*8975f5c5SAndroid Build Coastguard Worker // The drawArraysImpl function would treat them as non-instanced. 549*8975f5c5SAndroid Build Coastguard Worker ASSERT(instanceCount > 0); 550*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(resyncDrawFramebufferIfNeeded(context)); 551*8975f5c5SAndroid Build Coastguard Worker return drawArraysImpl(context, mode, first, count, instanceCount, baseInstance); 552*8975f5c5SAndroid Build Coastguard Worker} 553*8975f5c5SAndroid Build Coastguard Worker 554*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawTriFanElements(const gl::Context *context, 555*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 556*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type, 557*8975f5c5SAndroid Build Coastguard Worker const void *indices, 558*8975f5c5SAndroid Build Coastguard Worker GLsizei instances, 559*8975f5c5SAndroid Build Coastguard Worker GLint baseVertex, 560*8975f5c5SAndroid Build Coastguard Worker GLuint baseInstance) 561*8975f5c5SAndroid Build Coastguard Worker{ 562*8975f5c5SAndroid Build Coastguard Worker if (count > 3) 563*8975f5c5SAndroid Build Coastguard Worker { 564*8975f5c5SAndroid Build Coastguard Worker mtl::BufferRef genIdxBuffer; 565*8975f5c5SAndroid Build Coastguard Worker uint32_t genIdxBufferOffset; 566*8975f5c5SAndroid Build Coastguard Worker uint32_t genIndicesCount; 567*8975f5c5SAndroid Build Coastguard Worker bool primitiveRestart = getState().isPrimitiveRestartEnabled(); 568*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(AllocateTriangleFanBufferFromPool(this, count, &mTriFanIndexBuffer, &genIdxBuffer, 569*8975f5c5SAndroid Build Coastguard Worker &genIdxBufferOffset, &genIndicesCount)); 570*8975f5c5SAndroid Build Coastguard Worker 571*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(getDisplay()->getUtils().generateTriFanBufferFromElementsArray( 572*8975f5c5SAndroid Build Coastguard Worker this, {type, count, indices, genIdxBuffer, genIdxBufferOffset, primitiveRestart}, 573*8975f5c5SAndroid Build Coastguard Worker &genIndicesCount)); 574*8975f5c5SAndroid Build Coastguard Worker 575*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mTriFanIndexBuffer.commit(this)); 576*8975f5c5SAndroid Build Coastguard Worker bool isNoOp = false; 577*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setupDraw(context, gl::PrimitiveMode::TriangleFan, 0, count, instances, type, 578*8975f5c5SAndroid Build Coastguard Worker indices, false, &isNoOp)); 579*8975f5c5SAndroid Build Coastguard Worker if (!isNoOp && genIndicesCount > 0) 580*8975f5c5SAndroid Build Coastguard Worker { 581*8975f5c5SAndroid Build Coastguard Worker if (baseVertex == 0 && baseInstance == 0) 582*8975f5c5SAndroid Build Coastguard Worker { 583*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.drawIndexedInstanced(MTLPrimitiveTypeTriangle, genIndicesCount, 584*8975f5c5SAndroid Build Coastguard Worker MTLIndexTypeUInt32, genIdxBuffer, 585*8975f5c5SAndroid Build Coastguard Worker genIdxBufferOffset, instances); 586*8975f5c5SAndroid Build Coastguard Worker } 587*8975f5c5SAndroid Build Coastguard Worker else 588*8975f5c5SAndroid Build Coastguard Worker { 589*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.drawIndexedInstancedBaseVertexBaseInstance( 590*8975f5c5SAndroid Build Coastguard Worker MTLPrimitiveTypeTriangle, genIndicesCount, MTLIndexTypeUInt32, genIdxBuffer, 591*8975f5c5SAndroid Build Coastguard Worker genIdxBufferOffset, instances, baseVertex, baseInstance); 592*8975f5c5SAndroid Build Coastguard Worker } 593*8975f5c5SAndroid Build Coastguard Worker } 594*8975f5c5SAndroid Build Coastguard Worker 595*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 596*8975f5c5SAndroid Build Coastguard Worker } // if (count > 3) 597*8975f5c5SAndroid Build Coastguard Worker return drawElementsImpl(context, gl::PrimitiveMode::Triangles, count, type, indices, instances, 598*8975f5c5SAndroid Build Coastguard Worker baseVertex, baseInstance); 599*8975f5c5SAndroid Build Coastguard Worker} 600*8975f5c5SAndroid Build Coastguard Worker 601*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawLineLoopElementsNonInstancedNoPrimitiveRestart( 602*8975f5c5SAndroid Build Coastguard Worker const gl::Context *context, 603*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 604*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type, 605*8975f5c5SAndroid Build Coastguard Worker const void *indices) 606*8975f5c5SAndroid Build Coastguard Worker{ 607*8975f5c5SAndroid Build Coastguard Worker // Generate line loop's last segment. It will be rendered when this function exits. 608*8975f5c5SAndroid Build Coastguard Worker LineLoopLastSegmentHelper lineloopHelper; 609*8975f5c5SAndroid Build Coastguard Worker // Line loop helper needs to generate index before rendering command encoder starts. 610*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY( 611*8975f5c5SAndroid Build Coastguard Worker lineloopHelper.begin(context, &mLineLoopLastSegmentIndexBuffer, 0, count, type, indices)); 612*8975f5c5SAndroid Build Coastguard Worker 613*8975f5c5SAndroid Build Coastguard Worker return drawElementsImpl(context, gl::PrimitiveMode::LineStrip, count, type, indices, 0, 0, 0); 614*8975f5c5SAndroid Build Coastguard Worker} 615*8975f5c5SAndroid Build Coastguard Worker 616*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawLineLoopElements(const gl::Context *context, 617*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 618*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type, 619*8975f5c5SAndroid Build Coastguard Worker const void *indices, 620*8975f5c5SAndroid Build Coastguard Worker GLsizei instances, 621*8975f5c5SAndroid Build Coastguard Worker GLint baseVertex, 622*8975f5c5SAndroid Build Coastguard Worker GLuint baseInstance) 623*8975f5c5SAndroid Build Coastguard Worker{ 624*8975f5c5SAndroid Build Coastguard Worker if (count >= 2) 625*8975f5c5SAndroid Build Coastguard Worker { 626*8975f5c5SAndroid Build Coastguard Worker bool primitiveRestart = getState().isPrimitiveRestartEnabled(); 627*8975f5c5SAndroid Build Coastguard Worker if (instances <= 1 && !primitiveRestart && baseVertex == 0 && baseInstance == 0) 628*8975f5c5SAndroid Build Coastguard Worker { 629*8975f5c5SAndroid Build Coastguard Worker // Non instanced draw and no primitive restart, just use faster version. 630*8975f5c5SAndroid Build Coastguard Worker return drawLineLoopElementsNonInstancedNoPrimitiveRestart(context, count, type, 631*8975f5c5SAndroid Build Coastguard Worker indices); 632*8975f5c5SAndroid Build Coastguard Worker } 633*8975f5c5SAndroid Build Coastguard Worker 634*8975f5c5SAndroid Build Coastguard Worker mtl::BufferRef genIdxBuffer; 635*8975f5c5SAndroid Build Coastguard Worker uint32_t genIdxBufferOffset; 636*8975f5c5SAndroid Build Coastguard Worker uint32_t reservedIndices = count * 2; 637*8975f5c5SAndroid Build Coastguard Worker uint32_t genIndicesCount; 638*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(AllocateBufferFromPool(this, reservedIndices, &mLineLoopIndexBuffer, 639*8975f5c5SAndroid Build Coastguard Worker &genIdxBuffer, &genIdxBufferOffset)); 640*8975f5c5SAndroid Build Coastguard Worker 641*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(getDisplay()->getUtils().generateLineLoopBufferFromElementsArray( 642*8975f5c5SAndroid Build Coastguard Worker this, {type, count, indices, genIdxBuffer, genIdxBufferOffset, primitiveRestart}, 643*8975f5c5SAndroid Build Coastguard Worker &genIndicesCount)); 644*8975f5c5SAndroid Build Coastguard Worker 645*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mLineLoopIndexBuffer.commit(this)); 646*8975f5c5SAndroid Build Coastguard Worker bool isNoOp = false; 647*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setupDraw(context, gl::PrimitiveMode::LineLoop, 0, count, instances, type, 648*8975f5c5SAndroid Build Coastguard Worker indices, false, &isNoOp)); 649*8975f5c5SAndroid Build Coastguard Worker if (!isNoOp && genIndicesCount > 0) 650*8975f5c5SAndroid Build Coastguard Worker { 651*8975f5c5SAndroid Build Coastguard Worker if (baseVertex == 0 && baseInstance == 0) 652*8975f5c5SAndroid Build Coastguard Worker { 653*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.drawIndexedInstanced(MTLPrimitiveTypeLineStrip, genIndicesCount, 654*8975f5c5SAndroid Build Coastguard Worker MTLIndexTypeUInt32, genIdxBuffer, 655*8975f5c5SAndroid Build Coastguard Worker genIdxBufferOffset, instances); 656*8975f5c5SAndroid Build Coastguard Worker } 657*8975f5c5SAndroid Build Coastguard Worker else 658*8975f5c5SAndroid Build Coastguard Worker { 659*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.drawIndexedInstancedBaseVertexBaseInstance( 660*8975f5c5SAndroid Build Coastguard Worker MTLPrimitiveTypeLineStrip, genIndicesCount, MTLIndexTypeUInt32, genIdxBuffer, 661*8975f5c5SAndroid Build Coastguard Worker genIdxBufferOffset, instances, baseVertex, baseInstance); 662*8975f5c5SAndroid Build Coastguard Worker } 663*8975f5c5SAndroid Build Coastguard Worker } 664*8975f5c5SAndroid Build Coastguard Worker 665*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 666*8975f5c5SAndroid Build Coastguard Worker } // if (count >= 2) 667*8975f5c5SAndroid Build Coastguard Worker return drawElementsImpl(context, gl::PrimitiveMode::Lines, count, type, indices, instances, 668*8975f5c5SAndroid Build Coastguard Worker baseVertex, baseInstance); 669*8975f5c5SAndroid Build Coastguard Worker} 670*8975f5c5SAndroid Build Coastguard Worker 671*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawArraysProvokingVertexImpl(const gl::Context *context, 672*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 673*8975f5c5SAndroid Build Coastguard Worker GLsizei first, 674*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 675*8975f5c5SAndroid Build Coastguard Worker GLsizei instances, 676*8975f5c5SAndroid Build Coastguard Worker GLuint baseInstance) 677*8975f5c5SAndroid Build Coastguard Worker{ 678*8975f5c5SAndroid Build Coastguard Worker 679*8975f5c5SAndroid Build Coastguard Worker size_t outIndexCount = 0; 680*8975f5c5SAndroid Build Coastguard Worker size_t outIndexOffset = 0; 681*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType convertedType = gl::DrawElementsType::UnsignedInt; 682*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode outIndexMode = gl::PrimitiveMode::InvalidEnum; 683*8975f5c5SAndroid Build Coastguard Worker 684*8975f5c5SAndroid Build Coastguard Worker mtl::BufferRef drawIdxBuffer; 685*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mProvokingVertexHelper.generateIndexBuffer( 686*8975f5c5SAndroid Build Coastguard Worker mtl::GetImpl(context), first, count, mode, convertedType, outIndexCount, outIndexOffset, 687*8975f5c5SAndroid Build Coastguard Worker outIndexMode, drawIdxBuffer)); 688*8975f5c5SAndroid Build Coastguard Worker GLsizei outIndexCounti32 = static_cast<GLsizei>(outIndexCount); 689*8975f5c5SAndroid Build Coastguard Worker 690*8975f5c5SAndroid Build Coastguard Worker // Note: we don't need to pass the generated index buffer to ContextMtl::setupDraw. 691*8975f5c5SAndroid Build Coastguard Worker // Because setupDraw only needs to operate on the original vertex buffers & PrimitiveMode. 692*8975f5c5SAndroid Build Coastguard Worker // setupDraw might convert vertex attributes if the offset & alignment are not natively 693*8975f5c5SAndroid Build Coastguard Worker // supported by Metal. However, the converted attributes have the same order as the original 694*8975f5c5SAndroid Build Coastguard Worker // vertices. Hence the conversion doesn't need to know about the newly generated index buffer. 695*8975f5c5SAndroid Build Coastguard Worker#define DRAW_PROVOKING_VERTEX_ARRAY(xfbPass) \ 696*8975f5c5SAndroid Build Coastguard Worker if (xfbPass) \ 697*8975f5c5SAndroid Build Coastguard Worker { \ 698*8975f5c5SAndroid Build Coastguard Worker bool isNoOp = false; \ 699*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setupDraw(context, mode, first, count, instances, \ 700*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType::InvalidEnum, nullptr, xfbPass, &isNoOp)); \ 701*8975f5c5SAndroid Build Coastguard Worker if (!isNoOp) \ 702*8975f5c5SAndroid Build Coastguard Worker { \ 703*8975f5c5SAndroid Build Coastguard Worker MTLPrimitiveType mtlType = mtl::GetPrimitiveType(mode); \ 704*8975f5c5SAndroid Build Coastguard Worker if (instances == 0) \ 705*8975f5c5SAndroid Build Coastguard Worker { \ 706*8975f5c5SAndroid Build Coastguard Worker /* This method is called from normal drawArrays() */ \ 707*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.draw(mtlType, first, count); \ 708*8975f5c5SAndroid Build Coastguard Worker } \ 709*8975f5c5SAndroid Build Coastguard Worker else \ 710*8975f5c5SAndroid Build Coastguard Worker { \ 711*8975f5c5SAndroid Build Coastguard Worker if (baseInstance == 0) \ 712*8975f5c5SAndroid Build Coastguard Worker { \ 713*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.drawInstanced(mtlType, first, count, instances); \ 714*8975f5c5SAndroid Build Coastguard Worker } \ 715*8975f5c5SAndroid Build Coastguard Worker else \ 716*8975f5c5SAndroid Build Coastguard Worker { \ 717*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.drawInstancedBaseInstance(mtlType, first, count, instances, \ 718*8975f5c5SAndroid Build Coastguard Worker baseInstance); \ 719*8975f5c5SAndroid Build Coastguard Worker } \ 720*8975f5c5SAndroid Build Coastguard Worker } \ 721*8975f5c5SAndroid Build Coastguard Worker } \ 722*8975f5c5SAndroid Build Coastguard Worker } \ 723*8975f5c5SAndroid Build Coastguard Worker else \ 724*8975f5c5SAndroid Build Coastguard Worker { \ 725*8975f5c5SAndroid Build Coastguard Worker bool isNoOp = false; \ 726*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setupDraw(context, mode, first, count, instances, \ 727*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType::InvalidEnum, nullptr, xfbPass, &isNoOp)); \ 728*8975f5c5SAndroid Build Coastguard Worker \ 729*8975f5c5SAndroid Build Coastguard Worker if (!isNoOp) \ 730*8975f5c5SAndroid Build Coastguard Worker { \ 731*8975f5c5SAndroid Build Coastguard Worker MTLPrimitiveType mtlType = mtl::GetPrimitiveType(outIndexMode); \ 732*8975f5c5SAndroid Build Coastguard Worker MTLIndexType mtlIdxType = mtl::GetIndexType(convertedType); \ 733*8975f5c5SAndroid Build Coastguard Worker if (instances == 0) \ 734*8975f5c5SAndroid Build Coastguard Worker { \ 735*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.drawIndexed(mtlType, outIndexCounti32, mtlIdxType, drawIdxBuffer, \ 736*8975f5c5SAndroid Build Coastguard Worker outIndexOffset); \ 737*8975f5c5SAndroid Build Coastguard Worker } \ 738*8975f5c5SAndroid Build Coastguard Worker else \ 739*8975f5c5SAndroid Build Coastguard Worker { \ 740*8975f5c5SAndroid Build Coastguard Worker if (baseInstance == 0) \ 741*8975f5c5SAndroid Build Coastguard Worker { \ 742*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.drawIndexedInstanced(mtlType, outIndexCounti32, mtlIdxType, \ 743*8975f5c5SAndroid Build Coastguard Worker drawIdxBuffer, outIndexOffset, instances); \ 744*8975f5c5SAndroid Build Coastguard Worker } \ 745*8975f5c5SAndroid Build Coastguard Worker else \ 746*8975f5c5SAndroid Build Coastguard Worker { \ 747*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.drawIndexedInstancedBaseVertexBaseInstance( \ 748*8975f5c5SAndroid Build Coastguard Worker mtlType, outIndexCounti32, mtlIdxType, drawIdxBuffer, outIndexOffset, \ 749*8975f5c5SAndroid Build Coastguard Worker instances, 0, baseInstance); \ 750*8975f5c5SAndroid Build Coastguard Worker } \ 751*8975f5c5SAndroid Build Coastguard Worker } \ 752*8975f5c5SAndroid Build Coastguard Worker } \ 753*8975f5c5SAndroid Build Coastguard Worker } 754*8975f5c5SAndroid Build Coastguard Worker 755*8975f5c5SAndroid Build Coastguard Worker ANGLE_MTL_XFB_DRAW(DRAW_PROVOKING_VERTEX_ARRAY) 756*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 757*8975f5c5SAndroid Build Coastguard Worker} 758*8975f5c5SAndroid Build Coastguard Worker 759*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawElementsImpl(const gl::Context *context, 760*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 761*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 762*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type, 763*8975f5c5SAndroid Build Coastguard Worker const void *indices, 764*8975f5c5SAndroid Build Coastguard Worker GLsizei instances, 765*8975f5c5SAndroid Build Coastguard Worker GLint baseVertex, 766*8975f5c5SAndroid Build Coastguard Worker GLuint baseInstance) 767*8975f5c5SAndroid Build Coastguard Worker{ 768*8975f5c5SAndroid Build Coastguard Worker // Real instances count. Zero means this is not instanced draw. 769*8975f5c5SAndroid Build Coastguard Worker GLsizei instanceCount = instances ? instances : 1; 770*8975f5c5SAndroid Build Coastguard Worker 771*8975f5c5SAndroid Build Coastguard Worker if (mCullAllPolygons && gl::IsPolygonMode(mode)) 772*8975f5c5SAndroid Build Coastguard Worker { 773*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 774*8975f5c5SAndroid Build Coastguard Worker } 775*8975f5c5SAndroid Build Coastguard Worker 776*8975f5c5SAndroid Build Coastguard Worker if (mode == gl::PrimitiveMode::TriangleFan) 777*8975f5c5SAndroid Build Coastguard Worker { 778*8975f5c5SAndroid Build Coastguard Worker return drawTriFanElements(context, count, type, indices, instanceCount, baseVertex, 779*8975f5c5SAndroid Build Coastguard Worker baseInstance); 780*8975f5c5SAndroid Build Coastguard Worker } 781*8975f5c5SAndroid Build Coastguard Worker else if (mode == gl::PrimitiveMode::LineLoop) 782*8975f5c5SAndroid Build Coastguard Worker { 783*8975f5c5SAndroid Build Coastguard Worker return drawLineLoopElements(context, count, type, indices, instanceCount, baseVertex, 784*8975f5c5SAndroid Build Coastguard Worker baseInstance); 785*8975f5c5SAndroid Build Coastguard Worker } 786*8975f5c5SAndroid Build Coastguard Worker 787*8975f5c5SAndroid Build Coastguard Worker mtl::BufferRef idxBuffer; 788*8975f5c5SAndroid Build Coastguard Worker mtl::BufferRef drawIdxBuffer; 789*8975f5c5SAndroid Build Coastguard Worker size_t convertedOffset = 0; 790*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType convertedType = type; 791*8975f5c5SAndroid Build Coastguard Worker 792*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mVertexArray->getIndexBuffer(context, type, count, indices, &idxBuffer, 793*8975f5c5SAndroid Build Coastguard Worker &convertedOffset, &convertedType)); 794*8975f5c5SAndroid Build Coastguard Worker 795*8975f5c5SAndroid Build Coastguard Worker ASSERT(idxBuffer); 796*8975f5c5SAndroid Build Coastguard Worker ASSERT((convertedType == gl::DrawElementsType::UnsignedShort && (convertedOffset % 2) == 0) || 797*8975f5c5SAndroid Build Coastguard Worker (convertedType == gl::DrawElementsType::UnsignedInt && (convertedOffset % 4) == 0)); 798*8975f5c5SAndroid Build Coastguard Worker 799*8975f5c5SAndroid Build Coastguard Worker uint32_t convertedCounti32 = (uint32_t)count; 800*8975f5c5SAndroid Build Coastguard Worker 801*8975f5c5SAndroid Build Coastguard Worker size_t provokingVertexAdditionalOffset = 0; 802*8975f5c5SAndroid Build Coastguard Worker 803*8975f5c5SAndroid Build Coastguard Worker if (requiresIndexRewrite(context->getState(), mode)) 804*8975f5c5SAndroid Build Coastguard Worker { 805*8975f5c5SAndroid Build Coastguard Worker size_t outIndexCount = 0; 806*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode newMode = gl::PrimitiveMode::InvalidEnum; 807*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mProvokingVertexHelper.preconditionIndexBuffer( 808*8975f5c5SAndroid Build Coastguard Worker mtl::GetImpl(context), idxBuffer, count, convertedOffset, 809*8975f5c5SAndroid Build Coastguard Worker mState.isPrimitiveRestartEnabled(), mode, convertedType, outIndexCount, 810*8975f5c5SAndroid Build Coastguard Worker provokingVertexAdditionalOffset, newMode, drawIdxBuffer)); 811*8975f5c5SAndroid Build Coastguard Worker // Line strips and triangle strips are rewritten to flat line arrays and tri arrays. 812*8975f5c5SAndroid Build Coastguard Worker convertedCounti32 = (uint32_t)outIndexCount; 813*8975f5c5SAndroid Build Coastguard Worker mode = newMode; 814*8975f5c5SAndroid Build Coastguard Worker } 815*8975f5c5SAndroid Build Coastguard Worker else 816*8975f5c5SAndroid Build Coastguard Worker { 817*8975f5c5SAndroid Build Coastguard Worker drawIdxBuffer = idxBuffer; 818*8975f5c5SAndroid Build Coastguard Worker } 819*8975f5c5SAndroid Build Coastguard Worker // Draw commands will only be broken up if transform feedback is enabled, 820*8975f5c5SAndroid Build Coastguard Worker // if the mode is a simple type, and if the buffer contained any restart 821*8975f5c5SAndroid Build Coastguard Worker // indices. 822*8975f5c5SAndroid Build Coastguard Worker // It's safe to use idxBuffer in this case, as it will contain the same count and restart ranges 823*8975f5c5SAndroid Build Coastguard Worker // as drawIdxBuffer. 824*8975f5c5SAndroid Build Coastguard Worker const std::vector<DrawCommandRange> drawCommands = mVertexArray->getDrawIndices( 825*8975f5c5SAndroid Build Coastguard Worker context, type, convertedType, mode, idxBuffer, convertedCounti32, convertedOffset); 826*8975f5c5SAndroid Build Coastguard Worker bool isNoOp = false; 827*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setupDraw(context, mode, 0, count, instances, type, indices, false, &isNoOp)); 828*8975f5c5SAndroid Build Coastguard Worker if (!isNoOp) 829*8975f5c5SAndroid Build Coastguard Worker { 830*8975f5c5SAndroid Build Coastguard Worker MTLPrimitiveType mtlType = mtl::GetPrimitiveType(mode); 831*8975f5c5SAndroid Build Coastguard Worker 832*8975f5c5SAndroid Build Coastguard Worker MTLIndexType mtlIdxType = mtl::GetIndexType(convertedType); 833*8975f5c5SAndroid Build Coastguard Worker 834*8975f5c5SAndroid Build Coastguard Worker if (instances == 0 && baseVertex == 0 && baseInstance == 0) 835*8975f5c5SAndroid Build Coastguard Worker { 836*8975f5c5SAndroid Build Coastguard Worker // Normal draw 837*8975f5c5SAndroid Build Coastguard Worker for (auto &command : drawCommands) 838*8975f5c5SAndroid Build Coastguard Worker { 839*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.drawIndexed(mtlType, command.count, mtlIdxType, drawIdxBuffer, 840*8975f5c5SAndroid Build Coastguard Worker command.offset + provokingVertexAdditionalOffset); 841*8975f5c5SAndroid Build Coastguard Worker } 842*8975f5c5SAndroid Build Coastguard Worker } 843*8975f5c5SAndroid Build Coastguard Worker else 844*8975f5c5SAndroid Build Coastguard Worker { 845*8975f5c5SAndroid Build Coastguard Worker // Instanced draw 846*8975f5c5SAndroid Build Coastguard Worker if (baseVertex == 0 && baseInstance == 0) 847*8975f5c5SAndroid Build Coastguard Worker { 848*8975f5c5SAndroid Build Coastguard Worker for (auto &command : drawCommands) 849*8975f5c5SAndroid Build Coastguard Worker { 850*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.drawIndexedInstanced( 851*8975f5c5SAndroid Build Coastguard Worker mtlType, command.count, mtlIdxType, drawIdxBuffer, 852*8975f5c5SAndroid Build Coastguard Worker command.offset + provokingVertexAdditionalOffset, instanceCount); 853*8975f5c5SAndroid Build Coastguard Worker } 854*8975f5c5SAndroid Build Coastguard Worker } 855*8975f5c5SAndroid Build Coastguard Worker else 856*8975f5c5SAndroid Build Coastguard Worker { 857*8975f5c5SAndroid Build Coastguard Worker for (auto &command : drawCommands) 858*8975f5c5SAndroid Build Coastguard Worker { 859*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.drawIndexedInstancedBaseVertexBaseInstance( 860*8975f5c5SAndroid Build Coastguard Worker mtlType, command.count, mtlIdxType, drawIdxBuffer, 861*8975f5c5SAndroid Build Coastguard Worker command.offset + provokingVertexAdditionalOffset, instanceCount, baseVertex, 862*8975f5c5SAndroid Build Coastguard Worker baseInstance); 863*8975f5c5SAndroid Build Coastguard Worker } 864*8975f5c5SAndroid Build Coastguard Worker } 865*8975f5c5SAndroid Build Coastguard Worker } 866*8975f5c5SAndroid Build Coastguard Worker } 867*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 868*8975f5c5SAndroid Build Coastguard Worker} 869*8975f5c5SAndroid Build Coastguard Worker 870*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawElements(const gl::Context *context, 871*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 872*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 873*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type, 874*8975f5c5SAndroid Build Coastguard Worker const void *indices) 875*8975f5c5SAndroid Build Coastguard Worker{ 876*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(resyncDrawFramebufferIfNeeded(context)); 877*8975f5c5SAndroid Build Coastguard Worker return drawElementsImpl(context, mode, count, type, indices, 0, 0, 0); 878*8975f5c5SAndroid Build Coastguard Worker} 879*8975f5c5SAndroid Build Coastguard Worker 880*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawElementsBaseVertex(const gl::Context *context, 881*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 882*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 883*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type, 884*8975f5c5SAndroid Build Coastguard Worker const void *indices, 885*8975f5c5SAndroid Build Coastguard Worker GLint baseVertex) 886*8975f5c5SAndroid Build Coastguard Worker{ 887*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED(); 888*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Stop; 889*8975f5c5SAndroid Build Coastguard Worker} 890*8975f5c5SAndroid Build Coastguard Worker 891*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawElementsInstanced(const gl::Context *context, 892*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 893*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 894*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type, 895*8975f5c5SAndroid Build Coastguard Worker const void *indices, 896*8975f5c5SAndroid Build Coastguard Worker GLsizei instanceCount) 897*8975f5c5SAndroid Build Coastguard Worker{ 898*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(resyncDrawFramebufferIfNeeded(context)); 899*8975f5c5SAndroid Build Coastguard Worker // Instanced draw calls with zero instances are skipped in the frontend. 900*8975f5c5SAndroid Build Coastguard Worker // The drawElementsImpl function would treat them as non-instanced. 901*8975f5c5SAndroid Build Coastguard Worker ASSERT(instanceCount > 0); 902*8975f5c5SAndroid Build Coastguard Worker return drawElementsImpl(context, mode, count, type, indices, instanceCount, 0, 0); 903*8975f5c5SAndroid Build Coastguard Worker} 904*8975f5c5SAndroid Build Coastguard Worker 905*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawElementsInstancedBaseVertex(const gl::Context *context, 906*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 907*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 908*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type, 909*8975f5c5SAndroid Build Coastguard Worker const void *indices, 910*8975f5c5SAndroid Build Coastguard Worker GLsizei instanceCount, 911*8975f5c5SAndroid Build Coastguard Worker GLint baseVertex) 912*8975f5c5SAndroid Build Coastguard Worker{ 913*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(resyncDrawFramebufferIfNeeded(context)); 914*8975f5c5SAndroid Build Coastguard Worker // Instanced draw calls with zero instances are skipped in the frontend. 915*8975f5c5SAndroid Build Coastguard Worker // The drawElementsImpl function would treat them as non-instanced. 916*8975f5c5SAndroid Build Coastguard Worker ASSERT(instanceCount > 0); 917*8975f5c5SAndroid Build Coastguard Worker return drawElementsImpl(context, mode, count, type, indices, instanceCount, baseVertex, 0); 918*8975f5c5SAndroid Build Coastguard Worker} 919*8975f5c5SAndroid Build Coastguard Worker 920*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context, 921*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 922*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 923*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type, 924*8975f5c5SAndroid Build Coastguard Worker const void *indices, 925*8975f5c5SAndroid Build Coastguard Worker GLsizei instances, 926*8975f5c5SAndroid Build Coastguard Worker GLint baseVertex, 927*8975f5c5SAndroid Build Coastguard Worker GLuint baseInstance) 928*8975f5c5SAndroid Build Coastguard Worker{ 929*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(resyncDrawFramebufferIfNeeded(context)); 930*8975f5c5SAndroid Build Coastguard Worker // Instanced draw calls with zero instances are skipped in the frontend. 931*8975f5c5SAndroid Build Coastguard Worker // The drawElementsImpl function would treat them as non-instanced. 932*8975f5c5SAndroid Build Coastguard Worker ASSERT(instances > 0); 933*8975f5c5SAndroid Build Coastguard Worker return drawElementsImpl(context, mode, count, type, indices, instances, baseVertex, 934*8975f5c5SAndroid Build Coastguard Worker baseInstance); 935*8975f5c5SAndroid Build Coastguard Worker} 936*8975f5c5SAndroid Build Coastguard Worker 937*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawRangeElements(const gl::Context *context, 938*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 939*8975f5c5SAndroid Build Coastguard Worker GLuint start, 940*8975f5c5SAndroid Build Coastguard Worker GLuint end, 941*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 942*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type, 943*8975f5c5SAndroid Build Coastguard Worker const void *indices) 944*8975f5c5SAndroid Build Coastguard Worker{ 945*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(resyncDrawFramebufferIfNeeded(context)); 946*8975f5c5SAndroid Build Coastguard Worker return drawElementsImpl(context, mode, count, type, indices, 0, 0, 0); 947*8975f5c5SAndroid Build Coastguard Worker} 948*8975f5c5SAndroid Build Coastguard Worker 949*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawRangeElementsBaseVertex(const gl::Context *context, 950*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 951*8975f5c5SAndroid Build Coastguard Worker GLuint start, 952*8975f5c5SAndroid Build Coastguard Worker GLuint end, 953*8975f5c5SAndroid Build Coastguard Worker GLsizei count, 954*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type, 955*8975f5c5SAndroid Build Coastguard Worker const void *indices, 956*8975f5c5SAndroid Build Coastguard Worker GLint baseVertex) 957*8975f5c5SAndroid Build Coastguard Worker{ 958*8975f5c5SAndroid Build Coastguard Worker // NOTE(hqle): ES 3.2 959*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED(); 960*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Stop; 961*8975f5c5SAndroid Build Coastguard Worker} 962*8975f5c5SAndroid Build Coastguard Worker 963*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawArraysIndirect(const gl::Context *context, 964*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 965*8975f5c5SAndroid Build Coastguard Worker const void *indirect) 966*8975f5c5SAndroid Build Coastguard Worker{ 967*8975f5c5SAndroid Build Coastguard Worker // NOTE(hqle): ES 3.0 968*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED(); 969*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Stop; 970*8975f5c5SAndroid Build Coastguard Worker} 971*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::drawElementsIndirect(const gl::Context *context, 972*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 973*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type, 974*8975f5c5SAndroid Build Coastguard Worker const void *indirect) 975*8975f5c5SAndroid Build Coastguard Worker{ 976*8975f5c5SAndroid Build Coastguard Worker // NOTE(hqle): ES 3.0 977*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED(); 978*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Stop; 979*8975f5c5SAndroid Build Coastguard Worker} 980*8975f5c5SAndroid Build Coastguard Worker 981*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::multiDrawArrays(const gl::Context *context, 982*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 983*8975f5c5SAndroid Build Coastguard Worker const GLint *firsts, 984*8975f5c5SAndroid Build Coastguard Worker const GLsizei *counts, 985*8975f5c5SAndroid Build Coastguard Worker GLsizei drawcount) 986*8975f5c5SAndroid Build Coastguard Worker{ 987*8975f5c5SAndroid Build Coastguard Worker return rx::MultiDrawArraysGeneral(this, context, mode, firsts, counts, drawcount); 988*8975f5c5SAndroid Build Coastguard Worker} 989*8975f5c5SAndroid Build Coastguard Worker 990*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::multiDrawArraysInstanced(const gl::Context *context, 991*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 992*8975f5c5SAndroid Build Coastguard Worker const GLint *firsts, 993*8975f5c5SAndroid Build Coastguard Worker const GLsizei *counts, 994*8975f5c5SAndroid Build Coastguard Worker const GLsizei *instanceCounts, 995*8975f5c5SAndroid Build Coastguard Worker GLsizei drawcount) 996*8975f5c5SAndroid Build Coastguard Worker{ 997*8975f5c5SAndroid Build Coastguard Worker return rx::MultiDrawArraysInstancedGeneral(this, context, mode, firsts, counts, instanceCounts, 998*8975f5c5SAndroid Build Coastguard Worker drawcount); 999*8975f5c5SAndroid Build Coastguard Worker} 1000*8975f5c5SAndroid Build Coastguard Worker 1001*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::multiDrawArraysIndirect(const gl::Context *context, 1002*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 1003*8975f5c5SAndroid Build Coastguard Worker const void *indirect, 1004*8975f5c5SAndroid Build Coastguard Worker GLsizei drawcount, 1005*8975f5c5SAndroid Build Coastguard Worker GLsizei stride) 1006*8975f5c5SAndroid Build Coastguard Worker{ 1007*8975f5c5SAndroid Build Coastguard Worker return rx::MultiDrawArraysIndirectGeneral(this, context, mode, indirect, drawcount, stride); 1008*8975f5c5SAndroid Build Coastguard Worker} 1009*8975f5c5SAndroid Build Coastguard Worker 1010*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::multiDrawElements(const gl::Context *context, 1011*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 1012*8975f5c5SAndroid Build Coastguard Worker const GLsizei *counts, 1013*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type, 1014*8975f5c5SAndroid Build Coastguard Worker const GLvoid *const *indices, 1015*8975f5c5SAndroid Build Coastguard Worker GLsizei drawcount) 1016*8975f5c5SAndroid Build Coastguard Worker{ 1017*8975f5c5SAndroid Build Coastguard Worker return rx::MultiDrawElementsGeneral(this, context, mode, counts, type, indices, drawcount); 1018*8975f5c5SAndroid Build Coastguard Worker} 1019*8975f5c5SAndroid Build Coastguard Worker 1020*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::multiDrawElementsInstanced(const gl::Context *context, 1021*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 1022*8975f5c5SAndroid Build Coastguard Worker const GLsizei *counts, 1023*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type, 1024*8975f5c5SAndroid Build Coastguard Worker const GLvoid *const *indices, 1025*8975f5c5SAndroid Build Coastguard Worker const GLsizei *instanceCounts, 1026*8975f5c5SAndroid Build Coastguard Worker GLsizei drawcount) 1027*8975f5c5SAndroid Build Coastguard Worker{ 1028*8975f5c5SAndroid Build Coastguard Worker return rx::MultiDrawElementsInstancedGeneral(this, context, mode, counts, type, indices, 1029*8975f5c5SAndroid Build Coastguard Worker instanceCounts, drawcount); 1030*8975f5c5SAndroid Build Coastguard Worker} 1031*8975f5c5SAndroid Build Coastguard Worker 1032*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::multiDrawElementsIndirect(const gl::Context *context, 1033*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 1034*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type, 1035*8975f5c5SAndroid Build Coastguard Worker const void *indirect, 1036*8975f5c5SAndroid Build Coastguard Worker GLsizei drawcount, 1037*8975f5c5SAndroid Build Coastguard Worker GLsizei stride) 1038*8975f5c5SAndroid Build Coastguard Worker{ 1039*8975f5c5SAndroid Build Coastguard Worker return rx::MultiDrawElementsIndirectGeneral(this, context, mode, type, indirect, drawcount, 1040*8975f5c5SAndroid Build Coastguard Worker stride); 1041*8975f5c5SAndroid Build Coastguard Worker} 1042*8975f5c5SAndroid Build Coastguard Worker 1043*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::multiDrawArraysInstancedBaseInstance(const gl::Context *context, 1044*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 1045*8975f5c5SAndroid Build Coastguard Worker const GLint *firsts, 1046*8975f5c5SAndroid Build Coastguard Worker const GLsizei *counts, 1047*8975f5c5SAndroid Build Coastguard Worker const GLsizei *instanceCounts, 1048*8975f5c5SAndroid Build Coastguard Worker const GLuint *baseInstances, 1049*8975f5c5SAndroid Build Coastguard Worker GLsizei drawcount) 1050*8975f5c5SAndroid Build Coastguard Worker{ 1051*8975f5c5SAndroid Build Coastguard Worker return rx::MultiDrawArraysInstancedBaseInstanceGeneral( 1052*8975f5c5SAndroid Build Coastguard Worker this, context, mode, firsts, counts, instanceCounts, baseInstances, drawcount); 1053*8975f5c5SAndroid Build Coastguard Worker} 1054*8975f5c5SAndroid Build Coastguard Worker 1055*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::multiDrawElementsInstancedBaseVertexBaseInstance( 1056*8975f5c5SAndroid Build Coastguard Worker const gl::Context *context, 1057*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 1058*8975f5c5SAndroid Build Coastguard Worker const GLsizei *counts, 1059*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type, 1060*8975f5c5SAndroid Build Coastguard Worker const GLvoid *const *indices, 1061*8975f5c5SAndroid Build Coastguard Worker const GLsizei *instanceCounts, 1062*8975f5c5SAndroid Build Coastguard Worker const GLint *baseVertices, 1063*8975f5c5SAndroid Build Coastguard Worker const GLuint *baseInstances, 1064*8975f5c5SAndroid Build Coastguard Worker GLsizei drawcount) 1065*8975f5c5SAndroid Build Coastguard Worker{ 1066*8975f5c5SAndroid Build Coastguard Worker return rx::MultiDrawElementsInstancedBaseVertexBaseInstanceGeneral( 1067*8975f5c5SAndroid Build Coastguard Worker this, context, mode, counts, type, indices, instanceCounts, baseVertices, baseInstances, 1068*8975f5c5SAndroid Build Coastguard Worker drawcount); 1069*8975f5c5SAndroid Build Coastguard Worker} 1070*8975f5c5SAndroid Build Coastguard Worker 1071*8975f5c5SAndroid Build Coastguard Worker// Device loss 1072*8975f5c5SAndroid Build Coastguard Workergl::GraphicsResetStatus ContextMtl::getResetStatus() 1073*8975f5c5SAndroid Build Coastguard Worker{ 1074*8975f5c5SAndroid Build Coastguard Worker return gl::GraphicsResetStatus::NoError; 1075*8975f5c5SAndroid Build Coastguard Worker} 1076*8975f5c5SAndroid Build Coastguard Worker 1077*8975f5c5SAndroid Build Coastguard Worker// EXT_debug_marker 1078*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::insertEventMarker(GLsizei length, const char *marker) 1079*8975f5c5SAndroid Build Coastguard Worker{ 1080*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1081*8975f5c5SAndroid Build Coastguard Worker} 1082*8975f5c5SAndroid Build Coastguard Worker 1083*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::pushGroupMarker(GLsizei length, const char *marker) 1084*8975f5c5SAndroid Build Coastguard Worker{ 1085*8975f5c5SAndroid Build Coastguard Worker mCmdBuffer.pushDebugGroup(ConvertMarkerToString(length, marker)); 1086*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1087*8975f5c5SAndroid Build Coastguard Worker} 1088*8975f5c5SAndroid Build Coastguard Worker 1089*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::popGroupMarker() 1090*8975f5c5SAndroid Build Coastguard Worker{ 1091*8975f5c5SAndroid Build Coastguard Worker mCmdBuffer.popDebugGroup(); 1092*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1093*8975f5c5SAndroid Build Coastguard Worker} 1094*8975f5c5SAndroid Build Coastguard Worker 1095*8975f5c5SAndroid Build Coastguard Worker// KHR_debug 1096*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::pushDebugGroup(const gl::Context *context, 1097*8975f5c5SAndroid Build Coastguard Worker GLenum source, 1098*8975f5c5SAndroid Build Coastguard Worker GLuint id, 1099*8975f5c5SAndroid Build Coastguard Worker const std::string &message) 1100*8975f5c5SAndroid Build Coastguard Worker{ 1101*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1102*8975f5c5SAndroid Build Coastguard Worker} 1103*8975f5c5SAndroid Build Coastguard Worker 1104*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::popDebugGroup(const gl::Context *context) 1105*8975f5c5SAndroid Build Coastguard Worker{ 1106*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1107*8975f5c5SAndroid Build Coastguard Worker} 1108*8975f5c5SAndroid Build Coastguard Worker 1109*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::updateIncompatibleAttachments(const gl::State &glState) 1110*8975f5c5SAndroid Build Coastguard Worker{ 1111*8975f5c5SAndroid Build Coastguard Worker const gl::ProgramExecutable *programExecutable = glState.getProgramExecutable(); 1112*8975f5c5SAndroid Build Coastguard Worker gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer(); 1113*8975f5c5SAndroid Build Coastguard Worker if (programExecutable == nullptr || drawFramebuffer == nullptr) 1114*8975f5c5SAndroid Build Coastguard Worker { 1115*8975f5c5SAndroid Build Coastguard Worker mIncompatibleAttachments.reset(); 1116*8975f5c5SAndroid Build Coastguard Worker return; 1117*8975f5c5SAndroid Build Coastguard Worker } 1118*8975f5c5SAndroid Build Coastguard Worker 1119*8975f5c5SAndroid Build Coastguard Worker // Cache a mask of incompatible attachments ignoring unused outputs and disabled draw buffers. 1120*8975f5c5SAndroid Build Coastguard Worker mIncompatibleAttachments = 1121*8975f5c5SAndroid Build Coastguard Worker gl::GetComponentTypeMaskDiff(drawFramebuffer->getDrawBufferTypeMask(), 1122*8975f5c5SAndroid Build Coastguard Worker programExecutable->getFragmentOutputsTypeMask()) & 1123*8975f5c5SAndroid Build Coastguard Worker drawFramebuffer->getDrawBufferMask() & programExecutable->getActiveOutputVariablesMask(); 1124*8975f5c5SAndroid Build Coastguard Worker} 1125*8975f5c5SAndroid Build Coastguard Worker 1126*8975f5c5SAndroid Build Coastguard Worker// State sync with dirty bits. 1127*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::syncState(const gl::Context *context, 1128*8975f5c5SAndroid Build Coastguard Worker const gl::state::DirtyBits dirtyBits, 1129*8975f5c5SAndroid Build Coastguard Worker const gl::state::DirtyBits bitMask, 1130*8975f5c5SAndroid Build Coastguard Worker const gl::state::ExtendedDirtyBits extendedDirtyBits, 1131*8975f5c5SAndroid Build Coastguard Worker const gl::state::ExtendedDirtyBits extendedBitMask, 1132*8975f5c5SAndroid Build Coastguard Worker gl::Command command) 1133*8975f5c5SAndroid Build Coastguard Worker{ 1134*8975f5c5SAndroid Build Coastguard Worker const gl::State &glState = context->getState(); 1135*8975f5c5SAndroid Build Coastguard Worker 1136*8975f5c5SAndroid Build Coastguard Worker // Metal's blend state is set at once, while ANGLE tracks separate dirty 1137*8975f5c5SAndroid Build Coastguard Worker // bits: ENABLED, FUNCS, and EQUATIONS. Merge all three of them to the first one. 1138*8975f5c5SAndroid Build Coastguard Worker // PS: these can not be statically initialized on some architectures as there is 1139*8975f5c5SAndroid Build Coastguard Worker // no constuctor for DirtyBits that takes an int (which becomes BitSetArray<64>). 1140*8975f5c5SAndroid Build Coastguard Worker gl::state::DirtyBits checkBlendBitsMask; 1141*8975f5c5SAndroid Build Coastguard Worker checkBlendBitsMask.set(gl::state::DIRTY_BIT_BLEND_ENABLED); 1142*8975f5c5SAndroid Build Coastguard Worker checkBlendBitsMask.set(gl::state::DIRTY_BIT_BLEND_FUNCS); 1143*8975f5c5SAndroid Build Coastguard Worker checkBlendBitsMask.set(gl::state::DIRTY_BIT_BLEND_EQUATIONS); 1144*8975f5c5SAndroid Build Coastguard Worker gl::state::DirtyBits resetBlendBitsMask; 1145*8975f5c5SAndroid Build Coastguard Worker resetBlendBitsMask.set(gl::state::DIRTY_BIT_BLEND_FUNCS); 1146*8975f5c5SAndroid Build Coastguard Worker resetBlendBitsMask.set(gl::state::DIRTY_BIT_BLEND_EQUATIONS); 1147*8975f5c5SAndroid Build Coastguard Worker 1148*8975f5c5SAndroid Build Coastguard Worker gl::state::DirtyBits mergedDirtyBits = gl::state::DirtyBits(dirtyBits) & ~resetBlendBitsMask; 1149*8975f5c5SAndroid Build Coastguard Worker mergedDirtyBits.set(gl::state::DIRTY_BIT_BLEND_ENABLED, (dirtyBits & checkBlendBitsMask).any()); 1150*8975f5c5SAndroid Build Coastguard Worker 1151*8975f5c5SAndroid Build Coastguard Worker for (auto iter = mergedDirtyBits.begin(), endIter = mergedDirtyBits.end(); iter != endIter; 1152*8975f5c5SAndroid Build Coastguard Worker ++iter) 1153*8975f5c5SAndroid Build Coastguard Worker { 1154*8975f5c5SAndroid Build Coastguard Worker size_t dirtyBit = *iter; 1155*8975f5c5SAndroid Build Coastguard Worker switch (dirtyBit) 1156*8975f5c5SAndroid Build Coastguard Worker { 1157*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_SCISSOR_TEST_ENABLED: 1158*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_SCISSOR: 1159*8975f5c5SAndroid Build Coastguard Worker updateScissor(glState); 1160*8975f5c5SAndroid Build Coastguard Worker break; 1161*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_VIEWPORT: 1162*8975f5c5SAndroid Build Coastguard Worker { 1163*8975f5c5SAndroid Build Coastguard Worker FramebufferMtl *framebufferMtl = mtl::GetImpl(glState.getDrawFramebuffer()); 1164*8975f5c5SAndroid Build Coastguard Worker updateViewport(framebufferMtl, glState.getViewport(), glState.getNearPlane(), 1165*8975f5c5SAndroid Build Coastguard Worker glState.getFarPlane()); 1166*8975f5c5SAndroid Build Coastguard Worker // Update the scissor, which will be constrained to the viewport 1167*8975f5c5SAndroid Build Coastguard Worker updateScissor(glState); 1168*8975f5c5SAndroid Build Coastguard Worker break; 1169*8975f5c5SAndroid Build Coastguard Worker } 1170*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_DEPTH_RANGE: 1171*8975f5c5SAndroid Build Coastguard Worker updateDepthRange(glState.getNearPlane(), glState.getFarPlane()); 1172*8975f5c5SAndroid Build Coastguard Worker break; 1173*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_BLEND_COLOR: 1174*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_BLEND_COLOR); 1175*8975f5c5SAndroid Build Coastguard Worker break; 1176*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_BLEND_ENABLED: 1177*8975f5c5SAndroid Build Coastguard Worker updateBlendDescArray(glState.getBlendStateExt()); 1178*8975f5c5SAndroid Build Coastguard Worker break; 1179*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_COLOR_MASK: 1180*8975f5c5SAndroid Build Coastguard Worker { 1181*8975f5c5SAndroid Build Coastguard Worker const gl::BlendStateExt &blendStateExt = glState.getBlendStateExt(); 1182*8975f5c5SAndroid Build Coastguard Worker size_t i = 0; 1183*8975f5c5SAndroid Build Coastguard Worker for (; i < blendStateExt.getDrawBufferCount(); i++) 1184*8975f5c5SAndroid Build Coastguard Worker { 1185*8975f5c5SAndroid Build Coastguard Worker mBlendDescArray[i].updateWriteMask(blendStateExt.getColorMaskIndexed(i)); 1186*8975f5c5SAndroid Build Coastguard Worker mWriteMaskArray[i] = mBlendDescArray[i].writeMask; 1187*8975f5c5SAndroid Build Coastguard Worker } 1188*8975f5c5SAndroid Build Coastguard Worker for (; i < mBlendDescArray.size(); i++) 1189*8975f5c5SAndroid Build Coastguard Worker { 1190*8975f5c5SAndroid Build Coastguard Worker mBlendDescArray[i].updateWriteMask(0); 1191*8975f5c5SAndroid Build Coastguard Worker mWriteMaskArray[i] = mBlendDescArray[i].writeMask; 1192*8975f5c5SAndroid Build Coastguard Worker } 1193*8975f5c5SAndroid Build Coastguard Worker invalidateRenderPipeline(); 1194*8975f5c5SAndroid Build Coastguard Worker break; 1195*8975f5c5SAndroid Build Coastguard Worker } 1196*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: 1197*8975f5c5SAndroid Build Coastguard Worker if (getDisplay()->getFeatures().emulateAlphaToCoverage.enabled) 1198*8975f5c5SAndroid Build Coastguard Worker { 1199*8975f5c5SAndroid Build Coastguard Worker invalidateDriverUniforms(); 1200*8975f5c5SAndroid Build Coastguard Worker } 1201*8975f5c5SAndroid Build Coastguard Worker else 1202*8975f5c5SAndroid Build Coastguard Worker { 1203*8975f5c5SAndroid Build Coastguard Worker invalidateRenderPipeline(); 1204*8975f5c5SAndroid Build Coastguard Worker } 1205*8975f5c5SAndroid Build Coastguard Worker break; 1206*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED: 1207*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_SAMPLE_COVERAGE: 1208*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_SAMPLE_MASK_ENABLED: 1209*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_SAMPLE_MASK: 1210*8975f5c5SAndroid Build Coastguard Worker invalidateDriverUniforms(); 1211*8975f5c5SAndroid Build Coastguard Worker break; 1212*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_DEPTH_TEST_ENABLED: 1213*8975f5c5SAndroid Build Coastguard Worker mDepthStencilDesc.updateDepthTestEnabled(glState.getDepthStencilState()); 1214*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_DESC); 1215*8975f5c5SAndroid Build Coastguard Worker break; 1216*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_DEPTH_FUNC: 1217*8975f5c5SAndroid Build Coastguard Worker mDepthStencilDesc.updateDepthCompareFunc(glState.getDepthStencilState()); 1218*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_DESC); 1219*8975f5c5SAndroid Build Coastguard Worker break; 1220*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_DEPTH_MASK: 1221*8975f5c5SAndroid Build Coastguard Worker mDepthStencilDesc.updateDepthWriteEnabled(glState.getDepthStencilState()); 1222*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_DESC); 1223*8975f5c5SAndroid Build Coastguard Worker break; 1224*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_STENCIL_TEST_ENABLED: 1225*8975f5c5SAndroid Build Coastguard Worker mDepthStencilDesc.updateStencilTestEnabled(glState.getDepthStencilState()); 1226*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_DESC); 1227*8975f5c5SAndroid Build Coastguard Worker break; 1228*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_STENCIL_FUNCS_FRONT: 1229*8975f5c5SAndroid Build Coastguard Worker mDepthStencilDesc.updateStencilFrontFuncs(glState.getDepthStencilState()); 1230*8975f5c5SAndroid Build Coastguard Worker mStencilRefFront = glState.getStencilRef(); // clamped on the frontend 1231*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_DESC); 1232*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_STENCIL_REF); 1233*8975f5c5SAndroid Build Coastguard Worker break; 1234*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_STENCIL_FUNCS_BACK: 1235*8975f5c5SAndroid Build Coastguard Worker mDepthStencilDesc.updateStencilBackFuncs(glState.getDepthStencilState()); 1236*8975f5c5SAndroid Build Coastguard Worker mStencilRefBack = glState.getStencilBackRef(); // clamped on the frontend 1237*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_DESC); 1238*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_STENCIL_REF); 1239*8975f5c5SAndroid Build Coastguard Worker break; 1240*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_STENCIL_OPS_FRONT: 1241*8975f5c5SAndroid Build Coastguard Worker mDepthStencilDesc.updateStencilFrontOps(glState.getDepthStencilState()); 1242*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_DESC); 1243*8975f5c5SAndroid Build Coastguard Worker break; 1244*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_STENCIL_OPS_BACK: 1245*8975f5c5SAndroid Build Coastguard Worker mDepthStencilDesc.updateStencilBackOps(glState.getDepthStencilState()); 1246*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_DESC); 1247*8975f5c5SAndroid Build Coastguard Worker break; 1248*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_STENCIL_WRITEMASK_FRONT: 1249*8975f5c5SAndroid Build Coastguard Worker mDepthStencilDesc.updateStencilFrontWriteMask(glState.getDepthStencilState()); 1250*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_DESC); 1251*8975f5c5SAndroid Build Coastguard Worker break; 1252*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_STENCIL_WRITEMASK_BACK: 1253*8975f5c5SAndroid Build Coastguard Worker mDepthStencilDesc.updateStencilBackWriteMask(glState.getDepthStencilState()); 1254*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_DESC); 1255*8975f5c5SAndroid Build Coastguard Worker break; 1256*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_CULL_FACE_ENABLED: 1257*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_CULL_FACE: 1258*8975f5c5SAndroid Build Coastguard Worker updateCullMode(glState); 1259*8975f5c5SAndroid Build Coastguard Worker break; 1260*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_FRONT_FACE: 1261*8975f5c5SAndroid Build Coastguard Worker updateFrontFace(glState); 1262*8975f5c5SAndroid Build Coastguard Worker break; 1263*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED: 1264*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_POLYGON_OFFSET: 1265*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS); 1266*8975f5c5SAndroid Build Coastguard Worker break; 1267*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED: 1268*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_RASTERIZER_DISCARD); 1269*8975f5c5SAndroid Build Coastguard Worker break; 1270*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_LINE_WIDTH: 1271*8975f5c5SAndroid Build Coastguard Worker // Do nothing 1272*8975f5c5SAndroid Build Coastguard Worker break; 1273*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED: 1274*8975f5c5SAndroid Build Coastguard Worker // NOTE(hqle): ES 3.0 feature. 1275*8975f5c5SAndroid Build Coastguard Worker break; 1276*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_CLEAR_COLOR: 1277*8975f5c5SAndroid Build Coastguard Worker mClearColor = mtl::ClearColorValue( 1278*8975f5c5SAndroid Build Coastguard Worker glState.getColorClearValue().red, glState.getColorClearValue().green, 1279*8975f5c5SAndroid Build Coastguard Worker glState.getColorClearValue().blue, glState.getColorClearValue().alpha); 1280*8975f5c5SAndroid Build Coastguard Worker break; 1281*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_CLEAR_DEPTH: 1282*8975f5c5SAndroid Build Coastguard Worker break; 1283*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_CLEAR_STENCIL: 1284*8975f5c5SAndroid Build Coastguard Worker mClearStencil = glState.getStencilClearValue() & mtl::kStencilMaskAll; 1285*8975f5c5SAndroid Build Coastguard Worker break; 1286*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_UNPACK_STATE: 1287*8975f5c5SAndroid Build Coastguard Worker // This is a no-op, its only important to use the right unpack state when we do 1288*8975f5c5SAndroid Build Coastguard Worker // setImage or setSubImage in TextureMtl, which is plumbed through the frontend call 1289*8975f5c5SAndroid Build Coastguard Worker break; 1290*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_UNPACK_BUFFER_BINDING: 1291*8975f5c5SAndroid Build Coastguard Worker break; 1292*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_PACK_STATE: 1293*8975f5c5SAndroid Build Coastguard Worker // This is a no-op, its only important to use the right pack state when we do 1294*8975f5c5SAndroid Build Coastguard Worker // call readPixels later on. 1295*8975f5c5SAndroid Build Coastguard Worker break; 1296*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_PACK_BUFFER_BINDING: 1297*8975f5c5SAndroid Build Coastguard Worker break; 1298*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_DITHER_ENABLED: 1299*8975f5c5SAndroid Build Coastguard Worker break; 1300*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING: 1301*8975f5c5SAndroid Build Coastguard Worker break; 1302*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING: 1303*8975f5c5SAndroid Build Coastguard Worker updateIncompatibleAttachments(glState); 1304*8975f5c5SAndroid Build Coastguard Worker updateDrawFrameBufferBinding(context); 1305*8975f5c5SAndroid Build Coastguard Worker break; 1306*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_RENDERBUFFER_BINDING: 1307*8975f5c5SAndroid Build Coastguard Worker break; 1308*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_VERTEX_ARRAY_BINDING: 1309*8975f5c5SAndroid Build Coastguard Worker updateVertexArray(context); 1310*8975f5c5SAndroid Build Coastguard Worker break; 1311*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING: 1312*8975f5c5SAndroid Build Coastguard Worker break; 1313*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING: 1314*8975f5c5SAndroid Build Coastguard Worker break; 1315*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_PROGRAM_BINDING: 1316*8975f5c5SAndroid Build Coastguard Worker static_assert( 1317*8975f5c5SAndroid Build Coastguard Worker gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE > gl::state::DIRTY_BIT_PROGRAM_BINDING, 1318*8975f5c5SAndroid Build Coastguard Worker "Dirty bit order"); 1319*8975f5c5SAndroid Build Coastguard Worker iter.setLaterBit(gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE); 1320*8975f5c5SAndroid Build Coastguard Worker break; 1321*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE: 1322*8975f5c5SAndroid Build Coastguard Worker { 1323*8975f5c5SAndroid Build Coastguard Worker updateIncompatibleAttachments(glState); 1324*8975f5c5SAndroid Build Coastguard Worker const gl::ProgramExecutable *executable = mState.getProgramExecutable(); 1325*8975f5c5SAndroid Build Coastguard Worker ASSERT(executable); 1326*8975f5c5SAndroid Build Coastguard Worker mExecutable = mtl::GetImpl(executable); 1327*8975f5c5SAndroid Build Coastguard Worker updateProgramExecutable(context); 1328*8975f5c5SAndroid Build Coastguard Worker break; 1329*8975f5c5SAndroid Build Coastguard Worker } 1330*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_TEXTURE_BINDINGS: 1331*8975f5c5SAndroid Build Coastguard Worker invalidateCurrentTextures(); 1332*8975f5c5SAndroid Build Coastguard Worker break; 1333*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_SAMPLER_BINDINGS: 1334*8975f5c5SAndroid Build Coastguard Worker invalidateCurrentTextures(); 1335*8975f5c5SAndroid Build Coastguard Worker break; 1336*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING: 1337*8975f5c5SAndroid Build Coastguard Worker // Nothing to do. 1338*8975f5c5SAndroid Build Coastguard Worker break; 1339*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING: 1340*8975f5c5SAndroid Build Coastguard Worker // NOTE(hqle): ES 3.0 feature. 1341*8975f5c5SAndroid Build Coastguard Worker break; 1342*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS: 1343*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_UNIFORM_BUFFERS_BINDING); 1344*8975f5c5SAndroid Build Coastguard Worker break; 1345*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING: 1346*8975f5c5SAndroid Build Coastguard Worker break; 1347*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_IMAGE_BINDINGS: 1348*8975f5c5SAndroid Build Coastguard Worker // NOTE(hqle): properly handle GLSL images. 1349*8975f5c5SAndroid Build Coastguard Worker invalidateCurrentTextures(); 1350*8975f5c5SAndroid Build Coastguard Worker break; 1351*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_MULTISAMPLING: 1352*8975f5c5SAndroid Build Coastguard Worker // NOTE(hqle): MSAA on/off. 1353*8975f5c5SAndroid Build Coastguard Worker break; 1354*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE: 1355*8975f5c5SAndroid Build Coastguard Worker // NOTE(hqle): this is part of EXT_multisample_compatibility. 1356*8975f5c5SAndroid Build Coastguard Worker // NOTE(hqle): MSAA feature. 1357*8975f5c5SAndroid Build Coastguard Worker break; 1358*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_COVERAGE_MODULATION: 1359*8975f5c5SAndroid Build Coastguard Worker break; 1360*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE: 1361*8975f5c5SAndroid Build Coastguard Worker break; 1362*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_CURRENT_VALUES: 1363*8975f5c5SAndroid Build Coastguard Worker { 1364*8975f5c5SAndroid Build Coastguard Worker invalidateDefaultAttributes(glState.getAndResetDirtyCurrentValues()); 1365*8975f5c5SAndroid Build Coastguard Worker break; 1366*8975f5c5SAndroid Build Coastguard Worker } 1367*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_PROVOKING_VERTEX: 1368*8975f5c5SAndroid Build Coastguard Worker break; 1369*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_EXTENDED: 1370*8975f5c5SAndroid Build Coastguard Worker updateExtendedState(glState, extendedDirtyBits); 1371*8975f5c5SAndroid Build Coastguard Worker break; 1372*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_SAMPLE_SHADING: 1373*8975f5c5SAndroid Build Coastguard Worker // Nothing to do until OES_sample_shading is implemented. 1374*8975f5c5SAndroid Build Coastguard Worker break; 1375*8975f5c5SAndroid Build Coastguard Worker case gl::state::DIRTY_BIT_PATCH_VERTICES: 1376*8975f5c5SAndroid Build Coastguard Worker // Nothing to do until EXT_tessellation_shader is implemented. 1377*8975f5c5SAndroid Build Coastguard Worker break; 1378*8975f5c5SAndroid Build Coastguard Worker default: 1379*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE(); 1380*8975f5c5SAndroid Build Coastguard Worker break; 1381*8975f5c5SAndroid Build Coastguard Worker } 1382*8975f5c5SAndroid Build Coastguard Worker } 1383*8975f5c5SAndroid Build Coastguard Worker 1384*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1385*8975f5c5SAndroid Build Coastguard Worker} 1386*8975f5c5SAndroid Build Coastguard Worker 1387*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::updateExtendedState(const gl::State &glState, 1388*8975f5c5SAndroid Build Coastguard Worker const gl::state::ExtendedDirtyBits extendedDirtyBits) 1389*8975f5c5SAndroid Build Coastguard Worker{ 1390*8975f5c5SAndroid Build Coastguard Worker for (size_t extendedDirtyBit : extendedDirtyBits) 1391*8975f5c5SAndroid Build Coastguard Worker { 1392*8975f5c5SAndroid Build Coastguard Worker switch (extendedDirtyBit) 1393*8975f5c5SAndroid Build Coastguard Worker { 1394*8975f5c5SAndroid Build Coastguard Worker case gl::state::EXTENDED_DIRTY_BIT_CLIP_CONTROL: 1395*8975f5c5SAndroid Build Coastguard Worker updateFrontFace(glState); 1396*8975f5c5SAndroid Build Coastguard Worker invalidateDriverUniforms(); 1397*8975f5c5SAndroid Build Coastguard Worker break; 1398*8975f5c5SAndroid Build Coastguard Worker case gl::state::EXTENDED_DIRTY_BIT_CLIP_DISTANCES: 1399*8975f5c5SAndroid Build Coastguard Worker invalidateDriverUniforms(); 1400*8975f5c5SAndroid Build Coastguard Worker break; 1401*8975f5c5SAndroid Build Coastguard Worker case gl::state::EXTENDED_DIRTY_BIT_DEPTH_CLAMP_ENABLED: 1402*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEPTH_CLIP_MODE); 1403*8975f5c5SAndroid Build Coastguard Worker break; 1404*8975f5c5SAndroid Build Coastguard Worker case gl::state::EXTENDED_DIRTY_BIT_POLYGON_MODE: 1405*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_FILL_MODE); 1406*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS); 1407*8975f5c5SAndroid Build Coastguard Worker break; 1408*8975f5c5SAndroid Build Coastguard Worker case gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_LINE_ENABLED: 1409*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS); 1410*8975f5c5SAndroid Build Coastguard Worker break; 1411*8975f5c5SAndroid Build Coastguard Worker default: 1412*8975f5c5SAndroid Build Coastguard Worker break; 1413*8975f5c5SAndroid Build Coastguard Worker } 1414*8975f5c5SAndroid Build Coastguard Worker } 1415*8975f5c5SAndroid Build Coastguard Worker} 1416*8975f5c5SAndroid Build Coastguard Worker 1417*8975f5c5SAndroid Build Coastguard Worker// Disjoint timer queries 1418*8975f5c5SAndroid Build Coastguard WorkerGLint ContextMtl::getGPUDisjoint() 1419*8975f5c5SAndroid Build Coastguard Worker{ 1420*8975f5c5SAndroid Build Coastguard Worker // Implementation currently is not affected by this. 1421*8975f5c5SAndroid Build Coastguard Worker return 0; 1422*8975f5c5SAndroid Build Coastguard Worker} 1423*8975f5c5SAndroid Build Coastguard Worker 1424*8975f5c5SAndroid Build Coastguard WorkerGLint64 ContextMtl::getTimestamp() 1425*8975f5c5SAndroid Build Coastguard Worker{ 1426*8975f5c5SAndroid Build Coastguard Worker // Timestamps are currently unsupported. An implementation 1427*8975f5c5SAndroid Build Coastguard Worker // strategy is written up in anglebug.com/42266300 if they're needed 1428*8975f5c5SAndroid Build Coastguard Worker // in the future. 1429*8975f5c5SAndroid Build Coastguard Worker return 0; 1430*8975f5c5SAndroid Build Coastguard Worker} 1431*8975f5c5SAndroid Build Coastguard Worker 1432*8975f5c5SAndroid Build Coastguard Worker// Context switching 1433*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::onMakeCurrent(const gl::Context *context) 1434*8975f5c5SAndroid Build Coastguard Worker{ 1435*8975f5c5SAndroid Build Coastguard Worker invalidateState(context); 1436*8975f5c5SAndroid Build Coastguard Worker gl::Query *query = mState.getActiveQuery(gl::QueryType::TimeElapsed); 1437*8975f5c5SAndroid Build Coastguard Worker if (query) 1438*8975f5c5SAndroid Build Coastguard Worker { 1439*8975f5c5SAndroid Build Coastguard Worker GetImplAs<QueryMtl>(query)->onContextMakeCurrent(context); 1440*8975f5c5SAndroid Build Coastguard Worker } 1441*8975f5c5SAndroid Build Coastguard Worker mBufferManager.incrementNumContextSwitches(); 1442*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1443*8975f5c5SAndroid Build Coastguard Worker} 1444*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::onUnMakeCurrent(const gl::Context *context) 1445*8975f5c5SAndroid Build Coastguard Worker{ 1446*8975f5c5SAndroid Build Coastguard Worker flushCommandBuffer(mtl::WaitUntilScheduled); 1447*8975f5c5SAndroid Build Coastguard Worker // Note: this 2nd flush is needed because if there is a query in progress 1448*8975f5c5SAndroid Build Coastguard Worker // then during flush, new command buffers are allocated that also need 1449*8975f5c5SAndroid Build Coastguard Worker // to be flushed. This is a temporary fix and we should probably refactor 1450*8975f5c5SAndroid Build Coastguard Worker // this later. See TODO(anglebug.com/42265611) 1451*8975f5c5SAndroid Build Coastguard Worker flushCommandBuffer(mtl::WaitUntilScheduled); 1452*8975f5c5SAndroid Build Coastguard Worker gl::Query *query = mState.getActiveQuery(gl::QueryType::TimeElapsed); 1453*8975f5c5SAndroid Build Coastguard Worker if (query) 1454*8975f5c5SAndroid Build Coastguard Worker { 1455*8975f5c5SAndroid Build Coastguard Worker GetImplAs<QueryMtl>(query)->onContextUnMakeCurrent(context); 1456*8975f5c5SAndroid Build Coastguard Worker } 1457*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1458*8975f5c5SAndroid Build Coastguard Worker} 1459*8975f5c5SAndroid Build Coastguard Worker 1460*8975f5c5SAndroid Build Coastguard Worker// Native capabilities, unmodified by gl::Context. 1461*8975f5c5SAndroid Build Coastguard Workergl::Caps ContextMtl::getNativeCaps() const 1462*8975f5c5SAndroid Build Coastguard Worker{ 1463*8975f5c5SAndroid Build Coastguard Worker return getDisplay()->getNativeCaps(); 1464*8975f5c5SAndroid Build Coastguard Worker} 1465*8975f5c5SAndroid Build Coastguard Workerconst gl::TextureCapsMap &ContextMtl::getNativeTextureCaps() const 1466*8975f5c5SAndroid Build Coastguard Worker{ 1467*8975f5c5SAndroid Build Coastguard Worker return getDisplay()->getNativeTextureCaps(); 1468*8975f5c5SAndroid Build Coastguard Worker} 1469*8975f5c5SAndroid Build Coastguard Workerconst gl::Extensions &ContextMtl::getNativeExtensions() const 1470*8975f5c5SAndroid Build Coastguard Worker{ 1471*8975f5c5SAndroid Build Coastguard Worker return getDisplay()->getNativeExtensions(); 1472*8975f5c5SAndroid Build Coastguard Worker} 1473*8975f5c5SAndroid Build Coastguard Workerconst gl::Limitations &ContextMtl::getNativeLimitations() const 1474*8975f5c5SAndroid Build Coastguard Worker{ 1475*8975f5c5SAndroid Build Coastguard Worker return getDisplay()->getNativeLimitations(); 1476*8975f5c5SAndroid Build Coastguard Worker} 1477*8975f5c5SAndroid Build Coastguard Workerconst ShPixelLocalStorageOptions &ContextMtl::getNativePixelLocalStorageOptions() const 1478*8975f5c5SAndroid Build Coastguard Worker{ 1479*8975f5c5SAndroid Build Coastguard Worker return getDisplay()->getNativePixelLocalStorageOptions(); 1480*8975f5c5SAndroid Build Coastguard Worker} 1481*8975f5c5SAndroid Build Coastguard Worker 1482*8975f5c5SAndroid Build Coastguard Worker// Shader creation 1483*8975f5c5SAndroid Build Coastguard WorkerCompilerImpl *ContextMtl::createCompiler() 1484*8975f5c5SAndroid Build Coastguard Worker{ 1485*8975f5c5SAndroid Build Coastguard Worker return new CompilerMtl(); 1486*8975f5c5SAndroid Build Coastguard Worker} 1487*8975f5c5SAndroid Build Coastguard WorkerShaderImpl *ContextMtl::createShader(const gl::ShaderState &state) 1488*8975f5c5SAndroid Build Coastguard Worker{ 1489*8975f5c5SAndroid Build Coastguard Worker return new ShaderMtl(state); 1490*8975f5c5SAndroid Build Coastguard Worker} 1491*8975f5c5SAndroid Build Coastguard WorkerProgramImpl *ContextMtl::createProgram(const gl::ProgramState &state) 1492*8975f5c5SAndroid Build Coastguard Worker{ 1493*8975f5c5SAndroid Build Coastguard Worker return new ProgramMtl(state); 1494*8975f5c5SAndroid Build Coastguard Worker} 1495*8975f5c5SAndroid Build Coastguard Worker 1496*8975f5c5SAndroid Build Coastguard WorkerProgramExecutableImpl *ContextMtl::createProgramExecutable(const gl::ProgramExecutable *executable) 1497*8975f5c5SAndroid Build Coastguard Worker{ 1498*8975f5c5SAndroid Build Coastguard Worker return new ProgramExecutableMtl(executable); 1499*8975f5c5SAndroid Build Coastguard Worker} 1500*8975f5c5SAndroid Build Coastguard Worker 1501*8975f5c5SAndroid Build Coastguard Worker// Framebuffer creation 1502*8975f5c5SAndroid Build Coastguard WorkerFramebufferImpl *ContextMtl::createFramebuffer(const gl::FramebufferState &state) 1503*8975f5c5SAndroid Build Coastguard Worker{ 1504*8975f5c5SAndroid Build Coastguard Worker return new FramebufferMtl(state, this, /* flipY */ false); 1505*8975f5c5SAndroid Build Coastguard Worker} 1506*8975f5c5SAndroid Build Coastguard Worker 1507*8975f5c5SAndroid Build Coastguard Worker// Texture creation 1508*8975f5c5SAndroid Build Coastguard WorkerTextureImpl *ContextMtl::createTexture(const gl::TextureState &state) 1509*8975f5c5SAndroid Build Coastguard Worker{ 1510*8975f5c5SAndroid Build Coastguard Worker return new TextureMtl(state); 1511*8975f5c5SAndroid Build Coastguard Worker} 1512*8975f5c5SAndroid Build Coastguard Worker 1513*8975f5c5SAndroid Build Coastguard Worker// Renderbuffer creation 1514*8975f5c5SAndroid Build Coastguard WorkerRenderbufferImpl *ContextMtl::createRenderbuffer(const gl::RenderbufferState &state) 1515*8975f5c5SAndroid Build Coastguard Worker{ 1516*8975f5c5SAndroid Build Coastguard Worker return new RenderbufferMtl(state); 1517*8975f5c5SAndroid Build Coastguard Worker} 1518*8975f5c5SAndroid Build Coastguard Worker 1519*8975f5c5SAndroid Build Coastguard Worker// Buffer creation 1520*8975f5c5SAndroid Build Coastguard WorkerBufferImpl *ContextMtl::createBuffer(const gl::BufferState &state) 1521*8975f5c5SAndroid Build Coastguard Worker{ 1522*8975f5c5SAndroid Build Coastguard Worker return new BufferMtl(state); 1523*8975f5c5SAndroid Build Coastguard Worker} 1524*8975f5c5SAndroid Build Coastguard Worker 1525*8975f5c5SAndroid Build Coastguard Worker// Vertex Array creation 1526*8975f5c5SAndroid Build Coastguard WorkerVertexArrayImpl *ContextMtl::createVertexArray(const gl::VertexArrayState &state) 1527*8975f5c5SAndroid Build Coastguard Worker{ 1528*8975f5c5SAndroid Build Coastguard Worker return new VertexArrayMtl(state, this); 1529*8975f5c5SAndroid Build Coastguard Worker} 1530*8975f5c5SAndroid Build Coastguard Worker 1531*8975f5c5SAndroid Build Coastguard Worker// Query and Fence creation 1532*8975f5c5SAndroid Build Coastguard WorkerQueryImpl *ContextMtl::createQuery(gl::QueryType type) 1533*8975f5c5SAndroid Build Coastguard Worker{ 1534*8975f5c5SAndroid Build Coastguard Worker return new QueryMtl(type); 1535*8975f5c5SAndroid Build Coastguard Worker} 1536*8975f5c5SAndroid Build Coastguard WorkerFenceNVImpl *ContextMtl::createFenceNV() 1537*8975f5c5SAndroid Build Coastguard Worker{ 1538*8975f5c5SAndroid Build Coastguard Worker return new FenceNVMtl(); 1539*8975f5c5SAndroid Build Coastguard Worker} 1540*8975f5c5SAndroid Build Coastguard WorkerSyncImpl *ContextMtl::createSync() 1541*8975f5c5SAndroid Build Coastguard Worker{ 1542*8975f5c5SAndroid Build Coastguard Worker return new SyncMtl(); 1543*8975f5c5SAndroid Build Coastguard Worker} 1544*8975f5c5SAndroid Build Coastguard Worker 1545*8975f5c5SAndroid Build Coastguard Worker// Transform Feedback creation 1546*8975f5c5SAndroid Build Coastguard WorkerTransformFeedbackImpl *ContextMtl::createTransformFeedback(const gl::TransformFeedbackState &state) 1547*8975f5c5SAndroid Build Coastguard Worker{ 1548*8975f5c5SAndroid Build Coastguard Worker // NOTE(hqle): ES 3.0 1549*8975f5c5SAndroid Build Coastguard Worker return new TransformFeedbackMtl(state); 1550*8975f5c5SAndroid Build Coastguard Worker} 1551*8975f5c5SAndroid Build Coastguard Worker 1552*8975f5c5SAndroid Build Coastguard Worker// Sampler object creation 1553*8975f5c5SAndroid Build Coastguard WorkerSamplerImpl *ContextMtl::createSampler(const gl::SamplerState &state) 1554*8975f5c5SAndroid Build Coastguard Worker{ 1555*8975f5c5SAndroid Build Coastguard Worker return new SamplerMtl(state); 1556*8975f5c5SAndroid Build Coastguard Worker} 1557*8975f5c5SAndroid Build Coastguard Worker 1558*8975f5c5SAndroid Build Coastguard Worker// Program Pipeline object creation 1559*8975f5c5SAndroid Build Coastguard WorkerProgramPipelineImpl *ContextMtl::createProgramPipeline(const gl::ProgramPipelineState &data) 1560*8975f5c5SAndroid Build Coastguard Worker{ 1561*8975f5c5SAndroid Build Coastguard Worker // NOTE(hqle): ES 3.0 1562*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED(); 1563*8975f5c5SAndroid Build Coastguard Worker return nullptr; 1564*8975f5c5SAndroid Build Coastguard Worker} 1565*8975f5c5SAndroid Build Coastguard Worker 1566*8975f5c5SAndroid Build Coastguard Worker// Memory object creation. 1567*8975f5c5SAndroid Build Coastguard WorkerMemoryObjectImpl *ContextMtl::createMemoryObject() 1568*8975f5c5SAndroid Build Coastguard Worker{ 1569*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED(); 1570*8975f5c5SAndroid Build Coastguard Worker return nullptr; 1571*8975f5c5SAndroid Build Coastguard Worker} 1572*8975f5c5SAndroid Build Coastguard Worker 1573*8975f5c5SAndroid Build Coastguard Worker// Semaphore creation. 1574*8975f5c5SAndroid Build Coastguard WorkerSemaphoreImpl *ContextMtl::createSemaphore() 1575*8975f5c5SAndroid Build Coastguard Worker{ 1576*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED(); 1577*8975f5c5SAndroid Build Coastguard Worker return nullptr; 1578*8975f5c5SAndroid Build Coastguard Worker} 1579*8975f5c5SAndroid Build Coastguard Worker 1580*8975f5c5SAndroid Build Coastguard WorkerOverlayImpl *ContextMtl::createOverlay(const gl::OverlayState &state) 1581*8975f5c5SAndroid Build Coastguard Worker{ 1582*8975f5c5SAndroid Build Coastguard Worker // Not implemented. 1583*8975f5c5SAndroid Build Coastguard Worker return new OverlayImpl(state); 1584*8975f5c5SAndroid Build Coastguard Worker} 1585*8975f5c5SAndroid Build Coastguard Worker 1586*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::dispatchCompute(const gl::Context *context, 1587*8975f5c5SAndroid Build Coastguard Worker GLuint numGroupsX, 1588*8975f5c5SAndroid Build Coastguard Worker GLuint numGroupsY, 1589*8975f5c5SAndroid Build Coastguard Worker GLuint numGroupsZ) 1590*8975f5c5SAndroid Build Coastguard Worker{ 1591*8975f5c5SAndroid Build Coastguard Worker // NOTE(hqle): ES 3.0 1592*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED(); 1593*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Stop; 1594*8975f5c5SAndroid Build Coastguard Worker} 1595*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) 1596*8975f5c5SAndroid Build Coastguard Worker{ 1597*8975f5c5SAndroid Build Coastguard Worker // NOTE(hqle): ES 3.0 1598*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED(); 1599*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Stop; 1600*8975f5c5SAndroid Build Coastguard Worker} 1601*8975f5c5SAndroid Build Coastguard Worker 1602*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::memoryBarrier(const gl::Context *context, GLbitfield barriers) 1603*8975f5c5SAndroid Build Coastguard Worker{ 1604*8975f5c5SAndroid Build Coastguard Worker if (barriers == 0) 1605*8975f5c5SAndroid Build Coastguard Worker { 1606*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1607*8975f5c5SAndroid Build Coastguard Worker } 1608*8975f5c5SAndroid Build Coastguard Worker if (context->getClientVersion() >= gl::Version{3, 1}) 1609*8975f5c5SAndroid Build Coastguard Worker { 1610*8975f5c5SAndroid Build Coastguard Worker // We expect ES 3.0, and as such we don't consider ES 3.1+ objects in this function yet. 1611*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED(); 1612*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Stop; 1613*8975f5c5SAndroid Build Coastguard Worker } 1614*8975f5c5SAndroid Build Coastguard Worker MTLBarrierScope scope; 1615*8975f5c5SAndroid Build Coastguard Worker switch (barriers) 1616*8975f5c5SAndroid Build Coastguard Worker { 1617*8975f5c5SAndroid Build Coastguard Worker case GL_ALL_BARRIER_BITS: 1618*8975f5c5SAndroid Build Coastguard Worker scope = MTLBarrierScopeTextures | MTLBarrierScopeBuffers; 1619*8975f5c5SAndroid Build Coastguard Worker#if TARGET_OS_OSX || TARGET_OS_MACCATALYST 1620*8975f5c5SAndroid Build Coastguard Worker if (getDisplay()->hasFragmentMemoryBarriers()) 1621*8975f5c5SAndroid Build Coastguard Worker { 1622*8975f5c5SAndroid Build Coastguard Worker scope |= MTLBarrierScopeRenderTargets; 1623*8975f5c5SAndroid Build Coastguard Worker } 1624*8975f5c5SAndroid Build Coastguard Worker#endif 1625*8975f5c5SAndroid Build Coastguard Worker break; 1626*8975f5c5SAndroid Build Coastguard Worker case GL_SHADER_IMAGE_ACCESS_BARRIER_BIT: 1627*8975f5c5SAndroid Build Coastguard Worker scope = MTLBarrierScopeTextures; 1628*8975f5c5SAndroid Build Coastguard Worker#if TARGET_OS_OSX || TARGET_OS_MACCATALYST 1629*8975f5c5SAndroid Build Coastguard Worker if (getDisplay()->hasFragmentMemoryBarriers()) 1630*8975f5c5SAndroid Build Coastguard Worker { 1631*8975f5c5SAndroid Build Coastguard Worker // SHADER_IMAGE_ACCESS_BARRIER_BIT (and SHADER_STORAGE_BARRIER_BIT) require that all 1632*8975f5c5SAndroid Build Coastguard Worker // prior types of accesses are finished before writes to the resource. Since this is 1633*8975f5c5SAndroid Build Coastguard Worker // the case, we also have to include render targets in our barrier to ensure any 1634*8975f5c5SAndroid Build Coastguard Worker // rendering completes before an imageLoad(). 1635*8975f5c5SAndroid Build Coastguard Worker // 1636*8975f5c5SAndroid Build Coastguard Worker // NOTE: Apple Silicon doesn't support MTLBarrierScopeRenderTargets. This seems to 1637*8975f5c5SAndroid Build Coastguard Worker // work anyway though, and on that hardware we use programmable blending for pixel 1638*8975f5c5SAndroid Build Coastguard Worker // local storage instead of read_write textures anyway. 1639*8975f5c5SAndroid Build Coastguard Worker scope |= MTLBarrierScopeRenderTargets; 1640*8975f5c5SAndroid Build Coastguard Worker } 1641*8975f5c5SAndroid Build Coastguard Worker#endif 1642*8975f5c5SAndroid Build Coastguard Worker break; 1643*8975f5c5SAndroid Build Coastguard Worker default: 1644*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED(); 1645*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Stop; 1646*8975f5c5SAndroid Build Coastguard Worker } 1647*8975f5c5SAndroid Build Coastguard Worker // The GL API doesn't provide a distinction between different shader stages. 1648*8975f5c5SAndroid Build Coastguard Worker // ES 3.0 doesn't have compute. 1649*8975f5c5SAndroid Build Coastguard Worker MTLRenderStages stages = MTLRenderStageVertex; 1650*8975f5c5SAndroid Build Coastguard Worker if (getDisplay()->hasFragmentMemoryBarriers()) 1651*8975f5c5SAndroid Build Coastguard Worker { 1652*8975f5c5SAndroid Build Coastguard Worker stages |= MTLRenderStageFragment; 1653*8975f5c5SAndroid Build Coastguard Worker } 1654*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.memoryBarrier(scope, stages, stages); 1655*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1656*8975f5c5SAndroid Build Coastguard Worker} 1657*8975f5c5SAndroid Build Coastguard Worker 1658*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers) 1659*8975f5c5SAndroid Build Coastguard Worker{ 1660*8975f5c5SAndroid Build Coastguard Worker // NOTE(hqle): ES 3.0 1661*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED(); 1662*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Stop; 1663*8975f5c5SAndroid Build Coastguard Worker} 1664*8975f5c5SAndroid Build Coastguard Worker 1665*8975f5c5SAndroid Build Coastguard Worker// override mtl::ErrorHandler 1666*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::handleError(GLenum glErrorCode, 1667*8975f5c5SAndroid Build Coastguard Worker const char *message, 1668*8975f5c5SAndroid Build Coastguard Worker const char *file, 1669*8975f5c5SAndroid Build Coastguard Worker const char *function, 1670*8975f5c5SAndroid Build Coastguard Worker unsigned int line) 1671*8975f5c5SAndroid Build Coastguard Worker{ 1672*8975f5c5SAndroid Build Coastguard Worker mErrors->handleError(glErrorCode, message, file, function, line); 1673*8975f5c5SAndroid Build Coastguard Worker} 1674*8975f5c5SAndroid Build Coastguard Worker 1675*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::handleError(NSError *nserror, 1676*8975f5c5SAndroid Build Coastguard Worker const char *message, 1677*8975f5c5SAndroid Build Coastguard Worker const char *file, 1678*8975f5c5SAndroid Build Coastguard Worker const char *function, 1679*8975f5c5SAndroid Build Coastguard Worker unsigned int line) 1680*8975f5c5SAndroid Build Coastguard Worker{ 1681*8975f5c5SAndroid Build Coastguard Worker if (!nserror) 1682*8975f5c5SAndroid Build Coastguard Worker { 1683*8975f5c5SAndroid Build Coastguard Worker return; 1684*8975f5c5SAndroid Build Coastguard Worker } 1685*8975f5c5SAndroid Build Coastguard Worker 1686*8975f5c5SAndroid Build Coastguard Worker mErrors->handleError(GL_INVALID_OPERATION, message, file, function, line); 1687*8975f5c5SAndroid Build Coastguard Worker} 1688*8975f5c5SAndroid Build Coastguard Worker 1689*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::invalidateState(const gl::Context *context) 1690*8975f5c5SAndroid Build Coastguard Worker{ 1691*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(); 1692*8975f5c5SAndroid Build Coastguard Worker 1693*8975f5c5SAndroid Build Coastguard Worker invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask()); 1694*8975f5c5SAndroid Build Coastguard Worker} 1695*8975f5c5SAndroid Build Coastguard Worker 1696*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::invalidateDefaultAttribute(size_t attribIndex) 1697*8975f5c5SAndroid Build Coastguard Worker{ 1698*8975f5c5SAndroid Build Coastguard Worker mDirtyDefaultAttribsMask.set(attribIndex); 1699*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEFAULT_ATTRIBS); 1700*8975f5c5SAndroid Build Coastguard Worker} 1701*8975f5c5SAndroid Build Coastguard Worker 1702*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask) 1703*8975f5c5SAndroid Build Coastguard Worker{ 1704*8975f5c5SAndroid Build Coastguard Worker if (dirtyMask.any()) 1705*8975f5c5SAndroid Build Coastguard Worker { 1706*8975f5c5SAndroid Build Coastguard Worker mDirtyDefaultAttribsMask |= dirtyMask; 1707*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEFAULT_ATTRIBS); 1708*8975f5c5SAndroid Build Coastguard Worker } 1709*8975f5c5SAndroid Build Coastguard Worker 1710*8975f5c5SAndroid Build Coastguard Worker // TODO(anglebug.com/40096755): determine how to merge this. 1711*8975f5c5SAndroid Build Coastguard Worker#if 0 1712*8975f5c5SAndroid Build Coastguard Worker if (getDisplay()->getFeatures().hasExplicitMemBarrier.enabled) 1713*8975f5c5SAndroid Build Coastguard Worker { 1714*8975f5c5SAndroid Build Coastguard Worker const gl::ProgramExecutable *executable = mState.getProgramExecutable(); 1715*8975f5c5SAndroid Build Coastguard Worker ASSERT(executable); 1716*8975f5c5SAndroid Build Coastguard Worker ASSERT(executable->hasTransformFeedbackOutput() || mState.isTransformFeedbackActive()); 1717*8975f5c5SAndroid Build Coastguard Worker TransformFeedbackMtl *transformFeedbackMtl = mtl::GetImpl(mState.getCurrentTransformFeedback()); 1718*8975f5c5SAndroid Build Coastguard Worker size_t bufferCount = executable->getTransformFeedbackBufferCount(); 1719*8975f5c5SAndroid Build Coastguard Worker const gl::TransformFeedbackBuffersArray<BufferMtl *> &bufferHandles = 1720*8975f5c5SAndroid Build Coastguard Worker transformFeedbackMtl->getBufferHandles(); 1721*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < bufferCount; i++) 1722*8975f5c5SAndroid Build Coastguard Worker { 1723*8975f5c5SAndroid Build Coastguard Worker const mtl::BufferRef & constBufferRef = bufferHandles[i]->getCurrentBuffer(); 1724*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.memoryBarrierWithResource(constBufferRef, mtl::kRenderStageVertex, mtl::kRenderStageVertex); 1725*8975f5c5SAndroid Build Coastguard Worker } 1726*8975f5c5SAndroid Build Coastguard Worker } 1727*8975f5c5SAndroid Build Coastguard Worker else 1728*8975f5c5SAndroid Build Coastguard Worker { 1729*8975f5c5SAndroid Build Coastguard Worker //End the command encoder, so any Transform Feedback changes are available to subsequent draw calls. 1730*8975f5c5SAndroid Build Coastguard Worker endEncoding(false); 1731*8975f5c5SAndroid Build Coastguard Worker } 1732*8975f5c5SAndroid Build Coastguard Worker#endif 1733*8975f5c5SAndroid Build Coastguard Worker} 1734*8975f5c5SAndroid Build Coastguard Worker 1735*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::invalidateCurrentTextures() 1736*8975f5c5SAndroid Build Coastguard Worker{ 1737*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_TEXTURES); 1738*8975f5c5SAndroid Build Coastguard Worker} 1739*8975f5c5SAndroid Build Coastguard Worker 1740*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::invalidateDriverUniforms() 1741*8975f5c5SAndroid Build Coastguard Worker{ 1742*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS); 1743*8975f5c5SAndroid Build Coastguard Worker} 1744*8975f5c5SAndroid Build Coastguard Worker 1745*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::invalidateRenderPipeline() 1746*8975f5c5SAndroid Build Coastguard Worker{ 1747*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_RENDER_PIPELINE); 1748*8975f5c5SAndroid Build Coastguard Worker} 1749*8975f5c5SAndroid Build Coastguard Worker 1750*8975f5c5SAndroid Build Coastguard Workerconst mtl::ClearColorValue &ContextMtl::getClearColorValue() const 1751*8975f5c5SAndroid Build Coastguard Worker{ 1752*8975f5c5SAndroid Build Coastguard Worker return mClearColor; 1753*8975f5c5SAndroid Build Coastguard Worker} 1754*8975f5c5SAndroid Build Coastguard Workerconst mtl::WriteMaskArray &ContextMtl::getWriteMaskArray() const 1755*8975f5c5SAndroid Build Coastguard Worker{ 1756*8975f5c5SAndroid Build Coastguard Worker return mWriteMaskArray; 1757*8975f5c5SAndroid Build Coastguard Worker} 1758*8975f5c5SAndroid Build Coastguard Workerfloat ContextMtl::getClearDepthValue() const 1759*8975f5c5SAndroid Build Coastguard Worker{ 1760*8975f5c5SAndroid Build Coastguard Worker return getState().getDepthClearValue(); 1761*8975f5c5SAndroid Build Coastguard Worker} 1762*8975f5c5SAndroid Build Coastguard Workeruint32_t ContextMtl::getClearStencilValue() const 1763*8975f5c5SAndroid Build Coastguard Worker{ 1764*8975f5c5SAndroid Build Coastguard Worker return mClearStencil; 1765*8975f5c5SAndroid Build Coastguard Worker} 1766*8975f5c5SAndroid Build Coastguard Workeruint32_t ContextMtl::getStencilMask() const 1767*8975f5c5SAndroid Build Coastguard Worker{ 1768*8975f5c5SAndroid Build Coastguard Worker return getState().getDepthStencilState().stencilWritemask & mtl::kStencilMaskAll; 1769*8975f5c5SAndroid Build Coastguard Worker} 1770*8975f5c5SAndroid Build Coastguard Worker 1771*8975f5c5SAndroid Build Coastguard Workerbool ContextMtl::getDepthMask() const 1772*8975f5c5SAndroid Build Coastguard Worker{ 1773*8975f5c5SAndroid Build Coastguard Worker return getState().getDepthStencilState().depthMask; 1774*8975f5c5SAndroid Build Coastguard Worker} 1775*8975f5c5SAndroid Build Coastguard Worker 1776*8975f5c5SAndroid Build Coastguard Workerconst mtl::Format &ContextMtl::getPixelFormat(angle::FormatID angleFormatId) const 1777*8975f5c5SAndroid Build Coastguard Worker{ 1778*8975f5c5SAndroid Build Coastguard Worker return getDisplay()->getPixelFormat(angleFormatId); 1779*8975f5c5SAndroid Build Coastguard Worker} 1780*8975f5c5SAndroid Build Coastguard Worker 1781*8975f5c5SAndroid Build Coastguard Worker// See mtl::FormatTable::getVertexFormat() 1782*8975f5c5SAndroid Build Coastguard Workerconst mtl::VertexFormat &ContextMtl::getVertexFormat(angle::FormatID angleFormatId, 1783*8975f5c5SAndroid Build Coastguard Worker bool tightlyPacked) const 1784*8975f5c5SAndroid Build Coastguard Worker{ 1785*8975f5c5SAndroid Build Coastguard Worker return getDisplay()->getVertexFormat(angleFormatId, tightlyPacked); 1786*8975f5c5SAndroid Build Coastguard Worker} 1787*8975f5c5SAndroid Build Coastguard Worker 1788*8975f5c5SAndroid Build Coastguard Workerconst mtl::FormatCaps &ContextMtl::getNativeFormatCaps(MTLPixelFormat mtlFormat) const 1789*8975f5c5SAndroid Build Coastguard Worker{ 1790*8975f5c5SAndroid Build Coastguard Worker return getDisplay()->getNativeFormatCaps(mtlFormat); 1791*8975f5c5SAndroid Build Coastguard Worker} 1792*8975f5c5SAndroid Build Coastguard Worker 1793*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::getIncompleteTexture(const gl::Context *context, 1794*8975f5c5SAndroid Build Coastguard Worker gl::TextureType type, 1795*8975f5c5SAndroid Build Coastguard Worker gl::SamplerFormat format, 1796*8975f5c5SAndroid Build Coastguard Worker gl::Texture **textureOut) 1797*8975f5c5SAndroid Build Coastguard Worker{ 1798*8975f5c5SAndroid Build Coastguard Worker return mIncompleteTextures.getIncompleteTexture(context, type, format, nullptr, textureOut); 1799*8975f5c5SAndroid Build Coastguard Worker} 1800*8975f5c5SAndroid Build Coastguard Worker 1801*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::endRenderEncoding(mtl::RenderCommandEncoder *encoder) 1802*8975f5c5SAndroid Build Coastguard Worker{ 1803*8975f5c5SAndroid Build Coastguard Worker // End any pending visibility query in the render pass 1804*8975f5c5SAndroid Build Coastguard Worker if (mOcclusionQuery) 1805*8975f5c5SAndroid Build Coastguard Worker { 1806*8975f5c5SAndroid Build Coastguard Worker disableActiveOcclusionQueryInRenderPass(); 1807*8975f5c5SAndroid Build Coastguard Worker } 1808*8975f5c5SAndroid Build Coastguard Worker 1809*8975f5c5SAndroid Build Coastguard Worker if (mBlitEncoder.valid()) 1810*8975f5c5SAndroid Build Coastguard Worker { 1811*8975f5c5SAndroid Build Coastguard Worker mBlitEncoder.endEncoding(); 1812*8975f5c5SAndroid Build Coastguard Worker } 1813*8975f5c5SAndroid Build Coastguard Worker 1814*8975f5c5SAndroid Build Coastguard Worker mOcclusionQueryPool.prepareRenderPassVisibilityPoolBuffer(this); 1815*8975f5c5SAndroid Build Coastguard Worker 1816*8975f5c5SAndroid Build Coastguard Worker encoder->endEncoding(); 1817*8975f5c5SAndroid Build Coastguard Worker 1818*8975f5c5SAndroid Build Coastguard Worker // Resolve visibility results 1819*8975f5c5SAndroid Build Coastguard Worker mOcclusionQueryPool.resolveVisibilityResults(this); 1820*8975f5c5SAndroid Build Coastguard Worker} 1821*8975f5c5SAndroid Build Coastguard Worker 1822*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::endBlitAndComputeEncoding() 1823*8975f5c5SAndroid Build Coastguard Worker{ 1824*8975f5c5SAndroid Build Coastguard Worker if (mBlitEncoder.valid()) 1825*8975f5c5SAndroid Build Coastguard Worker { 1826*8975f5c5SAndroid Build Coastguard Worker mBlitEncoder.endEncoding(); 1827*8975f5c5SAndroid Build Coastguard Worker } 1828*8975f5c5SAndroid Build Coastguard Worker 1829*8975f5c5SAndroid Build Coastguard Worker if (mComputeEncoder.valid()) 1830*8975f5c5SAndroid Build Coastguard Worker { 1831*8975f5c5SAndroid Build Coastguard Worker mComputeEncoder.endEncoding(); 1832*8975f5c5SAndroid Build Coastguard Worker mProvokingVertexHelper.releaseInFlightBuffers(this); 1833*8975f5c5SAndroid Build Coastguard Worker } 1834*8975f5c5SAndroid Build Coastguard Worker} 1835*8975f5c5SAndroid Build Coastguard Worker 1836*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::endEncoding(bool forceSaveRenderPassContent) 1837*8975f5c5SAndroid Build Coastguard Worker{ 1838*8975f5c5SAndroid Build Coastguard Worker endBlitAndComputeEncoding(); 1839*8975f5c5SAndroid Build Coastguard Worker 1840*8975f5c5SAndroid Build Coastguard Worker if (mRenderEncoder.valid()) 1841*8975f5c5SAndroid Build Coastguard Worker { 1842*8975f5c5SAndroid Build Coastguard Worker if (forceSaveRenderPassContent) 1843*8975f5c5SAndroid Build Coastguard Worker { 1844*8975f5c5SAndroid Build Coastguard Worker // Save the work in progress. 1845*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.setStoreAction(MTLStoreActionStore); 1846*8975f5c5SAndroid Build Coastguard Worker } 1847*8975f5c5SAndroid Build Coastguard Worker 1848*8975f5c5SAndroid Build Coastguard Worker endRenderEncoding(&mRenderEncoder); 1849*8975f5c5SAndroid Build Coastguard Worker } 1850*8975f5c5SAndroid Build Coastguard Worker // End blit encoder after render encoder, as endRenderEncoding() might create a 1851*8975f5c5SAndroid Build Coastguard Worker // blit encoder to resolve the visibility results. 1852*8975f5c5SAndroid Build Coastguard Worker if (mBlitEncoder.valid()) 1853*8975f5c5SAndroid Build Coastguard Worker { 1854*8975f5c5SAndroid Build Coastguard Worker mBlitEncoder.endEncoding(); 1855*8975f5c5SAndroid Build Coastguard Worker } 1856*8975f5c5SAndroid Build Coastguard Worker} 1857*8975f5c5SAndroid Build Coastguard Worker 1858*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::flushCommandBuffer(mtl::CommandBufferFinishOperation operation) 1859*8975f5c5SAndroid Build Coastguard Worker{ 1860*8975f5c5SAndroid Build Coastguard Worker mRenderPassesSinceFlush = 0; 1861*8975f5c5SAndroid Build Coastguard Worker if (mCmdBuffer.ready()) 1862*8975f5c5SAndroid Build Coastguard Worker { 1863*8975f5c5SAndroid Build Coastguard Worker endEncoding(true); 1864*8975f5c5SAndroid Build Coastguard Worker mCmdBuffer.commit(operation); 1865*8975f5c5SAndroid Build Coastguard Worker mBufferManager.incrementNumCommandBufferCommits(); 1866*8975f5c5SAndroid Build Coastguard Worker } 1867*8975f5c5SAndroid Build Coastguard Worker else 1868*8975f5c5SAndroid Build Coastguard Worker { 1869*8975f5c5SAndroid Build Coastguard Worker mCmdBuffer.wait(operation); 1870*8975f5c5SAndroid Build Coastguard Worker } 1871*8975f5c5SAndroid Build Coastguard Worker} 1872*8975f5c5SAndroid Build Coastguard Worker 1873*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::flushCommandBufferIfNeeded() 1874*8975f5c5SAndroid Build Coastguard Worker{ 1875*8975f5c5SAndroid Build Coastguard Worker if (mRenderPassesSinceFlush >= mtl::kMaxRenderPassesPerCommandBuffer || 1876*8975f5c5SAndroid Build Coastguard Worker mCmdBuffer.needsFlushForDrawCallLimits()) 1877*8975f5c5SAndroid Build Coastguard Worker { 1878*8975f5c5SAndroid Build Coastguard Worker // Ensure that we don't accumulate too many unflushed render passes. Don't wait until they 1879*8975f5c5SAndroid Build Coastguard Worker // are submitted, other components handle backpressure so don't create uneccessary CPU/GPU 1880*8975f5c5SAndroid Build Coastguard Worker // synchronization. 1881*8975f5c5SAndroid Build Coastguard Worker flushCommandBuffer(mtl::NoWait); 1882*8975f5c5SAndroid Build Coastguard Worker } 1883*8975f5c5SAndroid Build Coastguard Worker} 1884*8975f5c5SAndroid Build Coastguard Worker 1885*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::present(const gl::Context *context, id<CAMetalDrawable> presentationDrawable) 1886*8975f5c5SAndroid Build Coastguard Worker{ 1887*8975f5c5SAndroid Build Coastguard Worker ensureCommandBufferReady(); 1888*8975f5c5SAndroid Build Coastguard Worker 1889*8975f5c5SAndroid Build Coastguard Worker FramebufferMtl *currentframebuffer = mtl::GetImpl(getState().getDrawFramebuffer()); 1890*8975f5c5SAndroid Build Coastguard Worker if (currentframebuffer) 1891*8975f5c5SAndroid Build Coastguard Worker { 1892*8975f5c5SAndroid Build Coastguard Worker currentframebuffer->onFrameEnd(context); 1893*8975f5c5SAndroid Build Coastguard Worker } 1894*8975f5c5SAndroid Build Coastguard Worker 1895*8975f5c5SAndroid Build Coastguard Worker endEncoding(false); 1896*8975f5c5SAndroid Build Coastguard Worker mCmdBuffer.present(presentationDrawable); 1897*8975f5c5SAndroid Build Coastguard Worker mCmdBuffer.commit(mtl::NoWait); 1898*8975f5c5SAndroid Build Coastguard Worker mRenderPassesSinceFlush = 0; 1899*8975f5c5SAndroid Build Coastguard Worker} 1900*8975f5c5SAndroid Build Coastguard Worker 1901*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::finishCommandBuffer() 1902*8975f5c5SAndroid Build Coastguard Worker{ 1903*8975f5c5SAndroid Build Coastguard Worker flushCommandBuffer(mtl::WaitUntilFinished); 1904*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 1905*8975f5c5SAndroid Build Coastguard Worker} 1906*8975f5c5SAndroid Build Coastguard Worker 1907*8975f5c5SAndroid Build Coastguard Workerbool ContextMtl::hasStartedRenderPass(const mtl::RenderPassDesc &desc) 1908*8975f5c5SAndroid Build Coastguard Worker{ 1909*8975f5c5SAndroid Build Coastguard Worker return mRenderEncoder.valid() && 1910*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.renderPassDesc().equalIgnoreLoadStoreOptions(desc); 1911*8975f5c5SAndroid Build Coastguard Worker} 1912*8975f5c5SAndroid Build Coastguard Worker 1913*8975f5c5SAndroid Build Coastguard Workerbool ContextMtl::isCurrentRenderEncoderSerial(uint64_t serial) 1914*8975f5c5SAndroid Build Coastguard Worker{ 1915*8975f5c5SAndroid Build Coastguard Worker if (!mRenderEncoder.valid()) 1916*8975f5c5SAndroid Build Coastguard Worker { 1917*8975f5c5SAndroid Build Coastguard Worker return false; 1918*8975f5c5SAndroid Build Coastguard Worker } 1919*8975f5c5SAndroid Build Coastguard Worker 1920*8975f5c5SAndroid Build Coastguard Worker return serial == mRenderEncoder.getSerial(); 1921*8975f5c5SAndroid Build Coastguard Worker} 1922*8975f5c5SAndroid Build Coastguard Worker 1923*8975f5c5SAndroid Build Coastguard Worker// Get current render encoder 1924*8975f5c5SAndroid Build Coastguard Workermtl::RenderCommandEncoder *ContextMtl::getRenderCommandEncoder() 1925*8975f5c5SAndroid Build Coastguard Worker{ 1926*8975f5c5SAndroid Build Coastguard Worker if (!mRenderEncoder.valid()) 1927*8975f5c5SAndroid Build Coastguard Worker { 1928*8975f5c5SAndroid Build Coastguard Worker return nullptr; 1929*8975f5c5SAndroid Build Coastguard Worker } 1930*8975f5c5SAndroid Build Coastguard Worker 1931*8975f5c5SAndroid Build Coastguard Worker return &mRenderEncoder; 1932*8975f5c5SAndroid Build Coastguard Worker} 1933*8975f5c5SAndroid Build Coastguard Worker 1934*8975f5c5SAndroid Build Coastguard Workermtl::RenderCommandEncoder *ContextMtl::getRenderPassCommandEncoder(const mtl::RenderPassDesc &desc) 1935*8975f5c5SAndroid Build Coastguard Worker{ 1936*8975f5c5SAndroid Build Coastguard Worker if (hasStartedRenderPass(desc)) 1937*8975f5c5SAndroid Build Coastguard Worker { 1938*8975f5c5SAndroid Build Coastguard Worker return &mRenderEncoder; 1939*8975f5c5SAndroid Build Coastguard Worker } 1940*8975f5c5SAndroid Build Coastguard Worker 1941*8975f5c5SAndroid Build Coastguard Worker endEncoding(false); 1942*8975f5c5SAndroid Build Coastguard Worker 1943*8975f5c5SAndroid Build Coastguard Worker ensureCommandBufferReady(); 1944*8975f5c5SAndroid Build Coastguard Worker ++mRenderPassesSinceFlush; 1945*8975f5c5SAndroid Build Coastguard Worker 1946*8975f5c5SAndroid Build Coastguard Worker // Need to re-apply everything on next draw call. 1947*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(); 1948*8975f5c5SAndroid Build Coastguard Worker 1949*8975f5c5SAndroid Build Coastguard Worker const mtl::ContextDevice &metalDevice = getMetalDevice(); 1950*8975f5c5SAndroid Build Coastguard Worker if (mtl::DeviceHasMaximumRenderTargetSize(metalDevice)) 1951*8975f5c5SAndroid Build Coastguard Worker { 1952*8975f5c5SAndroid Build Coastguard Worker NSUInteger maxSize = mtl::GetMaxRenderTargetSizeForDeviceInBytes(metalDevice); 1953*8975f5c5SAndroid Build Coastguard Worker NSUInteger renderTargetSize = 1954*8975f5c5SAndroid Build Coastguard Worker ComputeTotalSizeUsedForMTLRenderPassDescriptor(desc, this, metalDevice); 1955*8975f5c5SAndroid Build Coastguard Worker if (renderTargetSize > maxSize) 1956*8975f5c5SAndroid Build Coastguard Worker { 1957*8975f5c5SAndroid Build Coastguard Worker std::stringstream errorStream; 1958*8975f5c5SAndroid Build Coastguard Worker errorStream << "This set of render targets requires " << renderTargetSize 1959*8975f5c5SAndroid Build Coastguard Worker << " bytes of pixel storage. This device supports " << maxSize << " bytes."; 1960*8975f5c5SAndroid Build Coastguard Worker ANGLE_MTL_HANDLE_ERROR(this, errorStream.str().c_str(), GL_INVALID_OPERATION); 1961*8975f5c5SAndroid Build Coastguard Worker return nullptr; 1962*8975f5c5SAndroid Build Coastguard Worker } 1963*8975f5c5SAndroid Build Coastguard Worker } 1964*8975f5c5SAndroid Build Coastguard Worker return &mRenderEncoder.restart(desc, getNativeCaps().maxColorAttachments); 1965*8975f5c5SAndroid Build Coastguard Worker} 1966*8975f5c5SAndroid Build Coastguard Worker 1967*8975f5c5SAndroid Build Coastguard Worker// Utilities to quickly create render command encoder to a specific texture: 1968*8975f5c5SAndroid Build Coastguard Worker// The previous content of texture will be loaded 1969*8975f5c5SAndroid Build Coastguard Workermtl::RenderCommandEncoder *ContextMtl::getTextureRenderCommandEncoder( 1970*8975f5c5SAndroid Build Coastguard Worker const mtl::TextureRef &textureTarget, 1971*8975f5c5SAndroid Build Coastguard Worker const mtl::ImageNativeIndex &index) 1972*8975f5c5SAndroid Build Coastguard Worker{ 1973*8975f5c5SAndroid Build Coastguard Worker ASSERT(textureTarget && textureTarget->valid()); 1974*8975f5c5SAndroid Build Coastguard Worker 1975*8975f5c5SAndroid Build Coastguard Worker mtl::RenderPassDesc rpDesc; 1976*8975f5c5SAndroid Build Coastguard Worker 1977*8975f5c5SAndroid Build Coastguard Worker rpDesc.colorAttachments[0].texture = textureTarget; 1978*8975f5c5SAndroid Build Coastguard Worker rpDesc.colorAttachments[0].level = index.getNativeLevel(); 1979*8975f5c5SAndroid Build Coastguard Worker rpDesc.colorAttachments[0].sliceOrDepth = index.hasLayer() ? index.getLayerIndex() : 0; 1980*8975f5c5SAndroid Build Coastguard Worker rpDesc.numColorAttachments = 1; 1981*8975f5c5SAndroid Build Coastguard Worker rpDesc.rasterSampleCount = textureTarget->samples(); 1982*8975f5c5SAndroid Build Coastguard Worker 1983*8975f5c5SAndroid Build Coastguard Worker return getRenderPassCommandEncoder(rpDesc); 1984*8975f5c5SAndroid Build Coastguard Worker} 1985*8975f5c5SAndroid Build Coastguard Worker 1986*8975f5c5SAndroid Build Coastguard Worker// The previous content of texture will be loaded if clearColor is not provided 1987*8975f5c5SAndroid Build Coastguard Workermtl::RenderCommandEncoder *ContextMtl::getRenderTargetCommandEncoderWithClear( 1988*8975f5c5SAndroid Build Coastguard Worker const RenderTargetMtl &renderTarget, 1989*8975f5c5SAndroid Build Coastguard Worker const Optional<MTLClearColor> &clearColor) 1990*8975f5c5SAndroid Build Coastguard Worker{ 1991*8975f5c5SAndroid Build Coastguard Worker ASSERT(renderTarget.getTexture()); 1992*8975f5c5SAndroid Build Coastguard Worker 1993*8975f5c5SAndroid Build Coastguard Worker mtl::RenderPassDesc rpDesc; 1994*8975f5c5SAndroid Build Coastguard Worker renderTarget.toRenderPassAttachmentDesc(&rpDesc.colorAttachments[0]); 1995*8975f5c5SAndroid Build Coastguard Worker rpDesc.numColorAttachments = 1; 1996*8975f5c5SAndroid Build Coastguard Worker rpDesc.rasterSampleCount = renderTarget.getRenderSamples(); 1997*8975f5c5SAndroid Build Coastguard Worker 1998*8975f5c5SAndroid Build Coastguard Worker if (clearColor.valid()) 1999*8975f5c5SAndroid Build Coastguard Worker { 2000*8975f5c5SAndroid Build Coastguard Worker rpDesc.colorAttachments[0].loadAction = MTLLoadActionClear; 2001*8975f5c5SAndroid Build Coastguard Worker rpDesc.colorAttachments[0].clearColor = mtl::EmulatedAlphaClearColor( 2002*8975f5c5SAndroid Build Coastguard Worker clearColor.value(), renderTarget.getTexture()->getColorWritableMask()); 2003*8975f5c5SAndroid Build Coastguard Worker 2004*8975f5c5SAndroid Build Coastguard Worker endEncoding(true); 2005*8975f5c5SAndroid Build Coastguard Worker } 2006*8975f5c5SAndroid Build Coastguard Worker 2007*8975f5c5SAndroid Build Coastguard Worker return getRenderPassCommandEncoder(rpDesc); 2008*8975f5c5SAndroid Build Coastguard Worker} 2009*8975f5c5SAndroid Build Coastguard Worker// The previous content of texture will be loaded 2010*8975f5c5SAndroid Build Coastguard Workermtl::RenderCommandEncoder *ContextMtl::getRenderTargetCommandEncoder( 2011*8975f5c5SAndroid Build Coastguard Worker const RenderTargetMtl &renderTarget) 2012*8975f5c5SAndroid Build Coastguard Worker{ 2013*8975f5c5SAndroid Build Coastguard Worker return getRenderTargetCommandEncoderWithClear(renderTarget, Optional<MTLClearColor>()); 2014*8975f5c5SAndroid Build Coastguard Worker} 2015*8975f5c5SAndroid Build Coastguard Worker 2016*8975f5c5SAndroid Build Coastguard Workermtl::BlitCommandEncoder *ContextMtl::getBlitCommandEncoder() 2017*8975f5c5SAndroid Build Coastguard Worker{ 2018*8975f5c5SAndroid Build Coastguard Worker if (mRenderEncoder.valid() || mComputeEncoder.valid()) 2019*8975f5c5SAndroid Build Coastguard Worker { 2020*8975f5c5SAndroid Build Coastguard Worker endEncoding(true); 2021*8975f5c5SAndroid Build Coastguard Worker } 2022*8975f5c5SAndroid Build Coastguard Worker 2023*8975f5c5SAndroid Build Coastguard Worker if (mBlitEncoder.valid()) 2024*8975f5c5SAndroid Build Coastguard Worker { 2025*8975f5c5SAndroid Build Coastguard Worker return &mBlitEncoder; 2026*8975f5c5SAndroid Build Coastguard Worker } 2027*8975f5c5SAndroid Build Coastguard Worker 2028*8975f5c5SAndroid Build Coastguard Worker endEncoding(true); 2029*8975f5c5SAndroid Build Coastguard Worker ensureCommandBufferReady(); 2030*8975f5c5SAndroid Build Coastguard Worker 2031*8975f5c5SAndroid Build Coastguard Worker return &mBlitEncoder.restart(); 2032*8975f5c5SAndroid Build Coastguard Worker} 2033*8975f5c5SAndroid Build Coastguard Worker 2034*8975f5c5SAndroid Build Coastguard Workermtl::BlitCommandEncoder *ContextMtl::getBlitCommandEncoderWithoutEndingRenderEncoder() 2035*8975f5c5SAndroid Build Coastguard Worker{ 2036*8975f5c5SAndroid Build Coastguard Worker if (mBlitEncoder.valid()) 2037*8975f5c5SAndroid Build Coastguard Worker { 2038*8975f5c5SAndroid Build Coastguard Worker return &mBlitEncoder; 2039*8975f5c5SAndroid Build Coastguard Worker } 2040*8975f5c5SAndroid Build Coastguard Worker 2041*8975f5c5SAndroid Build Coastguard Worker endBlitAndComputeEncoding(); 2042*8975f5c5SAndroid Build Coastguard Worker ensureCommandBufferReady(); 2043*8975f5c5SAndroid Build Coastguard Worker 2044*8975f5c5SAndroid Build Coastguard Worker return &mBlitEncoder.restart(); 2045*8975f5c5SAndroid Build Coastguard Worker} 2046*8975f5c5SAndroid Build Coastguard Worker 2047*8975f5c5SAndroid Build Coastguard Workermtl::ComputeCommandEncoder *ContextMtl::getComputeCommandEncoder() 2048*8975f5c5SAndroid Build Coastguard Worker{ 2049*8975f5c5SAndroid Build Coastguard Worker if (mRenderEncoder.valid() || mBlitEncoder.valid()) 2050*8975f5c5SAndroid Build Coastguard Worker { 2051*8975f5c5SAndroid Build Coastguard Worker endEncoding(true); 2052*8975f5c5SAndroid Build Coastguard Worker } 2053*8975f5c5SAndroid Build Coastguard Worker 2054*8975f5c5SAndroid Build Coastguard Worker if (mComputeEncoder.valid()) 2055*8975f5c5SAndroid Build Coastguard Worker { 2056*8975f5c5SAndroid Build Coastguard Worker return &mComputeEncoder; 2057*8975f5c5SAndroid Build Coastguard Worker } 2058*8975f5c5SAndroid Build Coastguard Worker 2059*8975f5c5SAndroid Build Coastguard Worker endEncoding(true); 2060*8975f5c5SAndroid Build Coastguard Worker ensureCommandBufferReady(); 2061*8975f5c5SAndroid Build Coastguard Worker 2062*8975f5c5SAndroid Build Coastguard Worker return &mComputeEncoder.restart(); 2063*8975f5c5SAndroid Build Coastguard Worker} 2064*8975f5c5SAndroid Build Coastguard Worker 2065*8975f5c5SAndroid Build Coastguard Workermtl::ComputeCommandEncoder *ContextMtl::getComputeCommandEncoderWithoutEndingRenderEncoder() 2066*8975f5c5SAndroid Build Coastguard Worker{ 2067*8975f5c5SAndroid Build Coastguard Worker if (mComputeEncoder.valid()) 2068*8975f5c5SAndroid Build Coastguard Worker { 2069*8975f5c5SAndroid Build Coastguard Worker return &mComputeEncoder; 2070*8975f5c5SAndroid Build Coastguard Worker } 2071*8975f5c5SAndroid Build Coastguard Worker 2072*8975f5c5SAndroid Build Coastguard Worker endBlitAndComputeEncoding(); 2073*8975f5c5SAndroid Build Coastguard Worker ensureCommandBufferReady(); 2074*8975f5c5SAndroid Build Coastguard Worker 2075*8975f5c5SAndroid Build Coastguard Worker return &mComputeEncoder.restart(); 2076*8975f5c5SAndroid Build Coastguard Worker} 2077*8975f5c5SAndroid Build Coastguard Worker 2078*8975f5c5SAndroid Build Coastguard Workermtl::ComputeCommandEncoder *ContextMtl::getIndexPreprocessingCommandEncoder() 2079*8975f5c5SAndroid Build Coastguard Worker{ 2080*8975f5c5SAndroid Build Coastguard Worker return getComputeCommandEncoder(); 2081*8975f5c5SAndroid Build Coastguard Worker} 2082*8975f5c5SAndroid Build Coastguard Worker 2083*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::ensureCommandBufferReady() 2084*8975f5c5SAndroid Build Coastguard Worker{ 2085*8975f5c5SAndroid Build Coastguard Worker flushCommandBufferIfNeeded(); 2086*8975f5c5SAndroid Build Coastguard Worker 2087*8975f5c5SAndroid Build Coastguard Worker if (!mCmdBuffer.ready()) 2088*8975f5c5SAndroid Build Coastguard Worker { 2089*8975f5c5SAndroid Build Coastguard Worker mCmdBuffer.restart(); 2090*8975f5c5SAndroid Build Coastguard Worker } 2091*8975f5c5SAndroid Build Coastguard Worker 2092*8975f5c5SAndroid Build Coastguard Worker ASSERT(mCmdBuffer.ready()); 2093*8975f5c5SAndroid Build Coastguard Worker} 2094*8975f5c5SAndroid Build Coastguard Worker 2095*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::updateViewport(FramebufferMtl *framebufferMtl, 2096*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &viewport, 2097*8975f5c5SAndroid Build Coastguard Worker float nearPlane, 2098*8975f5c5SAndroid Build Coastguard Worker float farPlane) 2099*8975f5c5SAndroid Build Coastguard Worker{ 2100*8975f5c5SAndroid Build Coastguard Worker mViewport = mtl::GetViewport(viewport, framebufferMtl->getState().getDimensions().height, 2101*8975f5c5SAndroid Build Coastguard Worker framebufferMtl->flipY(), nearPlane, farPlane); 2102*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_VIEWPORT); 2103*8975f5c5SAndroid Build Coastguard Worker 2104*8975f5c5SAndroid Build Coastguard Worker invalidateDriverUniforms(); 2105*8975f5c5SAndroid Build Coastguard Worker} 2106*8975f5c5SAndroid Build Coastguard Worker 2107*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::updateDepthRange(float nearPlane, float farPlane) 2108*8975f5c5SAndroid Build Coastguard Worker{ 2109*8975f5c5SAndroid Build Coastguard Worker if (NeedToInvertDepthRange(nearPlane, farPlane)) 2110*8975f5c5SAndroid Build Coastguard Worker { 2111*8975f5c5SAndroid Build Coastguard Worker // We also need to invert the depth in shader later by using scale value stored in driver 2112*8975f5c5SAndroid Build Coastguard Worker // uniform depthRange.reserved 2113*8975f5c5SAndroid Build Coastguard Worker std::swap(nearPlane, farPlane); 2114*8975f5c5SAndroid Build Coastguard Worker } 2115*8975f5c5SAndroid Build Coastguard Worker mViewport.znear = nearPlane; 2116*8975f5c5SAndroid Build Coastguard Worker mViewport.zfar = farPlane; 2117*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_VIEWPORT); 2118*8975f5c5SAndroid Build Coastguard Worker 2119*8975f5c5SAndroid Build Coastguard Worker invalidateDriverUniforms(); 2120*8975f5c5SAndroid Build Coastguard Worker} 2121*8975f5c5SAndroid Build Coastguard Worker 2122*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::updateBlendDescArray(const gl::BlendStateExt &blendStateExt) 2123*8975f5c5SAndroid Build Coastguard Worker{ 2124*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < mBlendDescArray.size(); i++) 2125*8975f5c5SAndroid Build Coastguard Worker { 2126*8975f5c5SAndroid Build Coastguard Worker mtl::BlendDesc &blendDesc = mBlendDescArray[i]; 2127*8975f5c5SAndroid Build Coastguard Worker if (blendStateExt.getEnabledMask().test(i)) 2128*8975f5c5SAndroid Build Coastguard Worker { 2129*8975f5c5SAndroid Build Coastguard Worker blendDesc.blendingEnabled = true; 2130*8975f5c5SAndroid Build Coastguard Worker 2131*8975f5c5SAndroid Build Coastguard Worker blendDesc.sourceRGBBlendFactor = 2132*8975f5c5SAndroid Build Coastguard Worker mtl::GetBlendFactor(blendStateExt.getSrcColorIndexed(i)); 2133*8975f5c5SAndroid Build Coastguard Worker blendDesc.sourceAlphaBlendFactor = 2134*8975f5c5SAndroid Build Coastguard Worker mtl::GetBlendFactor(blendStateExt.getSrcAlphaIndexed(i)); 2135*8975f5c5SAndroid Build Coastguard Worker blendDesc.destinationRGBBlendFactor = 2136*8975f5c5SAndroid Build Coastguard Worker mtl::GetBlendFactor(blendStateExt.getDstColorIndexed(i)); 2137*8975f5c5SAndroid Build Coastguard Worker blendDesc.destinationAlphaBlendFactor = 2138*8975f5c5SAndroid Build Coastguard Worker mtl::GetBlendFactor(blendStateExt.getDstAlphaIndexed(i)); 2139*8975f5c5SAndroid Build Coastguard Worker 2140*8975f5c5SAndroid Build Coastguard Worker blendDesc.rgbBlendOperation = mtl::GetBlendOp(blendStateExt.getEquationColorIndexed(i)); 2141*8975f5c5SAndroid Build Coastguard Worker blendDesc.alphaBlendOperation = 2142*8975f5c5SAndroid Build Coastguard Worker mtl::GetBlendOp(blendStateExt.getEquationAlphaIndexed(i)); 2143*8975f5c5SAndroid Build Coastguard Worker } 2144*8975f5c5SAndroid Build Coastguard Worker else 2145*8975f5c5SAndroid Build Coastguard Worker { 2146*8975f5c5SAndroid Build Coastguard Worker // Enforce default state when blending is disabled, 2147*8975f5c5SAndroid Build Coastguard Worker blendDesc.reset(blendDesc.writeMask); 2148*8975f5c5SAndroid Build Coastguard Worker } 2149*8975f5c5SAndroid Build Coastguard Worker } 2150*8975f5c5SAndroid Build Coastguard Worker invalidateRenderPipeline(); 2151*8975f5c5SAndroid Build Coastguard Worker} 2152*8975f5c5SAndroid Build Coastguard Worker 2153*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::updateScissor(const gl::State &glState) 2154*8975f5c5SAndroid Build Coastguard Worker{ 2155*8975f5c5SAndroid Build Coastguard Worker FramebufferMtl *framebufferMtl = mtl::GetImpl(glState.getDrawFramebuffer()); 2156*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle renderArea = framebufferMtl->getCompleteRenderArea(); 2157*8975f5c5SAndroid Build Coastguard Worker 2158*8975f5c5SAndroid Build Coastguard Worker ANGLE_MTL_LOG("renderArea = %d,%d,%d,%d", renderArea.x, renderArea.y, renderArea.width, 2159*8975f5c5SAndroid Build Coastguard Worker renderArea.height); 2160*8975f5c5SAndroid Build Coastguard Worker 2161*8975f5c5SAndroid Build Coastguard Worker // Clip the render area to the viewport. 2162*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle viewportClippedRenderArea; 2163*8975f5c5SAndroid Build Coastguard Worker if (!gl::ClipRectangle(renderArea, glState.getViewport(), &viewportClippedRenderArea)) 2164*8975f5c5SAndroid Build Coastguard Worker { 2165*8975f5c5SAndroid Build Coastguard Worker viewportClippedRenderArea = gl::Rectangle(); 2166*8975f5c5SAndroid Build Coastguard Worker } 2167*8975f5c5SAndroid Build Coastguard Worker 2168*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle scissoredArea = ClipRectToScissor(getState(), viewportClippedRenderArea, false); 2169*8975f5c5SAndroid Build Coastguard Worker if (framebufferMtl->flipY()) 2170*8975f5c5SAndroid Build Coastguard Worker { 2171*8975f5c5SAndroid Build Coastguard Worker scissoredArea.y = renderArea.height - scissoredArea.y - scissoredArea.height; 2172*8975f5c5SAndroid Build Coastguard Worker } 2173*8975f5c5SAndroid Build Coastguard Worker 2174*8975f5c5SAndroid Build Coastguard Worker ANGLE_MTL_LOG("scissoredArea = %d,%d,%d,%d", scissoredArea.x, scissoredArea.y, 2175*8975f5c5SAndroid Build Coastguard Worker scissoredArea.width, scissoredArea.height); 2176*8975f5c5SAndroid Build Coastguard Worker 2177*8975f5c5SAndroid Build Coastguard Worker mScissorRect = mtl::GetScissorRect(scissoredArea); 2178*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_SCISSOR); 2179*8975f5c5SAndroid Build Coastguard Worker} 2180*8975f5c5SAndroid Build Coastguard Worker 2181*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::updateCullMode(const gl::State &glState) 2182*8975f5c5SAndroid Build Coastguard Worker{ 2183*8975f5c5SAndroid Build Coastguard Worker const gl::RasterizerState &rasterState = glState.getRasterizerState(); 2184*8975f5c5SAndroid Build Coastguard Worker 2185*8975f5c5SAndroid Build Coastguard Worker mCullAllPolygons = false; 2186*8975f5c5SAndroid Build Coastguard Worker if (!rasterState.cullFace) 2187*8975f5c5SAndroid Build Coastguard Worker { 2188*8975f5c5SAndroid Build Coastguard Worker mCullMode = MTLCullModeNone; 2189*8975f5c5SAndroid Build Coastguard Worker } 2190*8975f5c5SAndroid Build Coastguard Worker else 2191*8975f5c5SAndroid Build Coastguard Worker { 2192*8975f5c5SAndroid Build Coastguard Worker switch (rasterState.cullMode) 2193*8975f5c5SAndroid Build Coastguard Worker { 2194*8975f5c5SAndroid Build Coastguard Worker case gl::CullFaceMode::Back: 2195*8975f5c5SAndroid Build Coastguard Worker mCullMode = MTLCullModeBack; 2196*8975f5c5SAndroid Build Coastguard Worker break; 2197*8975f5c5SAndroid Build Coastguard Worker case gl::CullFaceMode::Front: 2198*8975f5c5SAndroid Build Coastguard Worker mCullMode = MTLCullModeFront; 2199*8975f5c5SAndroid Build Coastguard Worker break; 2200*8975f5c5SAndroid Build Coastguard Worker case gl::CullFaceMode::FrontAndBack: 2201*8975f5c5SAndroid Build Coastguard Worker mCullAllPolygons = true; 2202*8975f5c5SAndroid Build Coastguard Worker break; 2203*8975f5c5SAndroid Build Coastguard Worker default: 2204*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE(); 2205*8975f5c5SAndroid Build Coastguard Worker break; 2206*8975f5c5SAndroid Build Coastguard Worker } 2207*8975f5c5SAndroid Build Coastguard Worker } 2208*8975f5c5SAndroid Build Coastguard Worker 2209*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_CULL_MODE); 2210*8975f5c5SAndroid Build Coastguard Worker} 2211*8975f5c5SAndroid Build Coastguard Worker 2212*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::updateFrontFace(const gl::State &glState) 2213*8975f5c5SAndroid Build Coastguard Worker{ 2214*8975f5c5SAndroid Build Coastguard Worker FramebufferMtl *framebufferMtl = mtl::GetImpl(glState.getDrawFramebuffer()); 2215*8975f5c5SAndroid Build Coastguard Worker const bool upperLeftOrigin = mState.getClipOrigin() == gl::ClipOrigin::UpperLeft; 2216*8975f5c5SAndroid Build Coastguard Worker mWinding = mtl::GetFrontfaceWinding(glState.getRasterizerState().frontFace, 2217*8975f5c5SAndroid Build Coastguard Worker framebufferMtl->flipY() == upperLeftOrigin); 2218*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_WINDING); 2219*8975f5c5SAndroid Build Coastguard Worker} 2220*8975f5c5SAndroid Build Coastguard Worker 2221*8975f5c5SAndroid Build Coastguard Worker// Index rewrite is required if: 2222*8975f5c5SAndroid Build Coastguard Worker// Provkoing vertex mode is 'last' 2223*8975f5c5SAndroid Build Coastguard Worker// Program has at least one 'flat' attribute 2224*8975f5c5SAndroid Build Coastguard Worker// PrimitiveMode is not POINTS. 2225*8975f5c5SAndroid Build Coastguard Workerbool ContextMtl::requiresIndexRewrite(const gl::State &state, gl::PrimitiveMode mode) 2226*8975f5c5SAndroid Build Coastguard Worker{ 2227*8975f5c5SAndroid Build Coastguard Worker return mode != gl::PrimitiveMode::Points && mExecutable->hasFlatAttribute() && 2228*8975f5c5SAndroid Build Coastguard Worker (state.getProvokingVertex() == gl::ProvokingVertexConvention::LastVertexConvention); 2229*8975f5c5SAndroid Build Coastguard Worker} 2230*8975f5c5SAndroid Build Coastguard Worker 2231*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::updateDrawFrameBufferBinding(const gl::Context *context) 2232*8975f5c5SAndroid Build Coastguard Worker{ 2233*8975f5c5SAndroid Build Coastguard Worker const gl::State &glState = getState(); 2234*8975f5c5SAndroid Build Coastguard Worker 2235*8975f5c5SAndroid Build Coastguard Worker FramebufferMtl *newDrawFramebuffer = mtl::GetImpl(glState.getDrawFramebuffer()); 2236*8975f5c5SAndroid Build Coastguard Worker if (newDrawFramebuffer != mDrawFramebuffer) 2237*8975f5c5SAndroid Build Coastguard Worker { 2238*8975f5c5SAndroid Build Coastguard Worker // Reset this flag if the framebuffer has changed to not sync it twice 2239*8975f5c5SAndroid Build Coastguard Worker mForceResyncDrawFramebuffer = false; 2240*8975f5c5SAndroid Build Coastguard Worker } 2241*8975f5c5SAndroid Build Coastguard Worker 2242*8975f5c5SAndroid Build Coastguard Worker mDrawFramebuffer = newDrawFramebuffer; 2243*8975f5c5SAndroid Build Coastguard Worker 2244*8975f5c5SAndroid Build Coastguard Worker mDrawFramebuffer->onStartedDrawingToFrameBuffer(context); 2245*8975f5c5SAndroid Build Coastguard Worker 2246*8975f5c5SAndroid Build Coastguard Worker onDrawFrameBufferChangedState(context, mDrawFramebuffer, true); 2247*8975f5c5SAndroid Build Coastguard Worker} 2248*8975f5c5SAndroid Build Coastguard Worker 2249*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::onDrawFrameBufferChangedState(const gl::Context *context, 2250*8975f5c5SAndroid Build Coastguard Worker FramebufferMtl *framebuffer, 2251*8975f5c5SAndroid Build Coastguard Worker bool renderPassChanged) 2252*8975f5c5SAndroid Build Coastguard Worker{ 2253*8975f5c5SAndroid Build Coastguard Worker const gl::State &glState = getState(); 2254*8975f5c5SAndroid Build Coastguard Worker ASSERT(framebuffer == mtl::GetImpl(glState.getDrawFramebuffer())); 2255*8975f5c5SAndroid Build Coastguard Worker 2256*8975f5c5SAndroid Build Coastguard Worker updateViewport(framebuffer, glState.getViewport(), glState.getNearPlane(), 2257*8975f5c5SAndroid Build Coastguard Worker glState.getFarPlane()); 2258*8975f5c5SAndroid Build Coastguard Worker updateFrontFace(glState); 2259*8975f5c5SAndroid Build Coastguard Worker updateScissor(glState); 2260*8975f5c5SAndroid Build Coastguard Worker 2261*8975f5c5SAndroid Build Coastguard Worker if (renderPassChanged) 2262*8975f5c5SAndroid Build Coastguard Worker { 2263*8975f5c5SAndroid Build Coastguard Worker // End any render encoding using the old render pass. 2264*8975f5c5SAndroid Build Coastguard Worker endEncoding(false); 2265*8975f5c5SAndroid Build Coastguard Worker // Need to re-apply state to RenderCommandEncoder 2266*8975f5c5SAndroid Build Coastguard Worker invalidateState(context); 2267*8975f5c5SAndroid Build Coastguard Worker } 2268*8975f5c5SAndroid Build Coastguard Worker else 2269*8975f5c5SAndroid Build Coastguard Worker { 2270*8975f5c5SAndroid Build Coastguard Worker // Invalidate current pipeline only. 2271*8975f5c5SAndroid Build Coastguard Worker invalidateRenderPipeline(); 2272*8975f5c5SAndroid Build Coastguard Worker } 2273*8975f5c5SAndroid Build Coastguard Worker} 2274*8975f5c5SAndroid Build Coastguard Worker 2275*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::onBackbufferResized(const gl::Context *context, WindowSurfaceMtl *backbuffer) 2276*8975f5c5SAndroid Build Coastguard Worker{ 2277*8975f5c5SAndroid Build Coastguard Worker const gl::State &glState = getState(); 2278*8975f5c5SAndroid Build Coastguard Worker FramebufferMtl *framebuffer = mtl::GetImpl(glState.getDrawFramebuffer()); 2279*8975f5c5SAndroid Build Coastguard Worker if (framebuffer->getAttachedBackbuffer() != backbuffer) 2280*8975f5c5SAndroid Build Coastguard Worker { 2281*8975f5c5SAndroid Build Coastguard Worker return; 2282*8975f5c5SAndroid Build Coastguard Worker } 2283*8975f5c5SAndroid Build Coastguard Worker 2284*8975f5c5SAndroid Build Coastguard Worker onDrawFrameBufferChangedState(context, framebuffer, true); 2285*8975f5c5SAndroid Build Coastguard Worker} 2286*8975f5c5SAndroid Build Coastguard Worker 2287*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::onOcclusionQueryBegin(const gl::Context *context, QueryMtl *query) 2288*8975f5c5SAndroid Build Coastguard Worker{ 2289*8975f5c5SAndroid Build Coastguard Worker ASSERT(mOcclusionQuery == nullptr); 2290*8975f5c5SAndroid Build Coastguard Worker mOcclusionQuery = query; 2291*8975f5c5SAndroid Build Coastguard Worker 2292*8975f5c5SAndroid Build Coastguard Worker if (mRenderEncoder.valid()) 2293*8975f5c5SAndroid Build Coastguard Worker { 2294*8975f5c5SAndroid Build Coastguard Worker // if render pass has started, start the query in the encoder 2295*8975f5c5SAndroid Build Coastguard Worker return startOcclusionQueryInRenderPass(query, true); 2296*8975f5c5SAndroid Build Coastguard Worker } 2297*8975f5c5SAndroid Build Coastguard Worker else 2298*8975f5c5SAndroid Build Coastguard Worker { 2299*8975f5c5SAndroid Build Coastguard Worker query->resetVisibilityResult(this); 2300*8975f5c5SAndroid Build Coastguard Worker } 2301*8975f5c5SAndroid Build Coastguard Worker 2302*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 2303*8975f5c5SAndroid Build Coastguard Worker} 2304*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::onOcclusionQueryEnd(const gl::Context *context, QueryMtl *query) 2305*8975f5c5SAndroid Build Coastguard Worker{ 2306*8975f5c5SAndroid Build Coastguard Worker ASSERT(mOcclusionQuery == query); 2307*8975f5c5SAndroid Build Coastguard Worker 2308*8975f5c5SAndroid Build Coastguard Worker if (mRenderEncoder.valid()) 2309*8975f5c5SAndroid Build Coastguard Worker { 2310*8975f5c5SAndroid Build Coastguard Worker // if render pass has started, end the query in the encoder 2311*8975f5c5SAndroid Build Coastguard Worker disableActiveOcclusionQueryInRenderPass(); 2312*8975f5c5SAndroid Build Coastguard Worker } 2313*8975f5c5SAndroid Build Coastguard Worker 2314*8975f5c5SAndroid Build Coastguard Worker mOcclusionQuery = nullptr; 2315*8975f5c5SAndroid Build Coastguard Worker} 2316*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::onOcclusionQueryDestroy(const gl::Context *context, QueryMtl *query) 2317*8975f5c5SAndroid Build Coastguard Worker{ 2318*8975f5c5SAndroid Build Coastguard Worker if (query->getAllocatedVisibilityOffsets().empty()) 2319*8975f5c5SAndroid Build Coastguard Worker { 2320*8975f5c5SAndroid Build Coastguard Worker return; 2321*8975f5c5SAndroid Build Coastguard Worker } 2322*8975f5c5SAndroid Build Coastguard Worker if (mOcclusionQuery == query) 2323*8975f5c5SAndroid Build Coastguard Worker { 2324*8975f5c5SAndroid Build Coastguard Worker onOcclusionQueryEnd(context, query); 2325*8975f5c5SAndroid Build Coastguard Worker } 2326*8975f5c5SAndroid Build Coastguard Worker mOcclusionQueryPool.deallocateQueryOffset(this, query); 2327*8975f5c5SAndroid Build Coastguard Worker} 2328*8975f5c5SAndroid Build Coastguard Worker 2329*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::disableActiveOcclusionQueryInRenderPass() 2330*8975f5c5SAndroid Build Coastguard Worker{ 2331*8975f5c5SAndroid Build Coastguard Worker if (!mOcclusionQuery || mOcclusionQuery->getAllocatedVisibilityOffsets().empty()) 2332*8975f5c5SAndroid Build Coastguard Worker { 2333*8975f5c5SAndroid Build Coastguard Worker return; 2334*8975f5c5SAndroid Build Coastguard Worker } 2335*8975f5c5SAndroid Build Coastguard Worker 2336*8975f5c5SAndroid Build Coastguard Worker ASSERT(mRenderEncoder.valid()); 2337*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.setVisibilityResultMode(MTLVisibilityResultModeDisabled, 2338*8975f5c5SAndroid Build Coastguard Worker mOcclusionQuery->getAllocatedVisibilityOffsets().back()); 2339*8975f5c5SAndroid Build Coastguard Worker} 2340*8975f5c5SAndroid Build Coastguard Worker 2341*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::restartActiveOcclusionQueryInRenderPass() 2342*8975f5c5SAndroid Build Coastguard Worker{ 2343*8975f5c5SAndroid Build Coastguard Worker if (!mOcclusionQuery || mOcclusionQuery->getAllocatedVisibilityOffsets().empty()) 2344*8975f5c5SAndroid Build Coastguard Worker { 2345*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 2346*8975f5c5SAndroid Build Coastguard Worker } 2347*8975f5c5SAndroid Build Coastguard Worker 2348*8975f5c5SAndroid Build Coastguard Worker return startOcclusionQueryInRenderPass(mOcclusionQuery, false); 2349*8975f5c5SAndroid Build Coastguard Worker} 2350*8975f5c5SAndroid Build Coastguard Worker 2351*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::startOcclusionQueryInRenderPass(QueryMtl *query, bool clearOldValue) 2352*8975f5c5SAndroid Build Coastguard Worker{ 2353*8975f5c5SAndroid Build Coastguard Worker ASSERT(mRenderEncoder.valid()); 2354*8975f5c5SAndroid Build Coastguard Worker 2355*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mOcclusionQueryPool.allocateQueryOffset(this, query, clearOldValue)); 2356*8975f5c5SAndroid Build Coastguard Worker 2357*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.setVisibilityResultMode(MTLVisibilityResultModeBoolean, 2358*8975f5c5SAndroid Build Coastguard Worker query->getAllocatedVisibilityOffsets().back()); 2359*8975f5c5SAndroid Build Coastguard Worker 2360*8975f5c5SAndroid Build Coastguard Worker // We need to mark the query's buffer as being written in this command buffer now. Since the 2361*8975f5c5SAndroid Build Coastguard Worker // actual writing is deferred until the render pass ends and user could try to read the query 2362*8975f5c5SAndroid Build Coastguard Worker // result before the render pass ends. 2363*8975f5c5SAndroid Build Coastguard Worker mCmdBuffer.setWriteDependency(query->getVisibilityResultBuffer(), /*isRenderCommand=*/true); 2364*8975f5c5SAndroid Build Coastguard Worker 2365*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 2366*8975f5c5SAndroid Build Coastguard Worker} 2367*8975f5c5SAndroid Build Coastguard Worker 2368*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::onTransformFeedbackActive(const gl::Context *context, TransformFeedbackMtl *xfb) 2369*8975f5c5SAndroid Build Coastguard Worker{ 2370*8975f5c5SAndroid Build Coastguard Worker // NOTE(hqle): We have to end current render pass to enable synchronization before XFB 2371*8975f5c5SAndroid Build Coastguard Worker // buffers could be used as vertex input. Consider a better approach. 2372*8975f5c5SAndroid Build Coastguard Worker endEncoding(true); 2373*8975f5c5SAndroid Build Coastguard Worker} 2374*8975f5c5SAndroid Build Coastguard Worker 2375*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::onTransformFeedbackInactive(const gl::Context *context, TransformFeedbackMtl *xfb) 2376*8975f5c5SAndroid Build Coastguard Worker{ 2377*8975f5c5SAndroid Build Coastguard Worker // NOTE(hqle): We have to end current render pass to enable synchronization before XFB 2378*8975f5c5SAndroid Build Coastguard Worker // buffers could be used as vertex input. Consider a better approach. 2379*8975f5c5SAndroid Build Coastguard Worker endEncoding(true); 2380*8975f5c5SAndroid Build Coastguard Worker} 2381*8975f5c5SAndroid Build Coastguard Worker 2382*8975f5c5SAndroid Build Coastguard Workeruint64_t ContextMtl::queueEventSignal(id<MTLEvent> event, uint64_t value) 2383*8975f5c5SAndroid Build Coastguard Worker{ 2384*8975f5c5SAndroid Build Coastguard Worker ensureCommandBufferReady(); 2385*8975f5c5SAndroid Build Coastguard Worker // Event is queued to be signaled after current render pass. If we have helper blit or 2386*8975f5c5SAndroid Build Coastguard Worker // compute encoders, avoid queueing by stopping them immediately so we get to insert the event 2387*8975f5c5SAndroid Build Coastguard Worker // right away. 2388*8975f5c5SAndroid Build Coastguard Worker endBlitAndComputeEncoding(); 2389*8975f5c5SAndroid Build Coastguard Worker return mCmdBuffer.queueEventSignal(event, value); 2390*8975f5c5SAndroid Build Coastguard Worker} 2391*8975f5c5SAndroid Build Coastguard Worker 2392*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::serverWaitEvent(id<MTLEvent> event, uint64_t value) 2393*8975f5c5SAndroid Build Coastguard Worker{ 2394*8975f5c5SAndroid Build Coastguard Worker ensureCommandBufferReady(); 2395*8975f5c5SAndroid Build Coastguard Worker 2396*8975f5c5SAndroid Build Coastguard Worker // Event waiting cannot be encoded if there is active encoder. 2397*8975f5c5SAndroid Build Coastguard Worker endEncoding(true); 2398*8975f5c5SAndroid Build Coastguard Worker 2399*8975f5c5SAndroid Build Coastguard Worker mCmdBuffer.serverWaitEvent(event, value); 2400*8975f5c5SAndroid Build Coastguard Worker} 2401*8975f5c5SAndroid Build Coastguard Worker 2402*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::updateProgramExecutable(const gl::Context *context) 2403*8975f5c5SAndroid Build Coastguard Worker{ 2404*8975f5c5SAndroid Build Coastguard Worker // Need to rebind textures 2405*8975f5c5SAndroid Build Coastguard Worker invalidateCurrentTextures(); 2406*8975f5c5SAndroid Build Coastguard Worker // Need to re-upload default attributes 2407*8975f5c5SAndroid Build Coastguard Worker invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask()); 2408*8975f5c5SAndroid Build Coastguard Worker // Render pipeline need to be re-applied 2409*8975f5c5SAndroid Build Coastguard Worker invalidateRenderPipeline(); 2410*8975f5c5SAndroid Build Coastguard Worker} 2411*8975f5c5SAndroid Build Coastguard Worker 2412*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::updateVertexArray(const gl::Context *context) 2413*8975f5c5SAndroid Build Coastguard Worker{ 2414*8975f5c5SAndroid Build Coastguard Worker const gl::State &glState = getState(); 2415*8975f5c5SAndroid Build Coastguard Worker mVertexArray = mtl::GetImpl(glState.getVertexArray()); 2416*8975f5c5SAndroid Build Coastguard Worker invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask()); 2417*8975f5c5SAndroid Build Coastguard Worker invalidateRenderPipeline(); 2418*8975f5c5SAndroid Build Coastguard Worker} 2419*8975f5c5SAndroid Build Coastguard Worker 2420*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::updateDefaultAttribute(size_t attribIndex) 2421*8975f5c5SAndroid Build Coastguard Worker{ 2422*8975f5c5SAndroid Build Coastguard Worker const gl::State &glState = mState; 2423*8975f5c5SAndroid Build Coastguard Worker const gl::VertexAttribCurrentValueData &defaultValue = 2424*8975f5c5SAndroid Build Coastguard Worker glState.getVertexAttribCurrentValues()[attribIndex]; 2425*8975f5c5SAndroid Build Coastguard Worker 2426*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kDefaultGLAttributeValueSize = 2427*8975f5c5SAndroid Build Coastguard Worker sizeof(gl::VertexAttribCurrentValueData::Values); 2428*8975f5c5SAndroid Build Coastguard Worker 2429*8975f5c5SAndroid Build Coastguard Worker static_assert(kDefaultGLAttributeValueSize == mtl::kDefaultAttributeSize, 2430*8975f5c5SAndroid Build Coastguard Worker "Unexpected default attribute size"); 2431*8975f5c5SAndroid Build Coastguard Worker memcpy(mDefaultAttributes[attribIndex].values, &defaultValue.Values, 2432*8975f5c5SAndroid Build Coastguard Worker mtl::kDefaultAttributeSize); 2433*8975f5c5SAndroid Build Coastguard Worker 2434*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 2435*8975f5c5SAndroid Build Coastguard Worker} 2436*8975f5c5SAndroid Build Coastguard Worker 2437*8975f5c5SAndroid Build Coastguard Workerstatic bool isDrawNoOp(const mtl::RenderPipelineDesc &descriptor, 2438*8975f5c5SAndroid Build Coastguard Worker ContextMtl *context, 2439*8975f5c5SAndroid Build Coastguard Worker const mtl::ContextDevice &device) 2440*8975f5c5SAndroid Build Coastguard Worker{ 2441*8975f5c5SAndroid Build Coastguard Worker // Ensure there is at least one valid render target. 2442*8975f5c5SAndroid Build Coastguard Worker bool hasValidRenderTarget = false; 2443*8975f5c5SAndroid Build Coastguard Worker 2444*8975f5c5SAndroid Build Coastguard Worker const NSUInteger maxColorRenderTargets = GetMaxNumberOfRenderTargetsForDevice(device); 2445*8975f5c5SAndroid Build Coastguard Worker for (NSUInteger i = 0; i < maxColorRenderTargets; ++i) 2446*8975f5c5SAndroid Build Coastguard Worker { 2447*8975f5c5SAndroid Build Coastguard Worker const auto &colorAttachment = descriptor.outputDescriptor.colorAttachments[i]; 2448*8975f5c5SAndroid Build Coastguard Worker if (colorAttachment.pixelFormat != MTLPixelFormatInvalid) 2449*8975f5c5SAndroid Build Coastguard Worker { 2450*8975f5c5SAndroid Build Coastguard Worker hasValidRenderTarget = true; 2451*8975f5c5SAndroid Build Coastguard Worker break; 2452*8975f5c5SAndroid Build Coastguard Worker } 2453*8975f5c5SAndroid Build Coastguard Worker } 2454*8975f5c5SAndroid Build Coastguard Worker 2455*8975f5c5SAndroid Build Coastguard Worker if (!hasValidRenderTarget && 2456*8975f5c5SAndroid Build Coastguard Worker descriptor.outputDescriptor.depthAttachmentPixelFormat != MTLPixelFormatInvalid) 2457*8975f5c5SAndroid Build Coastguard Worker { 2458*8975f5c5SAndroid Build Coastguard Worker hasValidRenderTarget = true; 2459*8975f5c5SAndroid Build Coastguard Worker } 2460*8975f5c5SAndroid Build Coastguard Worker 2461*8975f5c5SAndroid Build Coastguard Worker if (!hasValidRenderTarget && 2462*8975f5c5SAndroid Build Coastguard Worker descriptor.outputDescriptor.stencilAttachmentPixelFormat != MTLPixelFormatInvalid) 2463*8975f5c5SAndroid Build Coastguard Worker { 2464*8975f5c5SAndroid Build Coastguard Worker hasValidRenderTarget = true; 2465*8975f5c5SAndroid Build Coastguard Worker } 2466*8975f5c5SAndroid Build Coastguard Worker 2467*8975f5c5SAndroid Build Coastguard Worker if (!hasValidRenderTarget) 2468*8975f5c5SAndroid Build Coastguard Worker { 2469*8975f5c5SAndroid Build Coastguard Worker FramebufferMtl *framebufferMtl = mtl::GetImpl(context->getState().getDrawFramebuffer()); 2470*8975f5c5SAndroid Build Coastguard Worker hasValidRenderTarget = framebufferMtl->renderPassHasDefaultWidthOrHeight(); 2471*8975f5c5SAndroid Build Coastguard Worker } 2472*8975f5c5SAndroid Build Coastguard Worker 2473*8975f5c5SAndroid Build Coastguard Worker // Draw is no op if there is no valid render target, and we're not in a 2474*8975f5c5SAndroid Build Coastguard Worker // rasterization-disabled draw. 2475*8975f5c5SAndroid Build Coastguard Worker 2476*8975f5c5SAndroid Build Coastguard Worker bool noRenderTarget = !hasValidRenderTarget; 2477*8975f5c5SAndroid Build Coastguard Worker bool rasterizationDisabled = !descriptor.rasterizationEnabled(); 2478*8975f5c5SAndroid Build Coastguard Worker return !rasterizationDisabled && noRenderTarget; 2479*8975f5c5SAndroid Build Coastguard Worker} 2480*8975f5c5SAndroid Build Coastguard Worker 2481*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::setupDraw(const gl::Context *context, 2482*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 2483*8975f5c5SAndroid Build Coastguard Worker GLint firstVertex, 2484*8975f5c5SAndroid Build Coastguard Worker GLsizei vertexOrIndexCount, 2485*8975f5c5SAndroid Build Coastguard Worker GLsizei instances, 2486*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType indexTypeOrNone, 2487*8975f5c5SAndroid Build Coastguard Worker const void *indices, 2488*8975f5c5SAndroid Build Coastguard Worker bool xfbPass, 2489*8975f5c5SAndroid Build Coastguard Worker bool *isNoOp) 2490*8975f5c5SAndroid Build Coastguard Worker{ 2491*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setupDrawImpl(context, mode, firstVertex, vertexOrIndexCount, instances, 2492*8975f5c5SAndroid Build Coastguard Worker indexTypeOrNone, indices, xfbPass, isNoOp)); 2493*8975f5c5SAndroid Build Coastguard Worker if (*isNoOp) 2494*8975f5c5SAndroid Build Coastguard Worker { 2495*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 2496*8975f5c5SAndroid Build Coastguard Worker } 2497*8975f5c5SAndroid Build Coastguard Worker if (!mRenderEncoder.valid()) 2498*8975f5c5SAndroid Build Coastguard Worker { 2499*8975f5c5SAndroid Build Coastguard Worker // Flush occurred during setup, due to running out of memory while setting up the render 2500*8975f5c5SAndroid Build Coastguard Worker // pass state. This would happen for example when there is no more space in the uniform 2501*8975f5c5SAndroid Build Coastguard Worker // buffers in the uniform buffer pool. The rendering would be flushed to free the uniform 2502*8975f5c5SAndroid Build Coastguard Worker // buffer memory for new usage. In this case, re-run the setup. 2503*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setupDrawImpl(context, mode, firstVertex, vertexOrIndexCount, instances, 2504*8975f5c5SAndroid Build Coastguard Worker indexTypeOrNone, indices, xfbPass, isNoOp)); 2505*8975f5c5SAndroid Build Coastguard Worker 2506*8975f5c5SAndroid Build Coastguard Worker if (*isNoOp) 2507*8975f5c5SAndroid Build Coastguard Worker { 2508*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 2509*8975f5c5SAndroid Build Coastguard Worker } 2510*8975f5c5SAndroid Build Coastguard Worker // Setup with flushed state should either produce a working encoder or fail with an error 2511*8975f5c5SAndroid Build Coastguard Worker // result. 2512*8975f5c5SAndroid Build Coastguard Worker ASSERT(mRenderEncoder.valid()); 2513*8975f5c5SAndroid Build Coastguard Worker } 2514*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 2515*8975f5c5SAndroid Build Coastguard Worker} 2516*8975f5c5SAndroid Build Coastguard Worker 2517*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::setupDrawImpl(const gl::Context *context, 2518*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode mode, 2519*8975f5c5SAndroid Build Coastguard Worker GLint firstVertex, 2520*8975f5c5SAndroid Build Coastguard Worker GLsizei vertexOrIndexCount, 2521*8975f5c5SAndroid Build Coastguard Worker GLsizei instances, 2522*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType indexTypeOrNone, 2523*8975f5c5SAndroid Build Coastguard Worker const void *indices, 2524*8975f5c5SAndroid Build Coastguard Worker bool xfbPass, 2525*8975f5c5SAndroid Build Coastguard Worker bool *isNoOp) 2526*8975f5c5SAndroid Build Coastguard Worker{ 2527*8975f5c5SAndroid Build Coastguard Worker ASSERT(mExecutable); 2528*8975f5c5SAndroid Build Coastguard Worker *isNoOp = false; 2529*8975f5c5SAndroid Build Coastguard Worker // instances=0 means no instanced draw. 2530*8975f5c5SAndroid Build Coastguard Worker GLsizei instanceCount = instances ? instances : 1; 2531*8975f5c5SAndroid Build Coastguard Worker 2532*8975f5c5SAndroid Build Coastguard Worker if (context->getStateCache().hasAnyActiveClientAttrib()) 2533*8975f5c5SAndroid Build Coastguard Worker { 2534*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mVertexArray->updateClientAttribs(context, firstVertex, vertexOrIndexCount, 2535*8975f5c5SAndroid Build Coastguard Worker instanceCount, indexTypeOrNone, indices)); 2536*8975f5c5SAndroid Build Coastguard Worker } 2537*8975f5c5SAndroid Build Coastguard Worker 2538*8975f5c5SAndroid Build Coastguard Worker // This must be called before render command encoder is started. 2539*8975f5c5SAndroid Build Coastguard Worker bool textureChanged = false; 2540*8975f5c5SAndroid Build Coastguard Worker if (mDirtyBits.test(DIRTY_BIT_TEXTURES)) 2541*8975f5c5SAndroid Build Coastguard Worker { 2542*8975f5c5SAndroid Build Coastguard Worker textureChanged = true; 2543*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(handleDirtyActiveTextures(context)); 2544*8975f5c5SAndroid Build Coastguard Worker } 2545*8975f5c5SAndroid Build Coastguard Worker 2546*8975f5c5SAndroid Build Coastguard Worker if (mDirtyBits.test(DIRTY_BIT_RASTERIZER_DISCARD)) 2547*8975f5c5SAndroid Build Coastguard Worker { 2548*8975f5c5SAndroid Build Coastguard Worker if (getState().isTransformFeedbackActiveUnpaused()) 2549*8975f5c5SAndroid Build Coastguard Worker { 2550*8975f5c5SAndroid Build Coastguard Worker // If XFB is active we need to reset render pass since we could use a dummy render 2551*8975f5c5SAndroid Build Coastguard Worker // target if only XFB is needed. 2552*8975f5c5SAndroid Build Coastguard Worker invalidateState(context); 2553*8975f5c5SAndroid Build Coastguard Worker } 2554*8975f5c5SAndroid Build Coastguard Worker else 2555*8975f5c5SAndroid Build Coastguard Worker { 2556*8975f5c5SAndroid Build Coastguard Worker invalidateRenderPipeline(); 2557*8975f5c5SAndroid Build Coastguard Worker } 2558*8975f5c5SAndroid Build Coastguard Worker } 2559*8975f5c5SAndroid Build Coastguard Worker 2560*8975f5c5SAndroid Build Coastguard Worker if (!mRenderEncoder.valid()) 2561*8975f5c5SAndroid Build Coastguard Worker { 2562*8975f5c5SAndroid Build Coastguard Worker // re-apply everything 2563*8975f5c5SAndroid Build Coastguard Worker invalidateState(context); 2564*8975f5c5SAndroid Build Coastguard Worker } 2565*8975f5c5SAndroid Build Coastguard Worker 2566*8975f5c5SAndroid Build Coastguard Worker if (mDirtyBits.test(DIRTY_BIT_DRAW_FRAMEBUFFER)) 2567*8975f5c5SAndroid Build Coastguard Worker { 2568*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(handleDirtyRenderPass(context)); 2569*8975f5c5SAndroid Build Coastguard Worker } 2570*8975f5c5SAndroid Build Coastguard Worker 2571*8975f5c5SAndroid Build Coastguard Worker if (mOcclusionQuery && mOcclusionQueryPool.getNumRenderPassAllocatedQueries() == 0) 2572*8975f5c5SAndroid Build Coastguard Worker { 2573*8975f5c5SAndroid Build Coastguard Worker // The occlusion query is still active, and a new render pass has started. 2574*8975f5c5SAndroid Build Coastguard Worker // We need to continue the querying process in the new render encoder. 2575*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(startOcclusionQueryInRenderPass(mOcclusionQuery, false)); 2576*8975f5c5SAndroid Build Coastguard Worker } 2577*8975f5c5SAndroid Build Coastguard Worker 2578*8975f5c5SAndroid Build Coastguard Worker bool isPipelineDescChanged; 2579*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(checkIfPipelineChanged(context, mode, xfbPass, &isPipelineDescChanged)); 2580*8975f5c5SAndroid Build Coastguard Worker 2581*8975f5c5SAndroid Build Coastguard Worker bool uniformBuffersDirty = false; 2582*8975f5c5SAndroid Build Coastguard Worker 2583*8975f5c5SAndroid Build Coastguard Worker if (IsTransformFeedbackOnly(getState())) 2584*8975f5c5SAndroid Build Coastguard Worker { 2585*8975f5c5SAndroid Build Coastguard Worker // Filter out unneeded dirty bits 2586*8975f5c5SAndroid Build Coastguard Worker filterOutXFBOnlyDirtyBits(context); 2587*8975f5c5SAndroid Build Coastguard Worker } 2588*8975f5c5SAndroid Build Coastguard Worker 2589*8975f5c5SAndroid Build Coastguard Worker for (size_t bit : mDirtyBits) 2590*8975f5c5SAndroid Build Coastguard Worker { 2591*8975f5c5SAndroid Build Coastguard Worker switch (bit) 2592*8975f5c5SAndroid Build Coastguard Worker { 2593*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_TEXTURES: 2594*8975f5c5SAndroid Build Coastguard Worker // Already handled. 2595*8975f5c5SAndroid Build Coastguard Worker break; 2596*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_DEFAULT_ATTRIBS: 2597*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(handleDirtyDefaultAttribs(context)); 2598*8975f5c5SAndroid Build Coastguard Worker break; 2599*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_DRIVER_UNIFORMS: 2600*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(handleDirtyDriverUniforms(context, firstVertex, vertexOrIndexCount)); 2601*8975f5c5SAndroid Build Coastguard Worker break; 2602*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_DEPTH_STENCIL_DESC: 2603*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(handleDirtyDepthStencilState(context)); 2604*8975f5c5SAndroid Build Coastguard Worker break; 2605*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_DEPTH_BIAS: 2606*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(handleDirtyDepthBias(context)); 2607*8975f5c5SAndroid Build Coastguard Worker break; 2608*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_DEPTH_CLIP_MODE: 2609*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.setDepthClipMode( 2610*8975f5c5SAndroid Build Coastguard Worker mState.isDepthClampEnabled() ? MTLDepthClipModeClamp : MTLDepthClipModeClip); 2611*8975f5c5SAndroid Build Coastguard Worker break; 2612*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_STENCIL_REF: 2613*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.setStencilRefVals(mStencilRefFront, mStencilRefBack); 2614*8975f5c5SAndroid Build Coastguard Worker break; 2615*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_BLEND_COLOR: 2616*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.setBlendColor( 2617*8975f5c5SAndroid Build Coastguard Worker mState.getBlendColor().red, mState.getBlendColor().green, 2618*8975f5c5SAndroid Build Coastguard Worker mState.getBlendColor().blue, mState.getBlendColor().alpha); 2619*8975f5c5SAndroid Build Coastguard Worker break; 2620*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_VIEWPORT: 2621*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.setViewport(mViewport); 2622*8975f5c5SAndroid Build Coastguard Worker break; 2623*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_SCISSOR: 2624*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.setScissorRect(mScissorRect); 2625*8975f5c5SAndroid Build Coastguard Worker break; 2626*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_DRAW_FRAMEBUFFER: 2627*8975f5c5SAndroid Build Coastguard Worker // Already handled. 2628*8975f5c5SAndroid Build Coastguard Worker break; 2629*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_CULL_MODE: 2630*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.setCullMode(mCullMode); 2631*8975f5c5SAndroid Build Coastguard Worker break; 2632*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_FILL_MODE: 2633*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.setTriangleFillMode(mState.getPolygonMode() == gl::PolygonMode::Fill 2634*8975f5c5SAndroid Build Coastguard Worker ? MTLTriangleFillModeFill 2635*8975f5c5SAndroid Build Coastguard Worker : MTLTriangleFillModeLines); 2636*8975f5c5SAndroid Build Coastguard Worker break; 2637*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_WINDING: 2638*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.setFrontFacingWinding(mWinding); 2639*8975f5c5SAndroid Build Coastguard Worker break; 2640*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_RENDER_PIPELINE: 2641*8975f5c5SAndroid Build Coastguard Worker // Already handled. See checkIfPipelineChanged(). 2642*8975f5c5SAndroid Build Coastguard Worker break; 2643*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_UNIFORM_BUFFERS_BINDING: 2644*8975f5c5SAndroid Build Coastguard Worker uniformBuffersDirty = true; 2645*8975f5c5SAndroid Build Coastguard Worker break; 2646*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_RASTERIZER_DISCARD: 2647*8975f5c5SAndroid Build Coastguard Worker // Already handled. 2648*8975f5c5SAndroid Build Coastguard Worker break; 2649*8975f5c5SAndroid Build Coastguard Worker default: 2650*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE(); 2651*8975f5c5SAndroid Build Coastguard Worker break; 2652*8975f5c5SAndroid Build Coastguard Worker } 2653*8975f5c5SAndroid Build Coastguard Worker } 2654*8975f5c5SAndroid Build Coastguard Worker 2655*8975f5c5SAndroid Build Coastguard Worker if (xfbPass && !mDirtyBits.test(DIRTY_BIT_DRIVER_UNIFORMS)) 2656*8975f5c5SAndroid Build Coastguard Worker { 2657*8975f5c5SAndroid Build Coastguard Worker // If handleDirtyDriverUniforms() was not called and this is XFB pass, we still need to 2658*8975f5c5SAndroid Build Coastguard Worker // update XFB related uniforms 2659*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY( 2660*8975f5c5SAndroid Build Coastguard Worker fillDriverXFBUniforms(firstVertex, vertexOrIndexCount, /** skippedInstances */ 0)); 2661*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.setVertexData(mDriverUniforms, mtl::kDriverUniformsBindingIndex); 2662*8975f5c5SAndroid Build Coastguard Worker } 2663*8975f5c5SAndroid Build Coastguard Worker 2664*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.reset(); 2665*8975f5c5SAndroid Build Coastguard Worker // Check to see if our state would lead to a no-op draw. 2666*8975f5c5SAndroid Build Coastguard Worker // If so, skip program setup until we end up with a state that requires a program. 2667*8975f5c5SAndroid Build Coastguard Worker if (isDrawNoOp(mRenderPipelineDesc, this, mContextDevice)) 2668*8975f5c5SAndroid Build Coastguard Worker { 2669*8975f5c5SAndroid Build Coastguard Worker *isNoOp = true; 2670*8975f5c5SAndroid Build Coastguard Worker } 2671*8975f5c5SAndroid Build Coastguard Worker else 2672*8975f5c5SAndroid Build Coastguard Worker { 2673*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mExecutable->setupDraw(context, &mRenderEncoder, mRenderPipelineDesc, 2674*8975f5c5SAndroid Build Coastguard Worker isPipelineDescChanged, textureChanged, 2675*8975f5c5SAndroid Build Coastguard Worker uniformBuffersDirty)); 2676*8975f5c5SAndroid Build Coastguard Worker } 2677*8975f5c5SAndroid Build Coastguard Worker 2678*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 2679*8975f5c5SAndroid Build Coastguard Worker} 2680*8975f5c5SAndroid Build Coastguard Worker 2681*8975f5c5SAndroid Build Coastguard Workervoid ContextMtl::filterOutXFBOnlyDirtyBits(const gl::Context *context) 2682*8975f5c5SAndroid Build Coastguard Worker{ 2683*8975f5c5SAndroid Build Coastguard Worker ASSERT(IsTransformFeedbackOnly(getState())); 2684*8975f5c5SAndroid Build Coastguard Worker 2685*8975f5c5SAndroid Build Coastguard Worker ASSERT(mRenderEncoder.renderPassDesc().colorAttachments[0].texture == mDummyXFBRenderTexture); 2686*8975f5c5SAndroid Build Coastguard Worker 2687*8975f5c5SAndroid Build Coastguard Worker // In transform feedback only pass, only vertex shader's related states are needed. 2688*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kUnneededBits = 2689*8975f5c5SAndroid Build Coastguard Worker angle::Bit<size_t>(DIRTY_BIT_DEPTH_STENCIL_DESC) | 2690*8975f5c5SAndroid Build Coastguard Worker angle::Bit<size_t>(DIRTY_BIT_DEPTH_BIAS) | angle::Bit<size_t>(DIRTY_BIT_STENCIL_REF) | 2691*8975f5c5SAndroid Build Coastguard Worker angle::Bit<size_t>(DIRTY_BIT_BLEND_COLOR) | angle::Bit<size_t>(DIRTY_BIT_VIEWPORT) | 2692*8975f5c5SAndroid Build Coastguard Worker angle::Bit<size_t>(DIRTY_BIT_SCISSOR) | angle::Bit<size_t>(DIRTY_BIT_CULL_MODE) | 2693*8975f5c5SAndroid Build Coastguard Worker angle::Bit<size_t>(DIRTY_BIT_FILL_MODE) | angle::Bit<size_t>(DIRTY_BIT_WINDING); 2694*8975f5c5SAndroid Build Coastguard Worker 2695*8975f5c5SAndroid Build Coastguard Worker mDirtyBits &= ~kUnneededBits; 2696*8975f5c5SAndroid Build Coastguard Worker} 2697*8975f5c5SAndroid Build Coastguard Worker 2698*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::handleDirtyRenderPass(const gl::Context *context) 2699*8975f5c5SAndroid Build Coastguard Worker{ 2700*8975f5c5SAndroid Build Coastguard Worker if (!IsTransformFeedbackOnly(mState)) 2701*8975f5c5SAndroid Build Coastguard Worker { 2702*8975f5c5SAndroid Build Coastguard Worker // Start new render command encoder 2703*8975f5c5SAndroid Build Coastguard Worker mtl::RenderCommandEncoder *encoder; 2704*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mDrawFramebuffer->ensureRenderPassStarted(context, &encoder)); 2705*8975f5c5SAndroid Build Coastguard Worker } 2706*8975f5c5SAndroid Build Coastguard Worker else 2707*8975f5c5SAndroid Build Coastguard Worker { 2708*8975f5c5SAndroid Build Coastguard Worker // XFB is active and rasterization is disabled. Use dummy render target. 2709*8975f5c5SAndroid Build Coastguard Worker // We currently need to end the render pass when XFB is activated/deactivated so using 2710*8975f5c5SAndroid Build Coastguard Worker // a small dummy render target would make the render pass ending very cheap. 2711*8975f5c5SAndroid Build Coastguard Worker if (!mDummyXFBRenderTexture) 2712*8975f5c5SAndroid Build Coastguard Worker { 2713*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mtl::Texture::Make2DTexture(this, 2714*8975f5c5SAndroid Build Coastguard Worker getPixelFormat(angle::FormatID::R8G8B8A8_UNORM), 2715*8975f5c5SAndroid Build Coastguard Worker 1, 1, 1, true, false, &mDummyXFBRenderTexture)); 2716*8975f5c5SAndroid Build Coastguard Worker } 2717*8975f5c5SAndroid Build Coastguard Worker mtl::RenderCommandEncoder *encoder = getTextureRenderCommandEncoder( 2718*8975f5c5SAndroid Build Coastguard Worker mDummyXFBRenderTexture, 2719*8975f5c5SAndroid Build Coastguard Worker mtl::ImageNativeIndex::FromBaseZeroGLIndex(gl::ImageIndex::Make2D(0))); 2720*8975f5c5SAndroid Build Coastguard Worker encoder->setColorLoadAction(MTLLoadActionDontCare, MTLClearColor(), 0); 2721*8975f5c5SAndroid Build Coastguard Worker encoder->setColorStoreAction(MTLStoreActionDontCare); 2722*8975f5c5SAndroid Build Coastguard Worker 2723*8975f5c5SAndroid Build Coastguard Worker#ifndef NDEBUG 2724*8975f5c5SAndroid Build Coastguard Worker encoder->setLabel(@"TransformFeedbackOnlyPass"); 2725*8975f5c5SAndroid Build Coastguard Worker#endif 2726*8975f5c5SAndroid Build Coastguard Worker } 2727*8975f5c5SAndroid Build Coastguard Worker 2728*8975f5c5SAndroid Build Coastguard Worker // re-apply everything 2729*8975f5c5SAndroid Build Coastguard Worker invalidateState(context); 2730*8975f5c5SAndroid Build Coastguard Worker 2731*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 2732*8975f5c5SAndroid Build Coastguard Worker} 2733*8975f5c5SAndroid Build Coastguard Worker 2734*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::handleDirtyActiveTextures(const gl::Context *context) 2735*8975f5c5SAndroid Build Coastguard Worker{ 2736*8975f5c5SAndroid Build Coastguard Worker const gl::State &glState = mState; 2737*8975f5c5SAndroid Build Coastguard Worker const gl::ProgramExecutable *executable = glState.getProgramExecutable(); 2738*8975f5c5SAndroid Build Coastguard Worker 2739*8975f5c5SAndroid Build Coastguard Worker constexpr auto ensureTextureStorageCreated = [](const gl::Context *context, 2740*8975f5c5SAndroid Build Coastguard Worker gl::Texture *texture) -> angle::Result { 2741*8975f5c5SAndroid Build Coastguard Worker if (texture == nullptr) 2742*8975f5c5SAndroid Build Coastguard Worker { 2743*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 2744*8975f5c5SAndroid Build Coastguard Worker } 2745*8975f5c5SAndroid Build Coastguard Worker 2746*8975f5c5SAndroid Build Coastguard Worker TextureMtl *textureMtl = mtl::GetImpl(texture); 2747*8975f5c5SAndroid Build Coastguard Worker 2748*8975f5c5SAndroid Build Coastguard Worker // Make sure texture's image definitions will be transferred to GPU. 2749*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(textureMtl->ensureNativeStorageCreated(context)); 2750*8975f5c5SAndroid Build Coastguard Worker 2751*8975f5c5SAndroid Build Coastguard Worker // The binding of this texture will be done by ProgramMtl. 2752*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 2753*8975f5c5SAndroid Build Coastguard Worker }; 2754*8975f5c5SAndroid Build Coastguard Worker 2755*8975f5c5SAndroid Build Coastguard Worker const gl::ActiveTexturesCache &textures = glState.getActiveTexturesCache(); 2756*8975f5c5SAndroid Build Coastguard Worker const gl::ActiveTextureMask &activeTextures = executable->getActiveSamplersMask(); 2757*8975f5c5SAndroid Build Coastguard Worker 2758*8975f5c5SAndroid Build Coastguard Worker for (size_t textureUnit : activeTextures) 2759*8975f5c5SAndroid Build Coastguard Worker { 2760*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureTextureStorageCreated(context, textures[textureUnit])); 2761*8975f5c5SAndroid Build Coastguard Worker } 2762*8975f5c5SAndroid Build Coastguard Worker 2763*8975f5c5SAndroid Build Coastguard Worker for (size_t imageUnit : executable->getActiveImagesMask()) 2764*8975f5c5SAndroid Build Coastguard Worker { 2765*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY( 2766*8975f5c5SAndroid Build Coastguard Worker ensureTextureStorageCreated(context, glState.getImageUnit(imageUnit).texture.get())); 2767*8975f5c5SAndroid Build Coastguard Worker } 2768*8975f5c5SAndroid Build Coastguard Worker 2769*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 2770*8975f5c5SAndroid Build Coastguard Worker} 2771*8975f5c5SAndroid Build Coastguard Worker 2772*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::handleDirtyDefaultAttribs(const gl::Context *context) 2773*8975f5c5SAndroid Build Coastguard Worker{ 2774*8975f5c5SAndroid Build Coastguard Worker for (size_t attribIndex : mDirtyDefaultAttribsMask) 2775*8975f5c5SAndroid Build Coastguard Worker { 2776*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(updateDefaultAttribute(attribIndex)); 2777*8975f5c5SAndroid Build Coastguard Worker } 2778*8975f5c5SAndroid Build Coastguard Worker 2779*8975f5c5SAndroid Build Coastguard Worker ASSERT(mRenderEncoder.valid()); 2780*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.setVertexData(mDefaultAttributes, mtl::kDefaultAttribsBindingIndex); 2781*8975f5c5SAndroid Build Coastguard Worker 2782*8975f5c5SAndroid Build Coastguard Worker mDirtyDefaultAttribsMask.reset(); 2783*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 2784*8975f5c5SAndroid Build Coastguard Worker} 2785*8975f5c5SAndroid Build Coastguard Worker 2786*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::handleDirtyDriverUniforms(const gl::Context *context, 2787*8975f5c5SAndroid Build Coastguard Worker GLint drawCallFirstVertex, 2788*8975f5c5SAndroid Build Coastguard Worker uint32_t verticesPerInstance) 2789*8975f5c5SAndroid Build Coastguard Worker{ 2790*8975f5c5SAndroid Build Coastguard Worker mDriverUniforms.depthRange[0] = mState.getNearPlane(); 2791*8975f5c5SAndroid Build Coastguard Worker mDriverUniforms.depthRange[1] = mState.getFarPlane(); 2792*8975f5c5SAndroid Build Coastguard Worker 2793*8975f5c5SAndroid Build Coastguard Worker mDriverUniforms.renderArea = mDrawFramebuffer->getState().getDimensions().height << 16 | 2794*8975f5c5SAndroid Build Coastguard Worker mDrawFramebuffer->getState().getDimensions().width; 2795*8975f5c5SAndroid Build Coastguard Worker 2796*8975f5c5SAndroid Build Coastguard Worker const float flipX = 1.0; 2797*8975f5c5SAndroid Build Coastguard Worker const float flipY = mDrawFramebuffer->flipY() ? -1.0f : 1.0f; 2798*8975f5c5SAndroid Build Coastguard Worker mDriverUniforms.flipXY = gl::PackSnorm4x8( 2799*8975f5c5SAndroid Build Coastguard Worker flipX, flipY, flipX, mState.getClipOrigin() == gl::ClipOrigin::LowerLeft ? -flipY : flipY); 2800*8975f5c5SAndroid Build Coastguard Worker 2801*8975f5c5SAndroid Build Coastguard Worker // gl_ClipDistance 2802*8975f5c5SAndroid Build Coastguard Worker const uint32_t enabledClipDistances = mState.getEnabledClipDistances().bits(); 2803*8975f5c5SAndroid Build Coastguard Worker ASSERT((enabledClipDistances & ~sh::vk::kDriverUniformsMiscEnabledClipPlanesMask) == 0); 2804*8975f5c5SAndroid Build Coastguard Worker 2805*8975f5c5SAndroid Build Coastguard Worker // GL_CLIP_DEPTH_MODE_EXT 2806*8975f5c5SAndroid Build Coastguard Worker const uint32_t transformDepth = !mState.isClipDepthModeZeroToOne(); 2807*8975f5c5SAndroid Build Coastguard Worker ASSERT((transformDepth & ~sh::vk::kDriverUniformsMiscTransformDepthMask) == 0); 2808*8975f5c5SAndroid Build Coastguard Worker 2809*8975f5c5SAndroid Build Coastguard Worker // GL_SAMPLE_ALPHA_TO_COVERAGE 2810*8975f5c5SAndroid Build Coastguard Worker const uint32_t alphaToCoverage = mState.isSampleAlphaToCoverageEnabled(); 2811*8975f5c5SAndroid Build Coastguard Worker ASSERT((alphaToCoverage & ~sh::vk::kDriverUniformsMiscAlphaToCoverageMask) == 0); 2812*8975f5c5SAndroid Build Coastguard Worker 2813*8975f5c5SAndroid Build Coastguard Worker mDriverUniforms.misc = 2814*8975f5c5SAndroid Build Coastguard Worker (enabledClipDistances << sh::vk::kDriverUniformsMiscEnabledClipPlanesOffset) | 2815*8975f5c5SAndroid Build Coastguard Worker (transformDepth << sh::vk::kDriverUniformsMiscTransformDepthOffset) | 2816*8975f5c5SAndroid Build Coastguard Worker (alphaToCoverage << sh::vk::kDriverUniformsMiscAlphaToCoverageOffset); 2817*8975f5c5SAndroid Build Coastguard Worker 2818*8975f5c5SAndroid Build Coastguard Worker // Sample coverage mask 2819*8975f5c5SAndroid Build Coastguard Worker if (mState.isSampleCoverageEnabled()) 2820*8975f5c5SAndroid Build Coastguard Worker { 2821*8975f5c5SAndroid Build Coastguard Worker const uint32_t sampleBitCount = mDrawFramebuffer->getSamples(); 2822*8975f5c5SAndroid Build Coastguard Worker ASSERT(sampleBitCount < 32); 2823*8975f5c5SAndroid Build Coastguard Worker const uint32_t coverageSampleBitCount = 2824*8975f5c5SAndroid Build Coastguard Worker static_cast<uint32_t>(std::round(mState.getSampleCoverageValue() * sampleBitCount)); 2825*8975f5c5SAndroid Build Coastguard Worker uint32_t coverageMask = (1u << coverageSampleBitCount) - 1; 2826*8975f5c5SAndroid Build Coastguard Worker if (mState.getSampleCoverageInvert()) 2827*8975f5c5SAndroid Build Coastguard Worker { 2828*8975f5c5SAndroid Build Coastguard Worker const uint32_t sampleMask = (1u << sampleBitCount) - 1; 2829*8975f5c5SAndroid Build Coastguard Worker coverageMask = sampleMask & (~coverageMask); 2830*8975f5c5SAndroid Build Coastguard Worker } 2831*8975f5c5SAndroid Build Coastguard Worker mDriverUniforms.coverageMask = coverageMask; 2832*8975f5c5SAndroid Build Coastguard Worker } 2833*8975f5c5SAndroid Build Coastguard Worker else 2834*8975f5c5SAndroid Build Coastguard Worker { 2835*8975f5c5SAndroid Build Coastguard Worker mDriverUniforms.coverageMask = 0xFFFFFFFFu; 2836*8975f5c5SAndroid Build Coastguard Worker } 2837*8975f5c5SAndroid Build Coastguard Worker 2838*8975f5c5SAndroid Build Coastguard Worker // Sample mask 2839*8975f5c5SAndroid Build Coastguard Worker if (mState.isSampleMaskEnabled()) 2840*8975f5c5SAndroid Build Coastguard Worker { 2841*8975f5c5SAndroid Build Coastguard Worker mDriverUniforms.coverageMask &= mState.getSampleMaskWord(0); 2842*8975f5c5SAndroid Build Coastguard Worker } 2843*8975f5c5SAndroid Build Coastguard Worker 2844*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY( 2845*8975f5c5SAndroid Build Coastguard Worker fillDriverXFBUniforms(drawCallFirstVertex, verticesPerInstance, /** skippedInstances */ 0)); 2846*8975f5c5SAndroid Build Coastguard Worker 2847*8975f5c5SAndroid Build Coastguard Worker ASSERT(mRenderEncoder.valid()); 2848*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.setFragmentData(mDriverUniforms, mtl::kDriverUniformsBindingIndex); 2849*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.setVertexData(mDriverUniforms, mtl::kDriverUniformsBindingIndex); 2850*8975f5c5SAndroid Build Coastguard Worker 2851*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 2852*8975f5c5SAndroid Build Coastguard Worker} 2853*8975f5c5SAndroid Build Coastguard Worker 2854*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::fillDriverXFBUniforms(GLint drawCallFirstVertex, 2855*8975f5c5SAndroid Build Coastguard Worker uint32_t verticesPerInstance, 2856*8975f5c5SAndroid Build Coastguard Worker uint32_t skippedInstances) 2857*8975f5c5SAndroid Build Coastguard Worker{ 2858*8975f5c5SAndroid Build Coastguard Worker gl::TransformFeedback *transformFeedback = getState().getCurrentTransformFeedback(); 2859*8975f5c5SAndroid Build Coastguard Worker 2860*8975f5c5SAndroid Build Coastguard Worker bool xfbActiveUnpaused = getState().isTransformFeedbackActiveUnpaused(); 2861*8975f5c5SAndroid Build Coastguard Worker if (!transformFeedback || !xfbActiveUnpaused) 2862*8975f5c5SAndroid Build Coastguard Worker { 2863*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 2864*8975f5c5SAndroid Build Coastguard Worker } 2865*8975f5c5SAndroid Build Coastguard Worker 2866*8975f5c5SAndroid Build Coastguard Worker mDriverUniforms.xfbVerticesPerInstance = verticesPerInstance; 2867*8975f5c5SAndroid Build Coastguard Worker 2868*8975f5c5SAndroid Build Coastguard Worker TransformFeedbackMtl *transformFeedbackMtl = mtl::GetImpl(transformFeedback); 2869*8975f5c5SAndroid Build Coastguard Worker 2870*8975f5c5SAndroid Build Coastguard Worker return transformFeedbackMtl->getBufferOffsets(this, drawCallFirstVertex, 2871*8975f5c5SAndroid Build Coastguard Worker verticesPerInstance * skippedInstances, 2872*8975f5c5SAndroid Build Coastguard Worker mDriverUniforms.xfbBufferOffsets); 2873*8975f5c5SAndroid Build Coastguard Worker} 2874*8975f5c5SAndroid Build Coastguard Worker 2875*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::handleDirtyDepthStencilState(const gl::Context *context) 2876*8975f5c5SAndroid Build Coastguard Worker{ 2877*8975f5c5SAndroid Build Coastguard Worker ASSERT(mRenderEncoder.valid()); 2878*8975f5c5SAndroid Build Coastguard Worker 2879*8975f5c5SAndroid Build Coastguard Worker // Need to handle the case when render pass doesn't have depth/stencil attachment. 2880*8975f5c5SAndroid Build Coastguard Worker mtl::DepthStencilDesc dsDesc = mDepthStencilDesc; 2881*8975f5c5SAndroid Build Coastguard Worker const mtl::RenderPassDesc &renderPassDesc = mRenderEncoder.renderPassDesc(); 2882*8975f5c5SAndroid Build Coastguard Worker 2883*8975f5c5SAndroid Build Coastguard Worker if (!renderPassDesc.depthAttachment.texture) 2884*8975f5c5SAndroid Build Coastguard Worker { 2885*8975f5c5SAndroid Build Coastguard Worker dsDesc.depthWriteEnabled = false; 2886*8975f5c5SAndroid Build Coastguard Worker dsDesc.depthCompareFunction = MTLCompareFunctionAlways; 2887*8975f5c5SAndroid Build Coastguard Worker } 2888*8975f5c5SAndroid Build Coastguard Worker 2889*8975f5c5SAndroid Build Coastguard Worker if (!renderPassDesc.stencilAttachment.texture) 2890*8975f5c5SAndroid Build Coastguard Worker { 2891*8975f5c5SAndroid Build Coastguard Worker dsDesc.frontFaceStencil.reset(); 2892*8975f5c5SAndroid Build Coastguard Worker dsDesc.backFaceStencil.reset(); 2893*8975f5c5SAndroid Build Coastguard Worker } 2894*8975f5c5SAndroid Build Coastguard Worker 2895*8975f5c5SAndroid Build Coastguard Worker // Apply depth stencil state 2896*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.setDepthStencilState( 2897*8975f5c5SAndroid Build Coastguard Worker getDisplay()->getStateCache().getDepthStencilState(getMetalDevice(), dsDesc)); 2898*8975f5c5SAndroid Build Coastguard Worker 2899*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 2900*8975f5c5SAndroid Build Coastguard Worker} 2901*8975f5c5SAndroid Build Coastguard Worker 2902*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::handleDirtyDepthBias(const gl::Context *context) 2903*8975f5c5SAndroid Build Coastguard Worker{ 2904*8975f5c5SAndroid Build Coastguard Worker const gl::RasterizerState &rasterState = mState.getRasterizerState(); 2905*8975f5c5SAndroid Build Coastguard Worker ASSERT(mRenderEncoder.valid()); 2906*8975f5c5SAndroid Build Coastguard Worker if (!mState.isPolygonOffsetEnabled()) 2907*8975f5c5SAndroid Build Coastguard Worker { 2908*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.setDepthBias(0, 0, 0); 2909*8975f5c5SAndroid Build Coastguard Worker } 2910*8975f5c5SAndroid Build Coastguard Worker else 2911*8975f5c5SAndroid Build Coastguard Worker { 2912*8975f5c5SAndroid Build Coastguard Worker mRenderEncoder.setDepthBias(rasterState.polygonOffsetUnits, rasterState.polygonOffsetFactor, 2913*8975f5c5SAndroid Build Coastguard Worker rasterState.polygonOffsetClamp); 2914*8975f5c5SAndroid Build Coastguard Worker } 2915*8975f5c5SAndroid Build Coastguard Worker 2916*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 2917*8975f5c5SAndroid Build Coastguard Worker} 2918*8975f5c5SAndroid Build Coastguard Worker 2919*8975f5c5SAndroid Build Coastguard Workerangle::Result ContextMtl::checkIfPipelineChanged(const gl::Context *context, 2920*8975f5c5SAndroid Build Coastguard Worker gl::PrimitiveMode primitiveMode, 2921*8975f5c5SAndroid Build Coastguard Worker bool xfbPass, 2922*8975f5c5SAndroid Build Coastguard Worker bool *isPipelineDescChanged) 2923*8975f5c5SAndroid Build Coastguard Worker{ 2924*8975f5c5SAndroid Build Coastguard Worker ASSERT(mRenderEncoder.valid()); 2925*8975f5c5SAndroid Build Coastguard Worker MTLPrimitiveTopologyClass topologyClass = mtl::GetPrimitiveTopologyClass(primitiveMode); 2926*8975f5c5SAndroid Build Coastguard Worker 2927*8975f5c5SAndroid Build Coastguard Worker bool rppChange = mDirtyBits.test(DIRTY_BIT_RENDER_PIPELINE) || 2928*8975f5c5SAndroid Build Coastguard Worker topologyClass != mRenderPipelineDesc.inputPrimitiveTopology; 2929*8975f5c5SAndroid Build Coastguard Worker 2930*8975f5c5SAndroid Build Coastguard Worker // Obtain RenderPipelineDesc's vertex array descriptor. 2931*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mVertexArray->setupDraw(context, &mRenderEncoder, &rppChange, 2932*8975f5c5SAndroid Build Coastguard Worker &mRenderPipelineDesc.vertexDescriptor)); 2933*8975f5c5SAndroid Build Coastguard Worker 2934*8975f5c5SAndroid Build Coastguard Worker if (rppChange) 2935*8975f5c5SAndroid Build Coastguard Worker { 2936*8975f5c5SAndroid Build Coastguard Worker const mtl::RenderPassDesc &renderPassDesc = mRenderEncoder.renderPassDesc(); 2937*8975f5c5SAndroid Build Coastguard Worker // Obtain RenderPipelineDesc's output descriptor. 2938*8975f5c5SAndroid Build Coastguard Worker renderPassDesc.populateRenderPipelineOutputDesc(mBlendDescArray, 2939*8975f5c5SAndroid Build Coastguard Worker &mRenderPipelineDesc.outputDescriptor); 2940*8975f5c5SAndroid Build Coastguard Worker 2941*8975f5c5SAndroid Build Coastguard Worker if (xfbPass) 2942*8975f5c5SAndroid Build Coastguard Worker { 2943*8975f5c5SAndroid Build Coastguard Worker // In XFB pass, we disable fragment shader. 2944*8975f5c5SAndroid Build Coastguard Worker mRenderPipelineDesc.rasterizationType = mtl::RenderPipelineRasterization::Disabled; 2945*8975f5c5SAndroid Build Coastguard Worker } 2946*8975f5c5SAndroid Build Coastguard Worker else if (mState.isRasterizerDiscardEnabled()) 2947*8975f5c5SAndroid Build Coastguard Worker { 2948*8975f5c5SAndroid Build Coastguard Worker // If XFB is not active and rasterizer discard is enabled, we need to emulate the 2949*8975f5c5SAndroid Build Coastguard Worker // discard. Because in this case, vertex shader might write to stage output values and 2950*8975f5c5SAndroid Build Coastguard Worker // Metal doesn't allow rasterization to be disabled. 2951*8975f5c5SAndroid Build Coastguard Worker mRenderPipelineDesc.rasterizationType = 2952*8975f5c5SAndroid Build Coastguard Worker mtl::RenderPipelineRasterization::EmulatedDiscard; 2953*8975f5c5SAndroid Build Coastguard Worker } 2954*8975f5c5SAndroid Build Coastguard Worker else 2955*8975f5c5SAndroid Build Coastguard Worker { 2956*8975f5c5SAndroid Build Coastguard Worker mRenderPipelineDesc.rasterizationType = mtl::RenderPipelineRasterization::Enabled; 2957*8975f5c5SAndroid Build Coastguard Worker } 2958*8975f5c5SAndroid Build Coastguard Worker mRenderPipelineDesc.inputPrimitiveTopology = topologyClass; 2959*8975f5c5SAndroid Build Coastguard Worker mRenderPipelineDesc.alphaToCoverageEnabled = 2960*8975f5c5SAndroid Build Coastguard Worker mState.isSampleAlphaToCoverageEnabled() && 2961*8975f5c5SAndroid Build Coastguard Worker mRenderPipelineDesc.outputDescriptor.rasterSampleCount > 1 && 2962*8975f5c5SAndroid Build Coastguard Worker !getDisplay()->getFeatures().emulateAlphaToCoverage.enabled; 2963*8975f5c5SAndroid Build Coastguard Worker 2964*8975f5c5SAndroid Build Coastguard Worker mRenderPipelineDesc.outputDescriptor.updateEnabledDrawBuffers( 2965*8975f5c5SAndroid Build Coastguard Worker mDrawFramebuffer->getState().getEnabledDrawBuffers()); 2966*8975f5c5SAndroid Build Coastguard Worker } 2967*8975f5c5SAndroid Build Coastguard Worker 2968*8975f5c5SAndroid Build Coastguard Worker *isPipelineDescChanged = rppChange; 2969*8975f5c5SAndroid Build Coastguard Worker 2970*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue; 2971*8975f5c5SAndroid Build Coastguard Worker} 2972*8975f5c5SAndroid Build Coastguard Worker 2973*8975f5c5SAndroid Build Coastguard Worker} // namespace rx 2974