• 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     // Recommended to call these methods to end encoding instead of invoking the encoder's
244     // endEncoding() directly.
245     void endEncoding(mtl::RenderCommandEncoder *encoder);
246     // Ends any active command encoder
247     void endEncoding(bool forceSaveRenderPassContent);
248 
249     void flushCommandBufer();
250     void present(const gl::Context *context, id<CAMetalDrawable> presentationDrawable);
251     angle::Result finishCommandBuffer();
252 
253     // Check whether compatible render pass has been started.
254     bool hasStartedRenderPass(const mtl::RenderPassDesc &desc);
255     bool hasStartedRenderPass(FramebufferMtl *framebuffer);
256 
257     // Get current render encoder. May be nullptr if no render pass has been started.
258     mtl::RenderCommandEncoder *getRenderCommandEncoder();
259 
260     mtl::RenderCommandEncoder *getCurrentFramebufferRenderCommandEncoder();
261 
262     // Will end current command encoder if it is valid, then start new encoder.
263     // Unless hasStartedRenderPass(desc) returns true.
264     mtl::RenderCommandEncoder *getRenderCommandEncoder(const mtl::RenderPassDesc &desc);
265 
266     // Utilities to quickly create render command enconder to a specific texture:
267     // The previous content of texture will be loaded if clearColor is not provided
268     mtl::RenderCommandEncoder *getRenderCommandEncoder(const mtl::TextureRef &textureTarget,
269                                                        const gl::ImageIndex &index,
270                                                        const Optional<MTLClearColor> &clearColor);
271     // The previous content of texture will be loaded
272     mtl::RenderCommandEncoder *getRenderCommandEncoder(const mtl::TextureRef &textureTarget,
273                                                        const gl::ImageIndex &index);
274 
275     // Will end current command encoder and start new blit command encoder. Unless a blit comamnd
276     // encoder is already started.
277     mtl::BlitCommandEncoder *getBlitCommandEncoder();
278 
279     // Will end current command encoder and start new compute command encoder. Unless a compute
280     // command encoder is already started.
281     mtl::ComputeCommandEncoder *getComputeCommandEncoder();
282 
283   private:
284     void ensureCommandBufferValid();
285     angle::Result setupDraw(const gl::Context *context,
286                             gl::PrimitiveMode mode,
287                             GLint firstVertex,
288                             GLsizei vertexOrIndexCount,
289                             GLsizei instanceCount,
290                             gl::DrawElementsType indexTypeOrNone,
291                             const void *indices);
292     angle::Result genLineLoopLastSegment(const gl::Context *context,
293                                          GLint firstVertex,
294                                          GLsizei vertexOrIndexCount,
295                                          GLsizei instanceCount,
296                                          gl::DrawElementsType indexTypeOrNone,
297                                          const void *indices,
298                                          mtl::BufferRef *lastSegmentIndexBufferOut);
299 
300     angle::Result drawTriFanArrays(const gl::Context *context,
301                                    GLint first,
302                                    GLsizei count,
303                                    GLsizei instances);
304     angle::Result drawTriFanArraysWithBaseVertex(const gl::Context *context,
305                                                  GLint first,
306                                                  GLsizei count,
307                                                  GLsizei instances);
308     angle::Result drawTriFanArraysLegacy(const gl::Context *context,
309                                          GLint first,
310                                          GLsizei count,
311                                          GLsizei instances);
312     angle::Result drawTriFanElements(const gl::Context *context,
313                                      GLsizei count,
314                                      gl::DrawElementsType type,
315                                      const void *indices,
316                                      GLsizei instances);
317 
318     angle::Result drawArraysImpl(const gl::Context *context,
319                                  gl::PrimitiveMode mode,
320                                  GLint first,
321                                  GLsizei count,
322                                  GLsizei instanceCount);
323 
324     angle::Result drawElementsImpl(const gl::Context *context,
325                                    gl::PrimitiveMode mode,
326                                    GLsizei count,
327                                    gl::DrawElementsType type,
328                                    const void *indices,
329                                    GLsizei instanceCount);
330 
331     void updateViewport(FramebufferMtl *framebufferMtl,
332                         const gl::Rectangle &viewport,
333                         float nearPlane,
334                         float farPlane);
335     void updateDepthRange(float nearPlane, float farPlane);
336     void updateScissor(const gl::State &glState);
337     void updateCullMode(const gl::State &glState);
338     void updateFrontFace(const gl::State &glState);
339     void updateDepthBias(const gl::State &glState);
340     void updateDrawFrameBufferBinding(const gl::Context *context);
341     void updateProgramExecutable(const gl::Context *context);
342     void updateVertexArray(const gl::Context *context);
343 
344     angle::Result updateDefaultAttribute(size_t attribIndex);
345     angle::Result handleDirtyActiveTextures(const gl::Context *context);
346     angle::Result handleDirtyDefaultAttribs(const gl::Context *context);
347     angle::Result handleDirtyDriverUniforms(const gl::Context *context);
348     angle::Result handleDirtyDepthStencilState(const gl::Context *context);
349     angle::Result handleDirtyDepthBias(const gl::Context *context);
350     angle::Result checkIfPipelineChanged(const gl::Context *context,
351                                          gl::PrimitiveMode primitiveMode,
352                                          Optional<mtl::RenderPipelineDesc> *changedPipelineDesc);
353 
354     // Dirty bits.
355     enum DirtyBitType : size_t
356     {
357         DIRTY_BIT_DEFAULT_ATTRIBS,
358         DIRTY_BIT_TEXTURES,
359         DIRTY_BIT_DRIVER_UNIFORMS,
360         DIRTY_BIT_DEPTH_STENCIL_DESC,
361         DIRTY_BIT_DEPTH_BIAS,
362         DIRTY_BIT_STENCIL_REF,
363         DIRTY_BIT_BLEND_COLOR,
364         DIRTY_BIT_VIEWPORT,
365         DIRTY_BIT_SCISSOR,
366         DIRTY_BIT_DRAW_FRAMEBUFFER,
367         DIRTY_BIT_CULL_MODE,
368         DIRTY_BIT_WINDING,
369         DIRTY_BIT_RENDER_PIPELINE,
370         DIRTY_BIT_MAX,
371     };
372 
373     // See compiler/translator/TranslatorVulkan.cpp: AddDriverUniformsToShader()
374     struct DriverUniforms
375     {
376         float viewport[4];
377 
378         float halfRenderAreaHeight;
379         float viewportYScale;
380         float negViewportYScale;
381 
382         // NOTE(hqle): Transform feedsback is not supported yet.
383         uint32_t xfbActiveUnpaused;
384         uint32_t xfbVerticesPerDraw;
385         // NOTE: Explicit padding. Fill in with useful data when needed in the future.
386         int32_t padding[3];
387 
388         int32_t xfbBufferOffsets[4];
389         uint32_t acbBufferOffsets[4];
390 
391         // We'll use x, y, z, w for near / far / diff / zscale respectively.
392         float depthRange[4];
393 
394         // Used to pre-rotate gl_Position for Vulkan swapchain images on Android (a mat2, which is
395         // padded to the size of two vec4's).
396         float preRotation[8];
397     };
398 
399     struct DefaultAttribute
400     {
401         // NOTE(hqle): Support integer default attributes in ES 3.0
402         float values[4];
403     };
404 
405     mtl::CommandBuffer mCmdBuffer;
406     mtl::RenderCommandEncoder mRenderEncoder;
407     mtl::BlitCommandEncoder mBlitEncoder;
408     mtl::ComputeCommandEncoder mComputeEncoder;
409 
410     // Cached back-end objects
411     FramebufferMtl *mDrawFramebuffer = nullptr;
412     VertexArrayMtl *mVertexArray     = nullptr;
413     ProgramMtl *mProgram             = nullptr;
414 
415     // Special flag to indicate current draw framebuffer is default framebuffer.
416     // We need this instead of calling mDrawFramebuffer->getState().isDefault() because
417     // mDrawFramebuffer might point to a deleted object, ContextMtl only knows about this very late,
418     // only during syncState() function call.
419     bool mDrawFramebufferIsDefault = true;
420 
421     using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
422 
423     gl::AttributesMask mDirtyDefaultAttribsMask;
424     DirtyBits mDirtyBits;
425 
426     // State
427     mtl::RenderPipelineDesc mRenderPipelineDesc;
428     mtl::DepthStencilDesc mDepthStencilDesc;
429     mtl::BlendDesc mBlendDesc;
430     MTLClearColor mClearColor;
431     uint32_t mClearStencil    = 0;
432     uint32_t mStencilRefFront = 0;
433     uint32_t mStencilRefBack  = 0;
434     MTLViewport mViewport;
435     MTLScissorRect mScissorRect;
436     MTLWinding mWinding;
437     MTLCullMode mCullMode;
438     bool mCullAllPolygons = false;
439 
440     // Lineloop and TriFan index buffer
441     mtl::BufferPool mLineLoopIndexBuffer;
442     mtl::BufferPool mTriFanIndexBuffer;
443     // one buffer can be reused for any starting vertex in DrawArrays()
444     mtl::BufferRef mTriFanArraysIndexBuffer;
445 
446     DriverUniforms mDriverUniforms;
447 
448     DefaultAttribute mDefaultAttributes[mtl::kMaxVertexAttribs];
449 };
450 
451 }  // namespace rx
452 
453 #endif /* LIBANGLE_RENDERER_METAL_CONTEXTMTL_H_ */
454