• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ContextMtl.h:
7 //    Defines the class interface for ContextMtl, implementing ContextImpl.
8 //
9 
10 #ifndef LIBANGLE_RENDERER_METAL_CONTEXTMTL_H_
11 #define LIBANGLE_RENDERER_METAL_CONTEXTMTL_H_
12 
13 #import <Metal/Metal.h>
14 
15 #include "common/Optional.h"
16 #include "libANGLE/Context.h"
17 #include "libANGLE/renderer/ContextImpl.h"
18 #include "libANGLE/renderer/metal/mtl_buffer_pool.h"
19 #include "libANGLE/renderer/metal/mtl_command_buffer.h"
20 #include "libANGLE/renderer/metal/mtl_occlusion_query_pool.h"
21 #include "libANGLE/renderer/metal/mtl_resources.h"
22 #include "libANGLE/renderer/metal/mtl_state_cache.h"
23 #include "libANGLE/renderer/metal/mtl_utils.h"
24 
25 namespace rx
26 {
27 class DisplayMtl;
28 class FramebufferMtl;
29 class VertexArrayMtl;
30 class ProgramMtl;
31 class RenderTargetMtl;
32 class WindowSurfaceMtl;
33 class TransformFeedbackMtl;
34 
35 class ContextMtl : public ContextImpl, public mtl::Context
36 {
37   public:
38     ContextMtl(const gl::State &state, gl::ErrorSet *errorSet, DisplayMtl *display);
39     ~ContextMtl() override;
40 
41     angle::Result initialize() override;
42 
43     void onDestroy(const gl::Context *context) override;
44 
45     // Flush and finish.
46     angle::Result flush(const gl::Context *context) override;
47     angle::Result finish(const gl::Context *context) override;
48 
49     // Drawing methods.
50     angle::Result drawArrays(const gl::Context *context,
51                              gl::PrimitiveMode mode,
52                              GLint first,
53                              GLsizei count) override;
54     angle::Result drawArraysInstanced(const gl::Context *context,
55                                       gl::PrimitiveMode mode,
56                                       GLint first,
57                                       GLsizei count,
58                                       GLsizei instanceCount) override;
59     angle::Result drawArraysInstancedBaseInstance(const gl::Context *context,
60                                                   gl::PrimitiveMode mode,
61                                                   GLint first,
62                                                   GLsizei count,
63                                                   GLsizei instanceCount,
64                                                   GLuint baseInstance) override;
65 
66     angle::Result drawElements(const gl::Context *context,
67                                gl::PrimitiveMode mode,
68                                GLsizei count,
69                                gl::DrawElementsType type,
70                                const void *indices) override;
71     angle::Result drawElementsBaseVertex(const gl::Context *context,
72                                          gl::PrimitiveMode mode,
73                                          GLsizei count,
74                                          gl::DrawElementsType type,
75                                          const void *indices,
76                                          GLint baseVertex) override;
77     angle::Result drawElementsInstanced(const gl::Context *context,
78                                         gl::PrimitiveMode mode,
79                                         GLsizei count,
80                                         gl::DrawElementsType type,
81                                         const void *indices,
82                                         GLsizei instanceCount) override;
83     angle::Result drawElementsInstancedBaseVertex(const gl::Context *context,
84                                                   gl::PrimitiveMode mode,
85                                                   GLsizei count,
86                                                   gl::DrawElementsType type,
87                                                   const void *indices,
88                                                   GLsizei instanceCount,
89                                                   GLint baseVertex) override;
90     angle::Result drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
91                                                               gl::PrimitiveMode mode,
92                                                               GLsizei count,
93                                                               gl::DrawElementsType type,
94                                                               const void *indices,
95                                                               GLsizei instances,
96                                                               GLint baseVertex,
97                                                               GLuint baseInstance) override;
98     angle::Result drawRangeElements(const gl::Context *context,
99                                     gl::PrimitiveMode mode,
100                                     GLuint start,
101                                     GLuint end,
102                                     GLsizei count,
103                                     gl::DrawElementsType type,
104                                     const void *indices) override;
105     angle::Result drawRangeElementsBaseVertex(const gl::Context *context,
106                                               gl::PrimitiveMode mode,
107                                               GLuint start,
108                                               GLuint end,
109                                               GLsizei count,
110                                               gl::DrawElementsType type,
111                                               const void *indices,
112                                               GLint baseVertex) override;
113     angle::Result drawArraysIndirect(const gl::Context *context,
114                                      gl::PrimitiveMode mode,
115                                      const void *indirect) override;
116     angle::Result drawElementsIndirect(const gl::Context *context,
117                                        gl::PrimitiveMode mode,
118                                        gl::DrawElementsType type,
119                                        const void *indirect) override;
120     angle::Result multiDrawArrays(const gl::Context *context,
121                                   gl::PrimitiveMode mode,
122                                   const GLint *firsts,
123                                   const GLsizei *counts,
124                                   GLsizei drawcount) override;
125     angle::Result multiDrawArraysInstanced(const gl::Context *context,
126                                            gl::PrimitiveMode mode,
127                                            const GLint *firsts,
128                                            const GLsizei *counts,
129                                            const GLsizei *instanceCounts,
130                                            GLsizei drawcount) override;
131     angle::Result multiDrawElements(const gl::Context *context,
132                                     gl::PrimitiveMode mode,
133                                     const GLsizei *counts,
134                                     gl::DrawElementsType type,
135                                     const GLvoid *const *indices,
136                                     GLsizei drawcount) override;
137     angle::Result multiDrawElementsInstanced(const gl::Context *context,
138                                              gl::PrimitiveMode mode,
139                                              const GLsizei *counts,
140                                              gl::DrawElementsType type,
141                                              const GLvoid *const *indices,
142                                              const GLsizei *instanceCounts,
143                                              GLsizei drawcount) override;
144     angle::Result multiDrawArraysInstancedBaseInstance(const gl::Context *context,
145                                                        gl::PrimitiveMode mode,
146                                                        const GLint *firsts,
147                                                        const GLsizei *counts,
148                                                        const GLsizei *instanceCounts,
149                                                        const GLuint *baseInstances,
150                                                        GLsizei drawcount) override;
151     angle::Result multiDrawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
152                                                                    gl::PrimitiveMode mode,
153                                                                    const GLsizei *counts,
154                                                                    gl::DrawElementsType type,
155                                                                    const GLvoid *const *indices,
156                                                                    const GLsizei *instanceCounts,
157                                                                    const GLint *baseVertices,
158                                                                    const GLuint *baseInstances,
159                                                                    GLsizei drawcount) override;
160     angle::Result drawElementsSimpleTypesPrimitiveRestart(const gl::Context *context,
161                                                           gl::PrimitiveMode mode,
162                                                           GLsizei count,
163                                                           gl::DrawElementsType type,
164                                                           const void *indices,
165                                                           GLsizei instances);
166 
167     // Device loss
168     gl::GraphicsResetStatus getResetStatus() override;
169 
170     // EXT_debug_marker
171     angle::Result insertEventMarker(GLsizei length, const char *marker) override;
172     angle::Result pushGroupMarker(GLsizei length, const char *marker) override;
173     angle::Result popGroupMarker() override;
174 
175     // KHR_debug
176     angle::Result pushDebugGroup(const gl::Context *context,
177                                  GLenum source,
178                                  GLuint id,
179                                  const std::string &message) override;
180     angle::Result popDebugGroup(const gl::Context *context) override;
181 
182     // State sync with dirty bits.
183     angle::Result syncState(const gl::Context *context,
184                             const gl::State::DirtyBits &dirtyBits,
185                             const gl::State::DirtyBits &bitMask) override;
186 
187     // Disjoint timer queries
188     GLint getGPUDisjoint() override;
189     GLint64 getTimestamp() override;
190 
191     // Context switching
192     angle::Result onMakeCurrent(const gl::Context *context) override;
193     angle::Result onUnMakeCurrent(const gl::Context *context) override;
194 
195     // Native capabilities, unmodified by gl::Context.
196     gl::Caps getNativeCaps() const override;
197     const gl::TextureCapsMap &getNativeTextureCaps() const override;
198     const gl::Extensions &getNativeExtensions() const override;
199     const gl::Limitations &getNativeLimitations() const override;
200 
getProgram()201     const ProgramMtl *getProgram() const { return mProgram; }
202 
203     // Shader creation
204     CompilerImpl *createCompiler() override;
205     ShaderImpl *createShader(const gl::ShaderState &state) override;
206     ProgramImpl *createProgram(const gl::ProgramState &state) override;
207 
208     // Framebuffer creation
209     FramebufferImpl *createFramebuffer(const gl::FramebufferState &state) override;
210 
211     // Texture creation
212     TextureImpl *createTexture(const gl::TextureState &state) override;
213 
214     // Renderbuffer creation
215     RenderbufferImpl *createRenderbuffer(const gl::RenderbufferState &state) override;
216 
217     // Buffer creation
218     BufferImpl *createBuffer(const gl::BufferState &state) override;
219 
220     // Vertex Array creation
221     VertexArrayImpl *createVertexArray(const gl::VertexArrayState &state) override;
222 
223     // Query and Fence creation
224     QueryImpl *createQuery(gl::QueryType type) override;
225     FenceNVImpl *createFenceNV() override;
226     SyncImpl *createSync() override;
227 
228     // Transform Feedback creation
229     TransformFeedbackImpl *createTransformFeedback(
230         const gl::TransformFeedbackState &state) override;
231 
232     // Sampler object creation
233     SamplerImpl *createSampler(const gl::SamplerState &state) override;
234 
235     // Program Pipeline object creation
236     ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override;
237 
238     // Memory object creation.
239     MemoryObjectImpl *createMemoryObject() override;
240 
241     // Semaphore creation.
242     SemaphoreImpl *createSemaphore() override;
243 
244     // Overlay creation.
245     OverlayImpl *createOverlay(const gl::OverlayState &state) override;
246 
247     angle::Result dispatchCompute(const gl::Context *context,
248                                   GLuint numGroupsX,
249                                   GLuint numGroupsY,
250                                   GLuint numGroupsZ) override;
251     angle::Result dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) override;
252 
253     angle::Result memoryBarrier(const gl::Context *context, GLbitfield barriers) override;
254     angle::Result memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers) override;
255 
256     // override mtl::ErrorHandler
257     void handleError(GLenum error,
258                      const char *file,
259                      const char *function,
260                      unsigned int line) override;
261     void handleError(NSError *_Nullable error,
262                      const char *file,
263                      const char *function,
264                      unsigned int line) override;
265 
266     using ContextImpl::handleError;
267 
268     void invalidateState(const gl::Context *context);
269     void invalidateDefaultAttribute(size_t attribIndex);
270     void invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask);
271     void invalidateCurrentTextures();
272     void invalidateDriverUniforms();
273     void invalidateRenderPipeline();
274 
275     // Call this to notify ContextMtl whenever FramebufferMtl's state changed
276     void onDrawFrameBufferChangedState(const gl::Context *context,
277                                        FramebufferMtl *framebuffer,
278                                        bool renderPassChanged);
279     void onBackbufferResized(const gl::Context *context, WindowSurfaceMtl *backbuffer);
280 
281     // Invoke by QueryMtl
282     angle::Result onOcclusionQueryBegin(const gl::Context *context, QueryMtl *query);
283     void onOcclusionQueryEnd(const gl::Context *context, QueryMtl *query);
284     void onOcclusionQueryDestroy(const gl::Context *context, QueryMtl *query);
285 
286     // Useful for temporarily pause then restart occlusion query during clear/blit with draw.
hasActiveOcclusionQuery()287     bool hasActiveOcclusionQuery() const { return mOcclusionQuery; }
288     // Disable the occlusion query in the current render pass.
289     // The render pass must already started.
290     void disableActiveOcclusionQueryInRenderPass();
291     // Re-enable the occlusion query in the current render pass.
292     // The render pass must already started.
293     // NOTE: the old query's result will be retained and combined with the new result.
294     angle::Result restartActiveOcclusionQueryInRenderPass();
295 
296     // Invoke by TransformFeedbackMtl
297     void onTransformFeedbackActive(const gl::Context *context, TransformFeedbackMtl *xfb);
298     void onTransformFeedbackInactive(const gl::Context *context, TransformFeedbackMtl *xfb);
299 
300     // Invoke by mtl::Sync
301     void queueEventSignal(const mtl::SharedEventRef &event, uint64_t value);
302     void serverWaitEvent(const mtl::SharedEventRef &event, uint64_t value);
303 
304     const mtl::ClearColorValue &getClearColorValue() const;
305     const mtl::WriteMaskArray &getWriteMaskArray() const;
306     float getClearDepthValue() const;
307     uint32_t getClearStencilValue() const;
308     // Return front facing stencil write mask
309     uint32_t getStencilMask() const;
310     bool getDepthMask() const;
311 
312     const mtl::Format &getPixelFormat(angle::FormatID angleFormatId) const;
313     const mtl::FormatCaps &getNativeFormatCaps(MTLPixelFormat mtlFormat) const;
314     // See mtl::FormatTable::getVertexFormat()
315     const mtl::VertexFormat &getVertexFormat(angle::FormatID angleFormatId,
316                                              bool tightlyPacked) const;
317 
318     angle::Result getIncompleteTexture(const gl::Context *context,
319                                        gl::TextureType type,
320                                        gl::Texture **textureOut);
321 
322     // Recommended to call these methods to end encoding instead of invoking the encoder's
323     // endEncoding() directly.
324     void endRenderEncoding(mtl::RenderCommandEncoder *encoder);
325     // Ends any active command encoder
326     void endEncoding(bool forceSaveRenderPassContent);
327 
328     void flushCommandBufer();
329     void present(const gl::Context *context, id<CAMetalDrawable> presentationDrawable);
330     angle::Result finishCommandBuffer();
331 
332     // Check whether compatible render pass has been started. Compatible render pass is a render
333     // pass having the same attachments, and possibly having different load/store options.
334     bool hasStartedRenderPass(const mtl::RenderPassDesc &desc);
335 
336     // Get current render encoder. May be nullptr if no render pass has been started.
337     mtl::RenderCommandEncoder *getRenderCommandEncoder();
338 
339     // Will end current command encoder if it is valid, then start new encoder.
340     // Unless hasStartedRenderPass(desc) returns true.
341     // Note: passing a compatible render pass with different load/store options won't end the
342     // current render pass. If a new render pass is desired, call endEncoding() prior to this.
343     mtl::RenderCommandEncoder *getRenderPassCommandEncoder(const mtl::RenderPassDesc &desc);
344 
345     // Utilities to quickly create render command encoder to a specific texture:
346     // The previous content of texture will be loaded
347     mtl::RenderCommandEncoder *getTextureRenderCommandEncoder(const mtl::TextureRef &textureTarget,
348                                                               const mtl::ImageNativeIndex &index);
349     // The previous content of texture will be loaded if clearColor is not provided
350     mtl::RenderCommandEncoder *getRenderTargetCommandEncoderWithClear(
351         const RenderTargetMtl &renderTarget,
352         const Optional<MTLClearColor> &clearColor);
353     // The previous content of texture will be loaded
354     mtl::RenderCommandEncoder *getRenderTargetCommandEncoder(const RenderTargetMtl &renderTarget);
355 
356     // Will end current command encoder and start new blit command encoder. Unless a blit comamnd
357     // encoder is already started.
358     mtl::BlitCommandEncoder *getBlitCommandEncoder();
359 
360     // Will end current command encoder and start new compute command encoder. Unless a compute
361     // command encoder is already started.
362     mtl::ComputeCommandEncoder *getComputeCommandEncoder();
363 
364   private:
365     void ensureCommandBufferReady();
366     angle::Result ensureIncompleteTexturesCreated(const gl::Context *context);
367     angle::Result setupDraw(const gl::Context *context,
368                             gl::PrimitiveMode mode,
369                             GLint firstVertex,
370                             GLsizei vertexOrIndexCount,
371                             GLsizei instanceCount,
372                             gl::DrawElementsType indexTypeOrNone,
373                             const void *indices,
374                             bool xfbPass);
375 
376     angle::Result drawTriFanArrays(const gl::Context *context,
377                                    GLint first,
378                                    GLsizei count,
379                                    GLsizei instances);
380     angle::Result drawTriFanArraysWithBaseVertex(const gl::Context *context,
381                                                  GLint first,
382                                                  GLsizei count,
383                                                  GLsizei instances);
384     angle::Result drawTriFanArraysLegacy(const gl::Context *context,
385                                          GLint first,
386                                          GLsizei count,
387                                          GLsizei instances);
388     angle::Result drawTriFanElements(const gl::Context *context,
389                                      GLsizei count,
390                                      gl::DrawElementsType type,
391                                      const void *indices,
392                                      GLsizei instances);
393 
394     angle::Result drawLineLoopArraysNonInstanced(const gl::Context *context,
395                                                  GLint first,
396                                                  GLsizei count);
397     angle::Result drawLineLoopArrays(const gl::Context *context,
398                                      GLint first,
399                                      GLsizei count,
400                                      GLsizei instances);
401     angle::Result drawLineLoopElementsNonInstancedNoPrimitiveRestart(const gl::Context *context,
402                                                                      GLsizei count,
403                                                                      gl::DrawElementsType type,
404                                                                      const void *indices);
405     angle::Result drawLineLoopElements(const gl::Context *context,
406                                        GLsizei count,
407                                        gl::DrawElementsType type,
408                                        const void *indices,
409                                        GLsizei instances);
410 
411     angle::Result drawArraysImpl(const gl::Context *context,
412                                  gl::PrimitiveMode mode,
413                                  GLint first,
414                                  GLsizei count,
415                                  GLsizei instanceCount);
416 
417     angle::Result drawElementsImpl(const gl::Context *context,
418                                    gl::PrimitiveMode mode,
419                                    GLsizei count,
420                                    gl::DrawElementsType type,
421                                    const void *indices,
422                                    GLsizei instanceCount);
423 
424     void updateExtendedState(const gl::State &glState);
425 
426     void updateViewport(FramebufferMtl *framebufferMtl,
427                         const gl::Rectangle &viewport,
428                         float nearPlane,
429                         float farPlane);
430     void updateDepthRange(float nearPlane, float farPlane);
431     void updateBlendDescArray(const gl::BlendStateExt &blendStateExt);
432     void updateScissor(const gl::State &glState);
433     void updateCullMode(const gl::State &glState);
434     void updateFrontFace(const gl::State &glState);
435     void updateDepthBias(const gl::State &glState);
436     void updateDrawFrameBufferBinding(const gl::Context *context);
437     void updateProgramExecutable(const gl::Context *context);
438     void updateVertexArray(const gl::Context *context);
439 
440     angle::Result updateDefaultAttribute(size_t attribIndex);
441     void filterOutXFBOnlyDirtyBits(const gl::Context *context);
442     angle::Result handleDirtyActiveTextures(const gl::Context *context);
443     angle::Result handleDirtyDefaultAttribs(const gl::Context *context);
444     angle::Result handleDirtyDriverUniforms(const gl::Context *context,
445                                             GLint drawCallFirstVertex,
446                                             uint32_t verticesPerInstance);
447     angle::Result fillDriverXFBUniforms(GLint drawCallFirstVertex,
448                                         uint32_t verticesPerInstance,
449                                         uint32_t skippedInstances);
450     angle::Result handleDirtyDepthStencilState(const gl::Context *context);
451     angle::Result handleDirtyDepthBias(const gl::Context *context);
452     angle::Result handleDirtyRenderPass(const gl::Context *context);
453     angle::Result checkIfPipelineChanged(const gl::Context *context,
454                                          gl::PrimitiveMode primitiveMode,
455                                          bool xfbPass,
456                                          bool *pipelineDescChanged);
457 
458     angle::Result startOcclusionQueryInRenderPass(QueryMtl *query, bool clearOldValue);
459 
460     // Dirty bits.
461     enum DirtyBitType : size_t
462     {
463         DIRTY_BIT_DEFAULT_ATTRIBS,
464         DIRTY_BIT_TEXTURES,
465         DIRTY_BIT_DRIVER_UNIFORMS,
466         DIRTY_BIT_DEPTH_STENCIL_DESC,
467         DIRTY_BIT_DEPTH_BIAS,
468         DIRTY_BIT_STENCIL_REF,
469         DIRTY_BIT_BLEND_COLOR,
470         DIRTY_BIT_VIEWPORT,
471         DIRTY_BIT_SCISSOR,
472         DIRTY_BIT_DRAW_FRAMEBUFFER,
473         DIRTY_BIT_CULL_MODE,
474         DIRTY_BIT_WINDING,
475         DIRTY_BIT_RENDER_PIPELINE,
476         DIRTY_BIT_UNIFORM_BUFFERS_BINDING,
477         DIRTY_BIT_RASTERIZER_DISCARD,
478 
479         DIRTY_BIT_INVALID,
480         DIRTY_BIT_MAX = DIRTY_BIT_INVALID,
481     };
482 
483     // See compiler/translator/TranslatorVulkan.cpp: AddDriverUniformsToShader()
484     struct DriverUniforms
485     {
486         float viewport[4];
487 
488         // 32 bits for 32 clip distances
489         uint32_t enabledClipDistances;
490 
491         uint32_t xfbActiveUnpaused;
492         int32_t xfbVerticesPerInstance;
493 
494         int32_t numSamples;
495 
496         int32_t xfbBufferOffsets[4];
497         uint32_t acbBufferOffsets[4];
498 
499         // We'll use x, y, z, w for near / far / diff / zscale respectively.
500         float depthRange[4];
501 
502         // Metal specific
503         float halfRenderArea[2];
504         float flipXY[2];
505         float negFlipXY[2];
506         uint32_t coverageMask;
507         uint32_t padding;
508     };
509 
510     struct DefaultAttribute
511     {
512         uint8_t values[sizeof(float) * 4];
513     };
514 
515     mtl::OcclusionQueryPool mOcclusionQueryPool;
516 
517     mtl::CommandBuffer mCmdBuffer;
518     mtl::RenderCommandEncoder mRenderEncoder;
519     mtl::BlitCommandEncoder mBlitEncoder;
520     mtl::ComputeCommandEncoder mComputeEncoder;
521 
522     // Cached back-end objects
523     FramebufferMtl *mDrawFramebuffer = nullptr;
524     VertexArrayMtl *mVertexArray     = nullptr;
525     ProgramMtl *mProgram             = nullptr;
526     QueryMtl *mOcclusionQuery        = nullptr;
527 
528     using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
529 
530     gl::AttributesMask mDirtyDefaultAttribsMask;
531     DirtyBits mDirtyBits;
532 
533     // State
534     mtl::RenderPipelineDesc mRenderPipelineDesc;
535     mtl::DepthStencilDesc mDepthStencilDesc;
536     mtl::BlendDescArray mBlendDescArray;
537     mtl::WriteMaskArray mWriteMaskArray;
538     mtl::ClearColorValue mClearColor;
539     uint32_t mClearStencil    = 0;
540     uint32_t mStencilRefFront = 0;
541     uint32_t mStencilRefBack  = 0;
542     MTLViewport mViewport;
543     MTLScissorRect mScissorRect;
544     MTLWinding mWinding;
545     MTLCullMode mCullMode;
546     bool mCullAllPolygons = false;
547 
548     // Lineloop and TriFan index buffer
549     mtl::BufferPool mLineLoopIndexBuffer;
550     mtl::BufferPool mLineLoopLastSegmentIndexBuffer;
551     mtl::BufferPool mTriFanIndexBuffer;
552     // one buffer can be reused for any starting vertex in DrawArrays()
553     mtl::BufferRef mTriFanArraysIndexBuffer;
554 
555     // Dummy texture to be used for transform feedback only pass.
556     mtl::TextureRef mDummyXFBRenderTexture;
557 
558     DriverUniforms mDriverUniforms;
559 
560     DefaultAttribute mDefaultAttributes[mtl::kMaxVertexAttribs];
561 
562     IncompleteTextureSet mIncompleteTextures;
563     bool mIncompleteTexturesInitialized = false;
564 };
565 
566 }  // namespace rx
567 
568 #endif /* LIBANGLE_RENDERER_METAL_CONTEXTMTL_H_ */
569