• 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_resources.h"
21 #include "libANGLE/renderer/metal/mtl_state_cache.h"
22 #include "libANGLE/renderer/metal/mtl_utils.h"
23 
24 namespace rx
25 {
26 class DisplayMtl;
27 class FramebufferMtl;
28 class VertexArrayMtl;
29 class ProgramMtl;
30 
31 class ContextMtl : public ContextImpl, public mtl::Context
32 {
33   public:
34     ContextMtl(const gl::State &state, gl::ErrorSet *errorSet, DisplayMtl *display);
35     ~ContextMtl() override;
36 
37     angle::Result initialize() override;
38 
39     void onDestroy(const gl::Context *context) override;
40 
41     // Flush and finish.
42     angle::Result flush(const gl::Context *context) override;
43     angle::Result finish(const gl::Context *context) override;
44 
45     // Drawing methods.
46     angle::Result drawArrays(const gl::Context *context,
47                              gl::PrimitiveMode mode,
48                              GLint first,
49                              GLsizei count) override;
50     angle::Result drawArraysInstanced(const gl::Context *context,
51                                       gl::PrimitiveMode mode,
52                                       GLint first,
53                                       GLsizei count,
54                                       GLsizei instanceCount) override;
55     angle::Result drawArraysInstancedBaseInstance(const gl::Context *context,
56                                                   gl::PrimitiveMode mode,
57                                                   GLint first,
58                                                   GLsizei count,
59                                                   GLsizei instanceCount,
60                                                   GLuint baseInstance) override;
61 
62     angle::Result drawElements(const gl::Context *context,
63                                gl::PrimitiveMode mode,
64                                GLsizei count,
65                                gl::DrawElementsType type,
66                                const void *indices) override;
67     angle::Result drawElementsBaseVertex(const gl::Context *context,
68                                          gl::PrimitiveMode mode,
69                                          GLsizei count,
70                                          gl::DrawElementsType type,
71                                          const void *indices,
72                                          GLint baseVertex) override;
73     angle::Result drawElementsInstanced(const gl::Context *context,
74                                         gl::PrimitiveMode mode,
75                                         GLsizei count,
76                                         gl::DrawElementsType type,
77                                         const void *indices,
78                                         GLsizei instanceCount) override;
79     angle::Result drawElementsInstancedBaseVertex(const gl::Context *context,
80                                                   gl::PrimitiveMode mode,
81                                                   GLsizei count,
82                                                   gl::DrawElementsType type,
83                                                   const void *indices,
84                                                   GLsizei instanceCount,
85                                                   GLint baseVertex) override;
86     angle::Result drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
87                                                               gl::PrimitiveMode mode,
88                                                               GLsizei count,
89                                                               gl::DrawElementsType type,
90                                                               const void *indices,
91                                                               GLsizei instances,
92                                                               GLint baseVertex,
93                                                               GLuint baseInstance) override;
94     angle::Result drawRangeElements(const gl::Context *context,
95                                     gl::PrimitiveMode mode,
96                                     GLuint start,
97                                     GLuint end,
98                                     GLsizei count,
99                                     gl::DrawElementsType type,
100                                     const void *indices) override;
101     angle::Result drawRangeElementsBaseVertex(const gl::Context *context,
102                                               gl::PrimitiveMode mode,
103                                               GLuint start,
104                                               GLuint end,
105                                               GLsizei count,
106                                               gl::DrawElementsType type,
107                                               const void *indices,
108                                               GLint baseVertex) override;
109     angle::Result drawArraysIndirect(const gl::Context *context,
110                                      gl::PrimitiveMode mode,
111                                      const void *indirect) override;
112     angle::Result drawElementsIndirect(const gl::Context *context,
113                                        gl::PrimitiveMode mode,
114                                        gl::DrawElementsType type,
115                                        const void *indirect) override;
116 
117     // Device loss
118     gl::GraphicsResetStatus getResetStatus() override;
119 
120     // Vendor and description strings.
121     std::string getVendorString() const override;
122     std::string getRendererDescription() const override;
123 
124     // EXT_debug_marker
125     angle::Result insertEventMarker(GLsizei length, const char *marker) override;
126     angle::Result pushGroupMarker(GLsizei length, const char *marker) override;
127     angle::Result popGroupMarker() override;
128 
129     // KHR_debug
130     angle::Result pushDebugGroup(const gl::Context *context,
131                                  GLenum source,
132                                  GLuint id,
133                                  const std::string &message) override;
134     angle::Result popDebugGroup(const gl::Context *context) override;
135 
136     // State sync with dirty bits.
137     angle::Result syncState(const gl::Context *context,
138                             const gl::State::DirtyBits &dirtyBits,
139                             const gl::State::DirtyBits &bitMask) override;
140 
141     // Disjoint timer queries
142     GLint getGPUDisjoint() override;
143     GLint64 getTimestamp() override;
144 
145     // Context switching
146     angle::Result onMakeCurrent(const gl::Context *context) override;
147     angle::Result onUnMakeCurrent(const gl::Context *context) override;
148 
149     // Native capabilities, unmodified by gl::Context.
150     gl::Caps getNativeCaps() const override;
151     const gl::TextureCapsMap &getNativeTextureCaps() const override;
152     const gl::Extensions &getNativeExtensions() const override;
153     const gl::Limitations &getNativeLimitations() const override;
154 
155     // Shader creation
156     CompilerImpl *createCompiler() override;
157     ShaderImpl *createShader(const gl::ShaderState &state) override;
158     ProgramImpl *createProgram(const gl::ProgramState &state) override;
159 
160     // Framebuffer creation
161     FramebufferImpl *createFramebuffer(const gl::FramebufferState &state) override;
162 
163     // Texture creation
164     TextureImpl *createTexture(const gl::TextureState &state) override;
165 
166     // Renderbuffer creation
167     RenderbufferImpl *createRenderbuffer(const gl::RenderbufferState &state) override;
168 
169     // Buffer creation
170     BufferImpl *createBuffer(const gl::BufferState &state) override;
171 
172     // Vertex Array creation
173     VertexArrayImpl *createVertexArray(const gl::VertexArrayState &state) override;
174 
175     // Query and Fence creation
176     QueryImpl *createQuery(gl::QueryType type) override;
177     FenceNVImpl *createFenceNV() override;
178     SyncImpl *createSync() override;
179 
180     // Transform Feedback creation
181     TransformFeedbackImpl *createTransformFeedback(
182         const gl::TransformFeedbackState &state) override;
183 
184     // Sampler object creation
185     SamplerImpl *createSampler(const gl::SamplerState &state) override;
186 
187     // Program Pipeline object creation
188     ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override;
189 
190     // Memory object creation.
191     MemoryObjectImpl *createMemoryObject() override;
192 
193     // Semaphore creation.
194     SemaphoreImpl *createSemaphore() override;
195 
196     // Overlay creation.
197     OverlayImpl *createOverlay(const gl::OverlayState &state) override;
198 
199     angle::Result dispatchCompute(const gl::Context *context,
200                                   GLuint numGroupsX,
201                                   GLuint numGroupsY,
202                                   GLuint numGroupsZ) override;
203     angle::Result dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) override;
204 
205     angle::Result memoryBarrier(const gl::Context *context, GLbitfield barriers) override;
206     angle::Result memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers) override;
207 
208     // override mtl::ErrorHandler
209     void handleError(GLenum error,
210                      const char *file,
211                      const char *function,
212                      unsigned int line) override;
213     void handleError(NSError *_Nullable error,
214                      const char *file,
215                      const char *function,
216                      unsigned int line) override;
217 
218     using ContextImpl::handleError;
219 
220     void invalidateState(const gl::Context *context);
221     void invalidateDefaultAttribute(size_t attribIndex);
222     void invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask);
223     void invalidateCurrentTextures();
224     void invalidateDriverUniforms();
225     void invalidateRenderPipeline();
226 
227     // Call this to notify ContextMtl whenever FramebufferMtl's state changed
228     void onDrawFrameBufferChange(const gl::Context *context, FramebufferMtl *framebuffer);
229 
230     const MTLClearColor &getClearColorValue() const;
231     MTLColorWriteMask getColorMask() const;
232     float getClearDepthValue() const;
233     uint32_t getClearStencilValue() const;
234     // Return front facing stencil write mask
235     uint32_t getStencilMask() const;
236     bool getDepthMask() const;
237 
238     const mtl::Format &getPixelFormat(angle::FormatID angleFormatId) const;
239     // See mtl::FormatTable::getVertexFormat()
240     const mtl::VertexFormat &getVertexFormat(angle::FormatID angleFormatId,
241                                              bool tightlyPacked) const;
242 
243     angle::Result getIncompleteTexture(const gl::Context *context,
244                                        gl::TextureType type,
245                                        gl::Texture **textureOut);
246 
247     // Recommended to call these methods to end encoding instead of invoking the encoder's
248     // endEncoding() directly.
249     void endEncoding(mtl::RenderCommandEncoder *encoder);
250     // Ends any active command encoder
251     void endEncoding(bool forceSaveRenderPassContent);
252 
253     void flushCommandBufer();
254     void present(const gl::Context *context, id<CAMetalDrawable> presentationDrawable);
255     angle::Result finishCommandBuffer();
256 
257     // Check whether compatible render pass has been started.
258     bool hasStartedRenderPass(const mtl::RenderPassDesc &desc);
259     bool hasStartedRenderPass(FramebufferMtl *framebuffer);
260 
261     // Get current render encoder. May be nullptr if no render pass has been started.
262     mtl::RenderCommandEncoder *getRenderCommandEncoder();
263 
264     mtl::RenderCommandEncoder *getCurrentFramebufferRenderCommandEncoder();
265 
266     // Will end current command encoder if it is valid, then start new encoder.
267     // Unless hasStartedRenderPass(desc) returns true.
268     mtl::RenderCommandEncoder *getRenderCommandEncoder(const mtl::RenderPassDesc &desc);
269 
270     // Utilities to quickly create render command enconder to a specific texture:
271     // The previous content of texture will be loaded if clearColor is not provided
272     mtl::RenderCommandEncoder *getRenderCommandEncoder(const mtl::TextureRef &textureTarget,
273                                                        const gl::ImageIndex &index,
274                                                        const Optional<MTLClearColor> &clearColor);
275     // The previous content of texture will be loaded
276     mtl::RenderCommandEncoder *getRenderCommandEncoder(const mtl::TextureRef &textureTarget,
277                                                        const gl::ImageIndex &index);
278 
279     // Will end current command encoder and start new blit command encoder. Unless a blit comamnd
280     // encoder is already started.
281     mtl::BlitCommandEncoder *getBlitCommandEncoder();
282 
283     // Will end current command encoder and start new compute command encoder. Unless a compute
284     // command encoder is already started.
285     mtl::ComputeCommandEncoder *getComputeCommandEncoder();
286 
287   private:
288     void ensureCommandBufferValid();
289     angle::Result ensureIncompleteTexturesCreated(const gl::Context *context);
290     angle::Result setupDraw(const gl::Context *context,
291                             gl::PrimitiveMode mode,
292                             GLint firstVertex,
293                             GLsizei vertexOrIndexCount,
294                             GLsizei instanceCount,
295                             gl::DrawElementsType indexTypeOrNone,
296                             const void *indices);
297     angle::Result genLineLoopLastSegment(const gl::Context *context,
298                                          GLint firstVertex,
299                                          GLsizei vertexOrIndexCount,
300                                          GLsizei instanceCount,
301                                          gl::DrawElementsType indexTypeOrNone,
302                                          const void *indices,
303                                          mtl::BufferRef *lastSegmentIndexBufferOut);
304 
305     angle::Result drawTriFanArrays(const gl::Context *context,
306                                    GLint first,
307                                    GLsizei count,
308                                    GLsizei instances);
309     angle::Result drawTriFanArraysWithBaseVertex(const gl::Context *context,
310                                                  GLint first,
311                                                  GLsizei count,
312                                                  GLsizei instances);
313     angle::Result drawTriFanArraysLegacy(const gl::Context *context,
314                                          GLint first,
315                                          GLsizei count,
316                                          GLsizei instances);
317     angle::Result drawTriFanElements(const gl::Context *context,
318                                      GLsizei count,
319                                      gl::DrawElementsType type,
320                                      const void *indices,
321                                      GLsizei instances);
322 
323     angle::Result drawArraysImpl(const gl::Context *context,
324                                  gl::PrimitiveMode mode,
325                                  GLint first,
326                                  GLsizei count,
327                                  GLsizei instanceCount);
328 
329     angle::Result drawElementsImpl(const gl::Context *context,
330                                    gl::PrimitiveMode mode,
331                                    GLsizei count,
332                                    gl::DrawElementsType type,
333                                    const void *indices,
334                                    GLsizei instanceCount);
335 
336     void updateExtendedState(const gl::State &glState);
337 
338     void updateViewport(FramebufferMtl *framebufferMtl,
339                         const gl::Rectangle &viewport,
340                         float nearPlane,
341                         float farPlane);
342     void updateDepthRange(float nearPlane, float farPlane);
343     void updateScissor(const gl::State &glState);
344     void updateCullMode(const gl::State &glState);
345     void updateFrontFace(const gl::State &glState);
346     void updateDepthBias(const gl::State &glState);
347     void updateDrawFrameBufferBinding(const gl::Context *context);
348     void updateProgramExecutable(const gl::Context *context);
349     void updateVertexArray(const gl::Context *context);
350 
351     angle::Result updateDefaultAttribute(size_t attribIndex);
352     angle::Result handleDirtyActiveTextures(const gl::Context *context);
353     angle::Result handleDirtyDefaultAttribs(const gl::Context *context);
354     angle::Result handleDirtyDriverUniforms(const gl::Context *context);
355     angle::Result handleDirtyDepthStencilState(const gl::Context *context);
356     angle::Result handleDirtyDepthBias(const gl::Context *context);
357     angle::Result checkIfPipelineChanged(const gl::Context *context,
358                                          gl::PrimitiveMode primitiveMode,
359                                          Optional<mtl::RenderPipelineDesc> *changedPipelineDesc);
360 
361     // Dirty bits.
362     enum DirtyBitType : size_t
363     {
364         DIRTY_BIT_DEFAULT_ATTRIBS,
365         DIRTY_BIT_TEXTURES,
366         DIRTY_BIT_DRIVER_UNIFORMS,
367         DIRTY_BIT_DEPTH_STENCIL_DESC,
368         DIRTY_BIT_DEPTH_BIAS,
369         DIRTY_BIT_STENCIL_REF,
370         DIRTY_BIT_BLEND_COLOR,
371         DIRTY_BIT_VIEWPORT,
372         DIRTY_BIT_SCISSOR,
373         DIRTY_BIT_DRAW_FRAMEBUFFER,
374         DIRTY_BIT_CULL_MODE,
375         DIRTY_BIT_WINDING,
376         DIRTY_BIT_RENDER_PIPELINE,
377         DIRTY_BIT_MAX,
378     };
379 
380     // See compiler/translator/TranslatorVulkan.cpp: AddDriverUniformsToShader()
381     struct DriverUniforms
382     {
383         float viewport[4];
384 
385         float halfRenderArea[2];
386         float flipXY[2];
387         float negFlipXY[2];
388 
389         // 32 bits for 32 clip distances
390         uint32_t enabledClipDistances;
391 
392         // NOTE(hqle): Transform feedsback is not supported yet.
393         uint32_t xfbActiveUnpaused;
394         uint32_t xfbVerticesPerDraw;
395         // NOTE: Explicit padding. Fill in with useful data when needed in the future.
396         int32_t padding[3];
397 
398         int32_t xfbBufferOffsets[4];
399         uint32_t acbBufferOffsets[4];
400 
401         // We'll use x, y, z, w for near / far / diff / zscale respectively.
402         float depthRange[4];
403 
404         // Used to pre-rotate gl_Position for Vulkan swapchain images on Android (a mat2, which is
405         // padded to the size of two vec4's).
406         float preRotation[8];
407 
408         // Used to pre-rotate gl_FragCoord for Vulkan swapchain images on Android (a mat2, which is
409         // padded to the size of two vec4's).
410         float fragRotation[8];
411     };
412 
413     struct DefaultAttribute
414     {
415         // NOTE(hqle): Support integer default attributes in ES 3.0
416         float values[4];
417     };
418 
419     mtl::CommandBuffer mCmdBuffer;
420     mtl::RenderCommandEncoder mRenderEncoder;
421     mtl::BlitCommandEncoder mBlitEncoder;
422     mtl::ComputeCommandEncoder mComputeEncoder;
423 
424     // Cached back-end objects
425     FramebufferMtl *mDrawFramebuffer = nullptr;
426     VertexArrayMtl *mVertexArray     = nullptr;
427     ProgramMtl *mProgram             = nullptr;
428 
429     // Special flag to indicate current draw framebuffer is default framebuffer.
430     // We need this instead of calling mDrawFramebuffer->getState().isDefault() because
431     // mDrawFramebuffer might point to a deleted object, ContextMtl only knows about this very late,
432     // only during syncState() function call.
433     bool mDrawFramebufferIsDefault = true;
434 
435     using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
436 
437     gl::AttributesMask mDirtyDefaultAttribsMask;
438     DirtyBits mDirtyBits;
439 
440     // State
441     mtl::RenderPipelineDesc mRenderPipelineDesc;
442     mtl::DepthStencilDesc mDepthStencilDesc;
443     mtl::BlendDesc mBlendDesc;
444     MTLClearColor mClearColor;
445     uint32_t mClearStencil    = 0;
446     uint32_t mStencilRefFront = 0;
447     uint32_t mStencilRefBack  = 0;
448     MTLViewport mViewport;
449     MTLScissorRect mScissorRect;
450     MTLWinding mWinding;
451     MTLCullMode mCullMode;
452     bool mCullAllPolygons = false;
453 
454     // Lineloop and TriFan index buffer
455     mtl::BufferPool mLineLoopIndexBuffer;
456     mtl::BufferPool mTriFanIndexBuffer;
457     // one buffer can be reused for any starting vertex in DrawArrays()
458     mtl::BufferRef mTriFanArraysIndexBuffer;
459 
460     DriverUniforms mDriverUniforms;
461 
462     DefaultAttribute mDefaultAttributes[mtl::kMaxVertexAttribs];
463 
464     IncompleteTextureSet mIncompleteTextures;
465     bool mIncompleteTexturesInitialized = false;
466 };
467 
468 }  // namespace rx
469 
470 #endif /* LIBANGLE_RENDERER_METAL_CONTEXTMTL_H_ */
471