• 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 // mtl_render_utils.h:
7 //    Defines the class interface for RenderUtils, which contains many utility functions and shaders
8 //    for converting, blitting, copying as well as generating data, and many more.
9 //
10 
11 #ifndef LIBANGLE_RENDERER_METAL_MTL_RENDER_UTILS_H_
12 #define LIBANGLE_RENDERER_METAL_MTL_RENDER_UTILS_H_
13 
14 #import <Metal/Metal.h>
15 
16 #include "libANGLE/angletypes.h"
17 #include "libANGLE/renderer/metal/RenderTargetMtl.h"
18 #include "libANGLE/renderer/metal/mtl_command_buffer.h"
19 #include "libANGLE/renderer/metal/mtl_context_device.h"
20 #include "libANGLE/renderer/metal/mtl_state_cache.h"
21 #include "libANGLE/renderer/metal/shaders/constants.h"
22 
23 namespace rx
24 {
25 
26 class BufferMtl;
27 class ContextMtl;
28 class DisplayMtl;
29 class VisibilityBufferOffsetsMtl;
30 
31 namespace mtl
32 {
33 
34 struct ClearRectParams
35 {
ClearRectParamsClearRectParams36     ClearRectParams() { clearWriteMaskArray.fill(MTLColorWriteMaskAll); }
37 
38     Optional<ClearColorValue> clearColor;
39     Optional<float> clearDepth;
40     Optional<uint32_t> clearStencil;
41 
42     WriteMaskArray clearWriteMaskArray;
43 
44     const mtl::Format *colorFormat = nullptr;
45     gl::Extents dstTextureSize;
46 
47     // Only clear enabled buffers
48     gl::DrawBufferMask enabledBuffers;
49     gl::Rectangle clearArea;
50 
51     bool flipY = false;
52 };
53 
54 struct NormalizedCoords
55 {
56     NormalizedCoords();
57     NormalizedCoords(float x, float y, float width, float height, const gl::Rectangle &rect);
58     NormalizedCoords(const gl::Rectangle &rect, const gl::Extents &extents);
59     float v[4];
60 };
61 
62 struct BlitParams
63 {
64     gl::Extents dstTextureSize;
65     gl::Rectangle dstRect;
66     gl::Rectangle dstScissorRect;
67     // Destination texture needs to have viewport Y flipped?
68     // The difference between this param and unpackFlipY is that unpackFlipY is from
69     // glCopyImageCHROMIUM()/glBlitFramebuffer(), and dstFlipY controls whether the final viewport
70     // needs to be flipped when drawing to destination texture. It is possible to combine the two
71     // flags before passing to RenderUtils. However, to avoid duplicated works, just pass the two
72     // flags to RenderUtils, they will be combined internally by RenderUtils logic.
73     bool dstFlipY = false;
74     bool dstFlipX = false;
75 
76     TextureRef src;
77     MipmapNativeLevel srcLevel = kZeroNativeMipLevel;
78     uint32_t srcLayer          = 0;
79 
80     // Source rectangle:
81     // NOTE: if srcYFlipped=true, this rectangle will be converted internally to flipped rect before
82     // blitting.
83     NormalizedCoords srcNormalizedCoords;
84 
85     bool srcYFlipped = false;  // source texture has data flipped in Y direction
86     bool unpackFlipX = false;  // flip texture data copying process in X direction
87     bool unpackFlipY = false;  // flip texture data copying process in Y direction
88 };
89 
90 struct ColorBlitParams : public BlitParams
91 {
ColorBlitParamsColorBlitParams92     ColorBlitParams() {}
93 
94     gl::DrawBufferMask enabledBuffers;
95     GLenum filter               = GL_NEAREST;
96     bool unpackPremultiplyAlpha = false;
97     bool unpackUnmultiplyAlpha  = false;
98     bool dstLuminance           = false;
99 };
100 
101 struct DepthStencilBlitParams : public BlitParams
102 {
103     TextureRef srcStencil;
104 };
105 
106 // Stencil blit via an intermediate buffer. NOTE: source depth texture parameter is ignored.
107 // See DepthStencilBlitUtils::blitStencilViaCopyBuffer()
108 struct StencilBlitViaBufferParams : public DepthStencilBlitParams
109 {
110     StencilBlitViaBufferParams();
111     StencilBlitViaBufferParams(const DepthStencilBlitParams &src);
112 
113     TextureRef dstStencil;
114     MipmapNativeLevel dstStencilLevel = kZeroNativeMipLevel;
115     uint32_t dstStencilLayer          = 0;
116     bool dstPackedDepthStencilFormat  = false;
117 };
118 
119 struct TriFanOrLineLoopFromArrayParams
120 {
121     uint32_t firstVertex;
122     uint32_t vertexCount;
123     BufferRef dstBuffer;
124     // Must be multiples of kIndexBufferOffsetAlignment
125     uint32_t dstOffset;
126 };
127 
128 struct IndexConversionParams
129 {
130 
131     gl::DrawElementsType srcType;
132     uint32_t indexCount;
133     const BufferRef &srcBuffer;
134     uint32_t srcOffset;
135     const BufferRef &dstBuffer;
136     // Must be multiples of kIndexBufferOffsetAlignment
137     uint32_t dstOffset;
138     bool primitiveRestartEnabled = false;
139 };
140 
141 struct IndexGenerationParams
142 {
143     gl::DrawElementsType srcType;
144     GLsizei indexCount;
145     const void *indices;
146     BufferRef dstBuffer;
147     uint32_t dstOffset;
148     bool primitiveRestartEnabled = false;
149 };
150 
151 struct CopyPixelsCommonParams
152 {
153     BufferRef buffer;
154     uint32_t bufferStartOffset = 0;
155     uint32_t bufferRowPitch    = 0;
156 
157     TextureRef texture;
158 };
159 
160 struct CopyPixelsFromBufferParams : CopyPixelsCommonParams
161 {
162     uint32_t bufferDepthPitch = 0;
163 
164     // z offset is:
165     //  - slice index if texture is array.
166     //  - depth if texture is 3d.
167     gl::Box textureArea;
168 };
169 
170 struct CopyPixelsToBufferParams : CopyPixelsCommonParams
171 {
172     gl::Rectangle textureArea;
173     MipmapNativeLevel textureLevel = kZeroNativeMipLevel;
174     uint32_t textureSliceOrDeph    = 0;
175     bool reverseTextureRowOrder;
176 };
177 
178 struct VertexFormatConvertParams
179 {
180     BufferRef srcBuffer;
181     uint32_t srcBufferStartOffset = 0;
182     uint32_t srcStride            = 0;
183     uint32_t srcDefaultAlphaData  = 0;  // casted as uint
184 
185     BufferRef dstBuffer;
186     uint32_t dstBufferStartOffset = 0;
187     uint32_t dstStride            = 0;
188     uint32_t dstComponents        = 0;
189 
190     uint32_t vertexCount = 0;
191 };
192 
193 // Utils class for clear & blitting
194 class ClearUtils final : angle::NonCopyable
195 {
196   public:
197     ClearUtils() = delete;
198     ClearUtils(const std::string &fragmentShaderName);
199     ClearUtils(const ClearUtils &src);
200 
201     void onDestroy();
202 
203     // Clear current framebuffer
204     angle::Result clearWithDraw(const gl::Context *context,
205                                 RenderCommandEncoder *cmdEncoder,
206                                 const ClearRectParams &params);
207 
208   private:
209     void ensureRenderPipelineStateCacheInitialized(ContextMtl *ctx, uint32_t numColorAttachments);
210 
211     angle::Result setupClearWithDraw(const gl::Context *context,
212                                      RenderCommandEncoder *cmdEncoder,
213                                      const ClearRectParams &params);
214     id<MTLDepthStencilState> getClearDepthStencilState(const gl::Context *context,
215                                                        const ClearRectParams &params);
216     id<MTLRenderPipelineState> getClearRenderPipelineState(const gl::Context *context,
217                                                            RenderCommandEncoder *cmdEncoder,
218                                                            const ClearRectParams &params);
219 
220     const std::string mFragmentShaderName;
221 
222     // Render pipeline cache for clear with draw:
223     std::array<RenderPipelineCache, kMaxRenderTargets + 1> mClearRenderPipelineCache;
224 };
225 
226 class ColorBlitUtils final : angle::NonCopyable
227 {
228   public:
229     ColorBlitUtils() = delete;
230     ColorBlitUtils(const std::string &fragmentShaderName);
231     ColorBlitUtils(const ColorBlitUtils &src);
232 
233     void onDestroy();
234 
235     // Blit texture data to current framebuffer
236     angle::Result blitColorWithDraw(const gl::Context *context,
237                                     RenderCommandEncoder *cmdEncoder,
238                                     const ColorBlitParams &params);
239 
240   private:
241     void ensureRenderPipelineStateCacheInitialized(ContextMtl *ctx,
242                                                    uint32_t numColorAttachments,
243                                                    int alphaPremultiplyType,
244                                                    int sourceTextureType,
245                                                    RenderPipelineCache *cacheOut);
246 
247     angle::Result setupColorBlitWithDraw(const gl::Context *context,
248                                          RenderCommandEncoder *cmdEncoder,
249                                          const ColorBlitParams &params);
250 
251     id<MTLRenderPipelineState> getColorBlitRenderPipelineState(const gl::Context *context,
252                                                                RenderCommandEncoder *cmdEncoder,
253                                                                const ColorBlitParams &params);
254 
255     const std::string mFragmentShaderName;
256 
257     // Blit with draw pipeline caches:
258     // First array dimension: number of outputs.
259     // Second array dimension: source texture type (2d, ms, array, 3d, etc)
260     using ColorBlitRenderPipelineCacheArray =
261         std::array<std::array<RenderPipelineCache, mtl_shader::kTextureTypeCount>,
262                    kMaxRenderTargets>;
263     ColorBlitRenderPipelineCacheArray mBlitRenderPipelineCache;
264     ColorBlitRenderPipelineCacheArray mBlitPremultiplyAlphaRenderPipelineCache;
265     ColorBlitRenderPipelineCacheArray mBlitUnmultiplyAlphaRenderPipelineCache;
266 };
267 
268 class DepthStencilBlitUtils final : angle::NonCopyable
269 {
270   public:
271     void onDestroy();
272 
273     angle::Result blitDepthStencilWithDraw(const gl::Context *context,
274                                            RenderCommandEncoder *cmdEncoder,
275                                            const DepthStencilBlitParams &params);
276 
277     // Blit stencil data using intermediate buffer. This function is used on devices with no
278     // support for direct stencil write in shader. Thus an intermediate buffer storing copied
279     // stencil data is needed.
280     // NOTE: this function shares the params struct with depth & stencil blit, but depth texture
281     // parameter is not used. This function will break existing render pass.
282     angle::Result blitStencilViaCopyBuffer(const gl::Context *context,
283                                            const StencilBlitViaBufferParams &params);
284 
285   private:
286     void ensureRenderPipelineStateCacheInitialized(ContextMtl *ctx,
287                                                    int sourceDepthTextureType,
288                                                    int sourceStencilTextureType,
289                                                    RenderPipelineCache *cacheOut);
290 
291     angle::Result setupDepthStencilBlitWithDraw(const gl::Context *context,
292                                                 RenderCommandEncoder *cmdEncoder,
293                                                 const DepthStencilBlitParams &params);
294 
295     id<MTLRenderPipelineState> getDepthStencilBlitRenderPipelineState(
296         const gl::Context *context,
297         RenderCommandEncoder *cmdEncoder,
298         const DepthStencilBlitParams &params);
299 
300     id<MTLComputePipelineState> getStencilToBufferComputePipelineState(
301         ContextMtl *ctx,
302         const StencilBlitViaBufferParams &params);
303 
304     std::array<RenderPipelineCache, mtl_shader::kTextureTypeCount> mDepthBlitRenderPipelineCache;
305     std::array<RenderPipelineCache, mtl_shader::kTextureTypeCount> mStencilBlitRenderPipelineCache;
306     std::array<std::array<RenderPipelineCache, mtl_shader::kTextureTypeCount>,
307                mtl_shader::kTextureTypeCount>
308         mDepthStencilBlitRenderPipelineCache;
309 
310     std::array<AutoObjCPtr<id<MTLComputePipelineState>>, mtl_shader::kTextureTypeCount>
311         mStencilBlitToBufferComPipelineCache;
312 
313     // Intermediate buffer for storing copied stencil data. Used when device doesn't support
314     // writing stencil in shader.
315     BufferRef mStencilCopyBuffer;
316 };
317 
318 // util class for generating index buffer
319 class IndexGeneratorUtils final : angle::NonCopyable
320 {
321   public:
322     void onDestroy();
323 
324     angle::Result convertIndexBufferGPU(ContextMtl *contextMtl,
325                                         const IndexConversionParams &params);
326     angle::Result generateTriFanBufferFromArrays(ContextMtl *contextMtl,
327                                                  const TriFanOrLineLoopFromArrayParams &params);
328     // Generate triangle fan index buffer for glDrawElements().
329     angle::Result generateTriFanBufferFromElementsArray(ContextMtl *contextMtl,
330                                                         const IndexGenerationParams &params,
331                                                         uint32_t *indicesGenerated);
332 
333     angle::Result generateLineLoopBufferFromArrays(ContextMtl *contextMtl,
334                                                    const TriFanOrLineLoopFromArrayParams &params);
335     angle::Result generateLineLoopLastSegment(ContextMtl *contextMtl,
336                                               uint32_t firstVertex,
337                                               uint32_t lastVertex,
338                                               const BufferRef &dstBuffer,
339                                               uint32_t dstOffset);
340     // Generate line loop index buffer for glDrawElements().
341     // Destination buffer must have at least 2x the number of original indices if primitive restart
342     // is enabled.
343     angle::Result generateLineLoopBufferFromElementsArray(ContextMtl *contextMtl,
344                                                           const IndexGenerationParams &params,
345                                                           uint32_t *indicesGenerated);
346     // Generate line loop's last segment index buffer for glDrawElements().
347     // NOTE: this function assumes primitive restart is not enabled.
348     angle::Result generateLineLoopLastSegmentFromElementsArray(ContextMtl *contextMtl,
349                                                                const IndexGenerationParams &params);
350 
351     angle::Result generatePrimitiveRestartPointsBuffer(ContextMtl *contextMtl,
352                                                        const IndexGenerationParams &params,
353                                                        size_t *indicesGenerated);
354 
355     angle::Result generatePrimitiveRestartLinesBuffer(ContextMtl *contextMtl,
356                                                       const IndexGenerationParams &params,
357                                                       size_t *indicesGenerated);
358 
359     angle::Result generatePrimitiveRestartTrianglesBuffer(ContextMtl *contextMtl,
360                                                           const IndexGenerationParams &params,
361                                                           size_t *indicesGenerated);
362 
363   private:
364     // Index generator compute pipelines:
365     //  - First dimension: index type.
366     //  - second dimension: source buffer's offset is aligned or not.
367     using IndexConversionPipelineArray =
368         std::array<std::array<AutoObjCPtr<id<MTLComputePipelineState>>, 2>,
369                    angle::EnumSize<gl::DrawElementsType>()>;
370 
371     AutoObjCPtr<id<MTLComputePipelineState>> getIndexConversionPipeline(
372         ContextMtl *contextMtl,
373         gl::DrawElementsType srcType,
374         uint32_t srcOffset);
375     // Get compute pipeline to generate tri fan/line loop index for glDrawElements().
376     AutoObjCPtr<id<MTLComputePipelineState>> getIndicesFromElemArrayGeneratorPipeline(
377         ContextMtl *contextMtl,
378         gl::DrawElementsType srcType,
379         uint32_t srcOffset,
380         NSString *shaderName,
381         IndexConversionPipelineArray *pipelineCacheArray);
382     // Defer loading of compute pipeline to generate tri fan index for glDrawArrays().
383     void ensureTriFanFromArrayGeneratorInitialized(ContextMtl *contextMtl);
384     // Defer loading of compute pipeline to generate line loop index for glDrawArrays().
385     void ensureLineLoopFromArrayGeneratorInitialized(ContextMtl *contextMtl);
386 
387     angle::Result generateTriFanBufferFromElementsArrayGPU(
388         ContextMtl *contextMtl,
389         gl::DrawElementsType srcType,
390         uint32_t indexCount,
391         const BufferRef &srcBuffer,
392         uint32_t srcOffset,
393         const BufferRef &dstBuffer,
394         // Must be multiples of kIndexBufferOffsetAlignment
395         uint32_t dstOffset);
396     angle::Result generateTriFanBufferFromElementsArrayCPU(ContextMtl *contextMtl,
397                                                            const IndexGenerationParams &params,
398                                                            uint32_t *indicesGenerated);
399 
400     angle::Result generateLineLoopBufferFromElementsArrayGPU(
401         ContextMtl *contextMtl,
402         gl::DrawElementsType srcType,
403         uint32_t indexCount,
404         const BufferRef &srcBuffer,
405         uint32_t srcOffset,
406         const BufferRef &dstBuffer,
407         // Must be multiples of kIndexBufferOffsetAlignment
408         uint32_t dstOffset);
409     angle::Result generateLineLoopBufferFromElementsArrayCPU(ContextMtl *contextMtl,
410                                                              const IndexGenerationParams &params,
411                                                              uint32_t *indicesGenerated);
412     angle::Result generateLineLoopLastSegmentFromElementsArrayCPU(
413         ContextMtl *contextMtl,
414         const IndexGenerationParams &params);
415 
416     angle::Result generatePrimitiveRestartBuffer(ContextMtl *contextMtl,
417                                                  unsigned numVerticesPerPrimitive,
418                                                  const IndexGenerationParams &params,
419                                                  size_t *indicesGenerated);
420 
421     IndexConversionPipelineArray mIndexConversionPipelineCaches;
422 
423     IndexConversionPipelineArray mTriFanFromElemArrayGeneratorPipelineCaches;
424     AutoObjCPtr<id<MTLComputePipelineState>> mTriFanFromArraysGeneratorPipeline;
425 
426     IndexConversionPipelineArray mLineLoopFromElemArrayGeneratorPipelineCaches;
427     AutoObjCPtr<id<MTLComputePipelineState>> mLineLoopFromArraysGeneratorPipeline;
428 };
429 
430 // Util class for handling visibility query result
431 class VisibilityResultUtils final : angle::NonCopyable
432 {
433   public:
434     void onDestroy();
435 
436     void combineVisibilityResult(ContextMtl *contextMtl,
437                                  bool keepOldValue,
438                                  const VisibilityBufferOffsetsMtl &renderPassResultBufOffsets,
439                                  const BufferRef &renderPassResultBuf,
440                                  const BufferRef &finalResultBuf);
441 
442   private:
443     AutoObjCPtr<id<MTLComputePipelineState>> getVisibilityResultCombPipeline(ContextMtl *contextMtl,
444                                                                              bool keepOldValue);
445     // Visibility combination compute pipeline:
446     // - 0: This compute pipeline only combine the new values and discard old value.
447     // - 1: This compute pipeline keep the old value and combine with new values.
448     std::array<AutoObjCPtr<id<MTLComputePipelineState>>, 2> mVisibilityResultCombPipelines;
449 };
450 
451 // Util class for handling mipmap generation
452 class MipmapUtils final : angle::NonCopyable
453 {
454   public:
455     void onDestroy();
456 
457     // Compute based mipmap generation.
458     angle::Result generateMipmapCS(ContextMtl *contextMtl,
459                                    const TextureRef &srcTexture,
460                                    bool sRGBMipmap,
461                                    NativeTexLevelArray *mipmapOutputViews);
462 
463   private:
464     void ensure3DMipGeneratorPipelineInitialized(ContextMtl *contextMtl);
465     void ensure2DMipGeneratorPipelineInitialized(ContextMtl *contextMtl);
466     void ensure2DArrayMipGeneratorPipelineInitialized(ContextMtl *contextMtl);
467     void ensureCubeMipGeneratorPipelineInitialized(ContextMtl *contextMtl);
468 
469     // Mipmaps generating compute pipeline:
470     AutoObjCPtr<id<MTLComputePipelineState>> m3DMipGeneratorPipeline;
471     AutoObjCPtr<id<MTLComputePipelineState>> m2DMipGeneratorPipeline;
472     AutoObjCPtr<id<MTLComputePipelineState>> m2DArrayMipGeneratorPipeline;
473     AutoObjCPtr<id<MTLComputePipelineState>> mCubeMipGeneratorPipeline;
474 };
475 
476 // Util class for handling pixels copy between buffers and textures
477 class CopyPixelsUtils final : angle::NonCopyable
478 {
479   public:
480     CopyPixelsUtils() = default;
481     CopyPixelsUtils(const std::string &readShaderName, const std::string &writeShaderName);
482     CopyPixelsUtils(const CopyPixelsUtils &src);
483 
484     void onDestroy();
485 
486     angle::Result unpackPixelsFromBufferToTexture(ContextMtl *contextMtl,
487                                                   const angle::Format &srcAngleFormat,
488                                                   const CopyPixelsFromBufferParams &params);
489     angle::Result packPixelsFromTextureToBuffer(ContextMtl *contextMtl,
490                                                 const angle::Format &dstAngleFormat,
491                                                 const CopyPixelsToBufferParams &params);
492 
493   private:
494     AutoObjCPtr<id<MTLComputePipelineState>> getPixelsCopyPipeline(ContextMtl *contextMtl,
495                                                                    const angle::Format &angleFormat,
496                                                                    const TextureRef &texture,
497                                                                    bool bufferWrite);
498     // Copy pixels between buffer and texture compute pipelines:
499     // - First dimension: pixel format.
500     // - Second dimension: texture type * (buffer read/write flag)
501     using PixelsCopyPipelineArray = std::array<
502         std::array<AutoObjCPtr<id<MTLComputePipelineState>>, mtl_shader::kTextureTypeCount * 2>,
503         angle::kNumANGLEFormats>;
504     PixelsCopyPipelineArray mPixelsCopyPipelineCaches;
505 
506     const std::string mReadShaderName;
507     const std::string mWriteShaderName;
508 };
509 
510 // Util class for handling vertex format conversion on GPU
511 class VertexFormatConversionUtils final : angle::NonCopyable
512 {
513   public:
514     void onDestroy();
515 
516     // Convert vertex format to float. Compute shader version.
517     angle::Result convertVertexFormatToFloatCS(ContextMtl *contextMtl,
518                                                const angle::Format &srcAngleFormat,
519                                                const VertexFormatConvertParams &params);
520     // Convert vertex format to float. Vertex shader version. This version should be used if
521     // a render pass is active and we don't want to break it. Explicit memory barrier must be
522     // supported.
523     angle::Result convertVertexFormatToFloatVS(const gl::Context *context,
524                                                RenderCommandEncoder *renderEncoder,
525                                                const angle::Format &srcAngleFormat,
526                                                const VertexFormatConvertParams &params);
527     // Expand number of components per vertex's attribute (or just simply copy components between
528     // buffers with different stride and offset)
529     angle::Result expandVertexFormatComponentsCS(ContextMtl *contextMtl,
530                                                  const angle::Format &srcAngleFormat,
531                                                  const VertexFormatConvertParams &params);
532     angle::Result expandVertexFormatComponentsVS(const gl::Context *context,
533                                                  RenderCommandEncoder *renderEncoder,
534                                                  const angle::Format &srcAngleFormat,
535                                                  const VertexFormatConvertParams &params);
536 
537   private:
538     void ensureComponentsExpandComputePipelineCreated(ContextMtl *contextMtl);
539     AutoObjCPtr<id<MTLRenderPipelineState>> getComponentsExpandRenderPipeline(
540         ContextMtl *contextMtl,
541         RenderCommandEncoder *renderEncoder);
542 
543     AutoObjCPtr<id<MTLComputePipelineState>> getFloatConverstionComputePipeline(
544         ContextMtl *contextMtl,
545         const angle::Format &srcAngleFormat);
546 
547     AutoObjCPtr<id<MTLRenderPipelineState>> getFloatConverstionRenderPipeline(
548         ContextMtl *contextMtl,
549         RenderCommandEncoder *renderEncoder,
550         const angle::Format &srcAngleFormat);
551 
552     template <typename EncoderType, typename PipelineType>
553     angle::Result setupCommonConvertVertexFormatToFloat(ContextMtl *contextMtl,
554                                                         EncoderType cmdEncoder,
555                                                         const PipelineType &pipeline,
556                                                         const angle::Format &srcAngleFormat,
557                                                         const VertexFormatConvertParams &params);
558     template <typename EncoderType, typename PipelineType>
559     angle::Result setupCommonExpandVertexFormatComponents(ContextMtl *contextMtl,
560                                                           EncoderType cmdEncoder,
561                                                           const PipelineType &pipeline,
562                                                           const angle::Format &srcAngleFormat,
563                                                           const VertexFormatConvertParams &params);
564 
565     using ConvertToFloatCompPipelineArray =
566         std::array<AutoObjCPtr<id<MTLComputePipelineState>>, angle::kNumANGLEFormats>;
567     using ConvertToFloatRenderPipelineArray =
568         std::array<RenderPipelineCache, angle::kNumANGLEFormats>;
569 
570     ConvertToFloatCompPipelineArray mConvertToFloatCompPipelineCaches;
571     ConvertToFloatRenderPipelineArray mConvertToFloatRenderPipelineCaches;
572 
573     AutoObjCPtr<id<MTLComputePipelineState>> mComponentsExpandCompPipeline;
574     RenderPipelineCache mComponentsExpandRenderPipelineCache;
575 };
576 
577 // RenderUtils: container class of various util classes above
578 class RenderUtils : public Context, angle::NonCopyable
579 {
580   public:
581     RenderUtils(DisplayMtl *display);
582     ~RenderUtils() override;
583 
584     angle::Result initialize();
585     void onDestroy();
586 
587     // Clear current framebuffer
588     angle::Result clearWithDraw(const gl::Context *context,
589                                 RenderCommandEncoder *cmdEncoder,
590                                 const ClearRectParams &params);
591     // Blit texture data to current framebuffer
592     angle::Result blitColorWithDraw(const gl::Context *context,
593                                     RenderCommandEncoder *cmdEncoder,
594                                     const angle::Format &srcAngleFormat,
595                                     const ColorBlitParams &params);
596     // Same as above but blit the whole texture to the whole of current framebuffer.
597     // This function assumes the framebuffer and the source texture have same size.
598     angle::Result blitColorWithDraw(const gl::Context *context,
599                                     RenderCommandEncoder *cmdEncoder,
600                                     const angle::Format &srcAngleFormat,
601                                     const TextureRef &srcTexture);
602     angle::Result copyTextureWithDraw(const gl::Context *context,
603                                       RenderCommandEncoder *cmdEncoder,
604                                       const angle::Format &srcAngleFormat,
605                                       const angle::Format &dstAngleFormat,
606                                       const ColorBlitParams &params);
607 
608     angle::Result blitDepthStencilWithDraw(const gl::Context *context,
609                                            RenderCommandEncoder *cmdEncoder,
610                                            const DepthStencilBlitParams &params);
611     // See DepthStencilBlitUtils::blitStencilViaCopyBuffer()
612     angle::Result blitStencilViaCopyBuffer(const gl::Context *context,
613                                            const StencilBlitViaBufferParams &params);
614 
615     // See IndexGeneratorUtils
616     angle::Result convertIndexBufferGPU(ContextMtl *contextMtl,
617                                         const IndexConversionParams &params);
618     angle::Result generateTriFanBufferFromArrays(ContextMtl *contextMtl,
619                                                  const TriFanOrLineLoopFromArrayParams &params);
620     angle::Result generateTriFanBufferFromElementsArray(ContextMtl *contextMtl,
621                                                         const IndexGenerationParams &params,
622                                                         uint32_t *indicesGenerated);
623 
624     angle::Result generateLineLoopBufferFromArrays(ContextMtl *contextMtl,
625                                                    const TriFanOrLineLoopFromArrayParams &params);
626     angle::Result generateLineLoopLastSegment(ContextMtl *contextMtl,
627                                               uint32_t firstVertex,
628                                               uint32_t lastVertex,
629                                               const BufferRef &dstBuffer,
630                                               uint32_t dstOffset);
631     angle::Result generateLineLoopBufferFromElementsArray(ContextMtl *contextMtl,
632                                                           const IndexGenerationParams &params,
633                                                           uint32_t *indicesGenerated);
634     angle::Result generateLineLoopLastSegmentFromElementsArray(ContextMtl *contextMtl,
635                                                                const IndexGenerationParams &params);
636 
637     void combineVisibilityResult(ContextMtl *contextMtl,
638                                  bool keepOldValue,
639                                  const VisibilityBufferOffsetsMtl &renderPassResultBufOffsets,
640                                  const BufferRef &renderPassResultBuf,
641                                  const BufferRef &finalResultBuf);
642 
643     // Compute based mipmap generation. Only possible for 3D texture for now.
644     angle::Result generateMipmapCS(ContextMtl *contextMtl,
645                                    const TextureRef &srcTexture,
646                                    bool sRGBMipmap,
647                                    NativeTexLevelArray *mipmapOutputViews);
648 
649     angle::Result unpackPixelsFromBufferToTexture(ContextMtl *contextMtl,
650                                                   const angle::Format &srcAngleFormat,
651                                                   const CopyPixelsFromBufferParams &params);
652     angle::Result packPixelsFromTextureToBuffer(ContextMtl *contextMtl,
653                                                 const angle::Format &dstAngleFormat,
654                                                 const CopyPixelsToBufferParams &params);
655 
656     // See VertexFormatConversionUtils::convertVertexFormatToFloatCS()
657     angle::Result convertVertexFormatToFloatCS(ContextMtl *contextMtl,
658                                                const angle::Format &srcAngleFormat,
659                                                const VertexFormatConvertParams &params);
660     // See VertexFormatConversionUtils::convertVertexFormatToFloatVS()
661     angle::Result convertVertexFormatToFloatVS(const gl::Context *context,
662                                                RenderCommandEncoder *renderEncoder,
663                                                const angle::Format &srcAngleFormat,
664                                                const VertexFormatConvertParams &params);
665     // See VertexFormatConversionUtils::expandVertexFormatComponentsCS()
666     angle::Result expandVertexFormatComponentsCS(ContextMtl *contextMtl,
667                                                  const angle::Format &srcAngleFormat,
668                                                  const VertexFormatConvertParams &params);
669     // See VertexFormatConversionUtils::expandVertexFormatComponentsVS()
670     angle::Result expandVertexFormatComponentsVS(const gl::Context *context,
671                                                  RenderCommandEncoder *renderEncoder,
672                                                  const angle::Format &srcAngleFormat,
673                                                  const VertexFormatConvertParams &params);
674 
675     angle::Result generatePrimitiveRestartPointsBuffer(ContextMtl *contextMtl,
676                                                        const IndexGenerationParams &params,
677                                                        size_t *indicesGenerated);
678     angle::Result generatePrimitiveRestartLinesBuffer(ContextMtl *contextMtl,
679                                                       const IndexGenerationParams &params,
680                                                       size_t *indicesGenerated);
681     angle::Result generatePrimitiveRestartTrianglesBuffer(ContextMtl *contextMtl,
682                                                           const IndexGenerationParams &params,
683                                                           size_t *indicesGenerated);
684 
685   private:
686     // override ErrorHandler
687     void handleError(GLenum error,
688                      const char *file,
689                      const char *function,
690                      unsigned int line) override;
691     void handleError(NSError *error,
692                      const char *file,
693                      const char *function,
694                      unsigned int line) override;
695 
696     std::array<ClearUtils, angle::EnumSize<PixelType>()> mClearUtils;
697 
698     std::array<ColorBlitUtils, angle::EnumSize<PixelType>()> mColorBlitUtils;
699     ColorBlitUtils mCopyTextureFloatToUIntUtils;
700 
701     DepthStencilBlitUtils mDepthStencilBlitUtils;
702     IndexGeneratorUtils mIndexUtils;
703     VisibilityResultUtils mVisibilityResultUtils;
704     MipmapUtils mMipmapUtils;
705     std::array<CopyPixelsUtils, angle::EnumSize<PixelType>()> mCopyPixelsUtils;
706     VertexFormatConversionUtils mVertexFormatUtils;
707 };
708 
709 }  // namespace mtl
710 }  // namespace rx
711 
712 #endif /* LIBANGLE_RENDERER_METAL_MTL_RENDER_UTILS_H_ */
713