• 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 
200     // Clear current framebuffer
201     angle::Result clearWithDraw(const gl::Context *context,
202                                 RenderCommandEncoder *cmdEncoder,
203                                 const ClearRectParams &params);
204 
205   private:
206     angle::Result ensureShadersInitialized(ContextMtl *ctx, uint32_t numColorAttachments);
207 
208     angle::Result setupClearWithDraw(const gl::Context *context,
209                                      RenderCommandEncoder *cmdEncoder,
210                                      const ClearRectParams &params);
211     id<MTLDepthStencilState> getClearDepthStencilState(const gl::Context *context,
212                                                        const ClearRectParams &params);
213     angle::Result getClearRenderPipelineState(
214         const gl::Context *context,
215         RenderCommandEncoder *cmdEncoder,
216         const ClearRectParams &params,
217         AutoObjCPtr<id<MTLRenderPipelineState>> *outPipelineState);
218 
219     const std::string mFragmentShaderName;
220 
221     AutoObjCPtr<id<MTLFunction>> mVertexShader;
222     std::array<AutoObjCPtr<id<MTLFunction>>, kMaxRenderTargets + 1> mFragmentShaders;
223 };
224 
225 class ColorBlitUtils final : angle::NonCopyable
226 {
227   public:
228     ColorBlitUtils() = delete;
229     ColorBlitUtils(const std::string &fragmentShaderName);
230 
231     // Blit texture data to current framebuffer
232     angle::Result blitColorWithDraw(const gl::Context *context,
233                                     RenderCommandEncoder *cmdEncoder,
234                                     const ColorBlitParams &params);
235 
236   private:
237     angle::Result ensureShadersInitialized(ContextMtl *ctx,
238                                            uint32_t numColorAttachments,
239                                            int alphaPremultiplyType,
240                                            int sourceTextureType,
241                                            AutoObjCPtr<id<MTLFunction>> *fragmentShaderOut);
242 
243     angle::Result setupColorBlitWithDraw(const gl::Context *context,
244                                          RenderCommandEncoder *cmdEncoder,
245                                          const ColorBlitParams &params);
246 
247     angle::Result getColorBlitRenderPipelineState(
248         const gl::Context *context,
249         RenderCommandEncoder *cmdEncoder,
250         const ColorBlitParams &params,
251         AutoObjCPtr<id<MTLRenderPipelineState>> *outPipelineState);
252 
253     const std::string mFragmentShaderName;
254 
255     AutoObjCPtr<id<MTLFunction>> mVertexShader;
256 
257     // Blit fragment shaders:
258     // First array dimension: number of outputs.
259     // Second array dimension: source texture type (2d, ms, array, 3d, etc)
260     using ColorBlitFragmentShaderArray =
261         std::array<std::array<AutoObjCPtr<id<MTLFunction>>, mtl_shader::kTextureTypeCount>,
262                    kMaxRenderTargets>;
263     ColorBlitFragmentShaderArray mBlitFragmentShaders;
264     ColorBlitFragmentShaderArray mBlitPremultiplyAlphaFragmentShaders;
265     ColorBlitFragmentShaderArray mBlitUnmultiplyAlphaFragmentShaders;
266 };
267 
268 class DepthStencilBlitUtils final : angle::NonCopyable
269 {
270   public:
271     angle::Result blitDepthStencilWithDraw(const gl::Context *context,
272                                            RenderCommandEncoder *cmdEncoder,
273                                            const DepthStencilBlitParams &params);
274 
275     // Blit stencil data using intermediate buffer. This function is used on devices with no
276     // support for direct stencil write in shader. Thus an intermediate buffer storing copied
277     // stencil data is needed.
278     // NOTE: this function shares the params struct with depth & stencil blit, but depth texture
279     // parameter is not used. This function will break existing render pass.
280     angle::Result blitStencilViaCopyBuffer(const gl::Context *context,
281                                            const StencilBlitViaBufferParams &params);
282 
283   private:
284     angle::Result ensureShadersInitialized(ContextMtl *ctx,
285                                            int sourceDepthTextureType,
286                                            int sourceStencilTextureType,
287                                            AutoObjCPtr<id<MTLFunction>> *fragmentShaderOut);
288 
289     angle::Result setupDepthStencilBlitWithDraw(const gl::Context *context,
290                                                 RenderCommandEncoder *cmdEncoder,
291                                                 const DepthStencilBlitParams &params);
292 
293     angle::Result getDepthStencilBlitRenderPipelineState(
294         const gl::Context *context,
295         RenderCommandEncoder *cmdEncoder,
296         const DepthStencilBlitParams &params,
297         AutoObjCPtr<id<MTLRenderPipelineState>> *outRenderPipelineState);
298 
299     angle::Result getStencilToBufferComputePipelineState(
300         ContextMtl *ctx,
301         const StencilBlitViaBufferParams &params,
302         AutoObjCPtr<id<MTLComputePipelineState>> *outComputePipelineState);
303 
304     AutoObjCPtr<id<MTLFunction>> mVertexShader;
305 
306     std::array<AutoObjCPtr<id<MTLFunction>>, mtl_shader::kTextureTypeCount>
307         mDepthBlitFragmentShaders;
308     std::array<AutoObjCPtr<id<MTLFunction>>, mtl_shader::kTextureTypeCount>
309         mStencilBlitFragmentShaders;
310     std::array<std::array<AutoObjCPtr<id<MTLFunction>>, mtl_shader::kTextureTypeCount>,
311                mtl_shader::kTextureTypeCount>
312         mDepthStencilBlitFragmentShaders;
313 
314     std::array<AutoObjCPtr<id<MTLFunction>>, mtl_shader::kTextureTypeCount>
315         mStencilBlitToBufferComputeShaders;
316 
317     // Intermediate buffer for storing copied stencil data. Used when device doesn't support
318     // writing stencil in shader.
319     BufferRef mStencilCopyBuffer;
320 };
321 
322 // util class for generating index buffer
323 class IndexGeneratorUtils final : angle::NonCopyable
324 {
325   public:
326     angle::Result convertIndexBufferGPU(ContextMtl *contextMtl,
327                                         const IndexConversionParams &params);
328     angle::Result generateTriFanBufferFromArrays(ContextMtl *contextMtl,
329                                                  const TriFanOrLineLoopFromArrayParams &params);
330     // Generate triangle fan index buffer for glDrawElements().
331     angle::Result generateTriFanBufferFromElementsArray(ContextMtl *contextMtl,
332                                                         const IndexGenerationParams &params,
333                                                         uint32_t *indicesGenerated);
334 
335     angle::Result generateLineLoopBufferFromArrays(ContextMtl *contextMtl,
336                                                    const TriFanOrLineLoopFromArrayParams &params);
337     angle::Result generateLineLoopLastSegment(ContextMtl *contextMtl,
338                                               uint32_t firstVertex,
339                                               uint32_t lastVertex,
340                                               const BufferRef &dstBuffer,
341                                               uint32_t dstOffset);
342     // Generate line loop index buffer for glDrawElements().
343     // Destination buffer must have at least 2x the number of original indices if primitive restart
344     // is enabled.
345     angle::Result generateLineLoopBufferFromElementsArray(ContextMtl *contextMtl,
346                                                           const IndexGenerationParams &params,
347                                                           uint32_t *indicesGenerated);
348     // Generate line loop's last segment index buffer for glDrawElements().
349     // NOTE: this function assumes primitive restart is not enabled.
350     angle::Result generateLineLoopLastSegmentFromElementsArray(ContextMtl *contextMtl,
351                                                                const IndexGenerationParams &params);
352 
353     angle::Result generatePrimitiveRestartPointsBuffer(ContextMtl *contextMtl,
354                                                        const IndexGenerationParams &params,
355                                                        size_t *indicesGenerated);
356 
357     angle::Result generatePrimitiveRestartLinesBuffer(ContextMtl *contextMtl,
358                                                       const IndexGenerationParams &params,
359                                                       size_t *indicesGenerated);
360 
361     angle::Result generatePrimitiveRestartTrianglesBuffer(ContextMtl *contextMtl,
362                                                           const IndexGenerationParams &params,
363                                                           size_t *indicesGenerated);
364 
365   private:
366     // Index generator compute shaders:
367     //  - First dimension: index type.
368     //  - second dimension: source buffer's offset is aligned or not.
369     using IndexConversionShaderArray = std::array<std::array<AutoObjCPtr<id<MTLFunction>>, 2>,
370                                                   angle::EnumSize<gl::DrawElementsType>()>;
371 
372     angle::Result getIndexConversionPipeline(
373         ContextMtl *contextMtl,
374         gl::DrawElementsType srcType,
375         uint32_t srcOffset,
376         AutoObjCPtr<id<MTLComputePipelineState>> *outComputePipeline);
377     // Get compute pipeline to generate tri fan/line loop index for glDrawElements().
378     angle::Result getIndicesFromElemArrayGeneratorPipeline(
379         ContextMtl *contextMtl,
380         gl::DrawElementsType srcType,
381         uint32_t srcOffset,
382         NSString *shaderName,
383         IndexConversionShaderArray *pipelineCacheArray,
384         AutoObjCPtr<id<MTLComputePipelineState>> *outComputePipeline);
385     // Defer loading of compute pipeline to generate tri fan index for glDrawArrays().
386     angle::Result getTriFanFromArrayGeneratorPipeline(
387         ContextMtl *contextMtl,
388         AutoObjCPtr<id<MTLComputePipelineState>> *outComputePipeline);
389     // Defer loading of compute pipeline to generate line loop index for glDrawArrays().
390     angle::Result getLineLoopFromArrayGeneratorPipeline(
391         ContextMtl *contextMtl,
392         AutoObjCPtr<id<MTLComputePipelineState>> *outComputePipeline);
393 
394     angle::Result generateTriFanBufferFromElementsArrayGPU(
395         ContextMtl *contextMtl,
396         gl::DrawElementsType srcType,
397         uint32_t indexCount,
398         const BufferRef &srcBuffer,
399         uint32_t srcOffset,
400         const BufferRef &dstBuffer,
401         // Must be multiples of kIndexBufferOffsetAlignment
402         uint32_t dstOffset);
403     angle::Result generateTriFanBufferFromElementsArrayCPU(ContextMtl *contextMtl,
404                                                            const IndexGenerationParams &params,
405                                                            uint32_t *indicesGenerated);
406 
407     angle::Result generateLineLoopBufferFromElementsArrayGPU(
408         ContextMtl *contextMtl,
409         gl::DrawElementsType srcType,
410         uint32_t indexCount,
411         const BufferRef &srcBuffer,
412         uint32_t srcOffset,
413         const BufferRef &dstBuffer,
414         // Must be multiples of kIndexBufferOffsetAlignment
415         uint32_t dstOffset);
416     angle::Result generateLineLoopBufferFromElementsArrayCPU(ContextMtl *contextMtl,
417                                                              const IndexGenerationParams &params,
418                                                              uint32_t *indicesGenerated);
419     angle::Result generateLineLoopLastSegmentFromElementsArrayCPU(
420         ContextMtl *contextMtl,
421         const IndexGenerationParams &params);
422 
423     angle::Result generatePrimitiveRestartBuffer(ContextMtl *contextMtl,
424                                                  unsigned numVerticesPerPrimitive,
425                                                  const IndexGenerationParams &params,
426                                                  size_t *indicesGenerated);
427 
428     IndexConversionShaderArray mIndexConversionShaders;
429 
430     IndexConversionShaderArray mTriFanFromElemArrayGeneratorShaders;
431     AutoObjCPtr<id<MTLFunction>> mTriFanFromArraysGeneratorShader;
432 
433     IndexConversionShaderArray mLineLoopFromElemArrayGeneratorShaders;
434     AutoObjCPtr<id<MTLFunction>> mLineLoopFromArraysGeneratorShader;
435 };
436 
437 // Util class for handling visibility query result
438 class VisibilityResultUtils final : angle::NonCopyable
439 {
440   public:
441     angle::Result combineVisibilityResult(
442         ContextMtl *contextMtl,
443         bool keepOldValue,
444         const VisibilityBufferOffsetsMtl &renderPassResultBufOffsets,
445         const BufferRef &renderPassResultBuf,
446         const BufferRef &finalResultBuf);
447 
448   private:
449     angle::Result getVisibilityResultCombinePipeline(
450         ContextMtl *contextMtl,
451         bool keepOldValue,
452         AutoObjCPtr<id<MTLComputePipelineState>> *outComputePipeline);
453     // Visibility combination compute shaders:
454     // - 0: This compute shader only combines the new values and discard old value.
455     // - 1: This compute shader keep the old value and combines with new values.
456     std::array<AutoObjCPtr<id<MTLFunction>>, 2> mVisibilityResultCombineComputeShaders;
457 };
458 
459 // Util class for handling mipmap generation
460 class MipmapUtils final : angle::NonCopyable
461 {
462   public:
463     // Compute based mipmap generation.
464     angle::Result generateMipmapCS(ContextMtl *contextMtl,
465                                    const TextureRef &srcTexture,
466                                    bool sRGBMipmap,
467                                    NativeTexLevelArray *mipmapOutputViews);
468 
469   private:
470     angle::Result get3DMipGeneratorPipeline(
471         ContextMtl *contextMtl,
472         AutoObjCPtr<id<MTLComputePipelineState>> *outComputePipeline);
473     angle::Result get2DMipGeneratorPipeline(
474         ContextMtl *contextMtl,
475         AutoObjCPtr<id<MTLComputePipelineState>> *outComputePipeline);
476     angle::Result get2DArrayMipGeneratorPipeline(
477         ContextMtl *contextMtl,
478         AutoObjCPtr<id<MTLComputePipelineState>> *outComputePipeline);
479     angle::Result getCubeMipGeneratorPipeline(
480         ContextMtl *contextMtl,
481         AutoObjCPtr<id<MTLComputePipelineState>> *outComputePipeline);
482 
483     // Mipmaps generating compute pipeline:
484     AutoObjCPtr<id<MTLFunction>> m3DMipGeneratorShader;
485     AutoObjCPtr<id<MTLFunction>> m2DMipGeneratorShader;
486     AutoObjCPtr<id<MTLFunction>> m2DArrayMipGeneratorShader;
487     AutoObjCPtr<id<MTLFunction>> mCubeMipGeneratorShader;
488 };
489 
490 // Util class for handling pixels copy between buffers and textures
491 class CopyPixelsUtils final : angle::NonCopyable
492 {
493   public:
494     CopyPixelsUtils() = default;
495     CopyPixelsUtils(const std::string &readShaderName, const std::string &writeShaderName);
496 
497     angle::Result unpackPixelsFromBufferToTexture(ContextMtl *contextMtl,
498                                                   const angle::Format &srcAngleFormat,
499                                                   const CopyPixelsFromBufferParams &params);
500     angle::Result packPixelsFromTextureToBuffer(ContextMtl *contextMtl,
501                                                 const angle::Format &dstAngleFormat,
502                                                 const CopyPixelsToBufferParams &params);
503 
504   private:
505     angle::Result getPixelsCopyPipeline(
506         ContextMtl *contextMtl,
507         const angle::Format &angleFormat,
508         const TextureRef &texture,
509         bool bufferWrite,
510         AutoObjCPtr<id<MTLComputePipelineState>> *outComputePipeline);
511     // Copy pixels between buffer and texture compute pipelines:
512     // - First dimension: pixel format.
513     // - Second dimension: texture type * (buffer read/write flag)
514     using PixelsCopyComputeShaderArray =
515         std::array<std::array<AutoObjCPtr<id<MTLFunction>>, mtl_shader::kTextureTypeCount * 2>,
516                    angle::kNumANGLEFormats>;
517     PixelsCopyComputeShaderArray mPixelsCopyComputeShaders;
518 
519     const std::string mReadShaderName;
520     const std::string mWriteShaderName;
521 };
522 
523 // Util class for handling vertex format conversion on GPU
524 class VertexFormatConversionUtils final : angle::NonCopyable
525 {
526   public:
527     // Convert vertex format to float. Compute shader version.
528     angle::Result convertVertexFormatToFloatCS(ContextMtl *contextMtl,
529                                                const angle::Format &srcAngleFormat,
530                                                const VertexFormatConvertParams &params);
531     // Convert vertex format to float. Vertex shader version. This version should be used if
532     // a render pass is active and we don't want to break it. Explicit memory barrier must be
533     // supported.
534     angle::Result convertVertexFormatToFloatVS(const gl::Context *context,
535                                                RenderCommandEncoder *renderEncoder,
536                                                const angle::Format &srcAngleFormat,
537                                                const VertexFormatConvertParams &params);
538     // Expand number of components per vertex's attribute (or just simply copy components between
539     // buffers with different stride and offset)
540     angle::Result expandVertexFormatComponentsCS(ContextMtl *contextMtl,
541                                                  const angle::Format &srcAngleFormat,
542                                                  const VertexFormatConvertParams &params);
543     angle::Result expandVertexFormatComponentsVS(const gl::Context *context,
544                                                  RenderCommandEncoder *renderEncoder,
545                                                  const angle::Format &srcAngleFormat,
546                                                  const VertexFormatConvertParams &params);
547 
548   private:
549     angle::Result getComponentsExpandComputePipeline(
550         ContextMtl *contextMtl,
551         AutoObjCPtr<id<MTLComputePipelineState>> *outPipelineState);
552     angle::Result getComponentsExpandRenderPipeline(
553         ContextMtl *contextMtl,
554         RenderCommandEncoder *renderEncoder,
555         AutoObjCPtr<id<MTLRenderPipelineState>> *outPipelineState);
556 
557     angle::Result getFloatConverstionComputePipeline(
558         ContextMtl *contextMtl,
559         const angle::Format &srcAngleFormat,
560         AutoObjCPtr<id<MTLComputePipelineState>> *outPipelineState);
561 
562     angle::Result getFloatConverstionRenderPipeline(
563         ContextMtl *contextMtl,
564         RenderCommandEncoder *renderEncoder,
565         const angle::Format &srcAngleFormat,
566         AutoObjCPtr<id<MTLRenderPipelineState>> *outPipelineState);
567 
568     template <typename EncoderType, typename PipelineType>
569     angle::Result setupCommonConvertVertexFormatToFloat(ContextMtl *contextMtl,
570                                                         EncoderType cmdEncoder,
571                                                         const PipelineType &pipeline,
572                                                         const angle::Format &srcAngleFormat,
573                                                         const VertexFormatConvertParams &params);
574     template <typename EncoderType, typename PipelineType>
575     angle::Result setupCommonExpandVertexFormatComponents(ContextMtl *contextMtl,
576                                                           EncoderType cmdEncoder,
577                                                           const PipelineType &pipeline,
578                                                           const angle::Format &srcAngleFormat,
579                                                           const VertexFormatConvertParams &params);
580 
581     using ConvertToFloatComputeShaderArray =
582         std::array<AutoObjCPtr<id<MTLFunction>>, angle::kNumANGLEFormats>;
583     using ConvertToFloatVertexShaderArray =
584         std::array<AutoObjCPtr<id<MTLFunction>>, angle::kNumANGLEFormats>;
585 
586     ConvertToFloatComputeShaderArray mConvertToFloatCompPipelineCaches;
587     ConvertToFloatVertexShaderArray mConvertToFloatVertexShaders;
588 
589     AutoObjCPtr<id<MTLFunction>> mComponentsExpandComputeShader;
590     AutoObjCPtr<id<MTLFunction>> mComponentsExpandVertexShader;
591 };
592 
593 // RenderUtils: container class of various util classes above
594 class RenderUtils : public Context, angle::NonCopyable
595 {
596   public:
597     RenderUtils(DisplayMtl *display);
598     ~RenderUtils() override;
599 
600     // Clear current framebuffer
601     angle::Result clearWithDraw(const gl::Context *context,
602                                 RenderCommandEncoder *cmdEncoder,
603                                 const ClearRectParams &params);
604     // Blit texture data to current framebuffer
605     angle::Result blitColorWithDraw(const gl::Context *context,
606                                     RenderCommandEncoder *cmdEncoder,
607                                     const angle::Format &srcAngleFormat,
608                                     const ColorBlitParams &params);
609     // Same as above but blit the whole texture to the whole of current framebuffer.
610     // This function assumes the framebuffer and the source texture have same size.
611     angle::Result blitColorWithDraw(const gl::Context *context,
612                                     RenderCommandEncoder *cmdEncoder,
613                                     const angle::Format &srcAngleFormat,
614                                     const TextureRef &srcTexture);
615     angle::Result copyTextureWithDraw(const gl::Context *context,
616                                       RenderCommandEncoder *cmdEncoder,
617                                       const angle::Format &srcAngleFormat,
618                                       const angle::Format &dstAngleFormat,
619                                       const ColorBlitParams &params);
620 
621     angle::Result blitDepthStencilWithDraw(const gl::Context *context,
622                                            RenderCommandEncoder *cmdEncoder,
623                                            const DepthStencilBlitParams &params);
624     // See DepthStencilBlitUtils::blitStencilViaCopyBuffer()
625     angle::Result blitStencilViaCopyBuffer(const gl::Context *context,
626                                            const StencilBlitViaBufferParams &params);
627 
628     // See IndexGeneratorUtils
629     angle::Result convertIndexBufferGPU(ContextMtl *contextMtl,
630                                         const IndexConversionParams &params);
631     angle::Result generateTriFanBufferFromArrays(ContextMtl *contextMtl,
632                                                  const TriFanOrLineLoopFromArrayParams &params);
633     angle::Result generateTriFanBufferFromElementsArray(ContextMtl *contextMtl,
634                                                         const IndexGenerationParams &params,
635                                                         uint32_t *indicesGenerated);
636 
637     angle::Result generateLineLoopBufferFromArrays(ContextMtl *contextMtl,
638                                                    const TriFanOrLineLoopFromArrayParams &params);
639     angle::Result generateLineLoopLastSegment(ContextMtl *contextMtl,
640                                               uint32_t firstVertex,
641                                               uint32_t lastVertex,
642                                               const BufferRef &dstBuffer,
643                                               uint32_t dstOffset);
644     angle::Result generateLineLoopBufferFromElementsArray(ContextMtl *contextMtl,
645                                                           const IndexGenerationParams &params,
646                                                           uint32_t *indicesGenerated);
647     angle::Result generateLineLoopLastSegmentFromElementsArray(ContextMtl *contextMtl,
648                                                                const IndexGenerationParams &params);
649 
650     void combineVisibilityResult(ContextMtl *contextMtl,
651                                  bool keepOldValue,
652                                  const VisibilityBufferOffsetsMtl &renderPassResultBufOffsets,
653                                  const BufferRef &renderPassResultBuf,
654                                  const BufferRef &finalResultBuf);
655 
656     // Compute based mipmap generation. Only possible for 3D texture for now.
657     angle::Result generateMipmapCS(ContextMtl *contextMtl,
658                                    const TextureRef &srcTexture,
659                                    bool sRGBMipmap,
660                                    NativeTexLevelArray *mipmapOutputViews);
661 
662     angle::Result unpackPixelsFromBufferToTexture(ContextMtl *contextMtl,
663                                                   const angle::Format &srcAngleFormat,
664                                                   const CopyPixelsFromBufferParams &params);
665     angle::Result packPixelsFromTextureToBuffer(ContextMtl *contextMtl,
666                                                 const angle::Format &dstAngleFormat,
667                                                 const CopyPixelsToBufferParams &params);
668 
669     // See VertexFormatConversionUtils::convertVertexFormatToFloatCS()
670     angle::Result convertVertexFormatToFloatCS(ContextMtl *contextMtl,
671                                                const angle::Format &srcAngleFormat,
672                                                const VertexFormatConvertParams &params);
673     // See VertexFormatConversionUtils::convertVertexFormatToFloatVS()
674     angle::Result convertVertexFormatToFloatVS(const gl::Context *context,
675                                                RenderCommandEncoder *renderEncoder,
676                                                const angle::Format &srcAngleFormat,
677                                                const VertexFormatConvertParams &params);
678     // See VertexFormatConversionUtils::expandVertexFormatComponentsCS()
679     angle::Result expandVertexFormatComponentsCS(ContextMtl *contextMtl,
680                                                  const angle::Format &srcAngleFormat,
681                                                  const VertexFormatConvertParams &params);
682     // See VertexFormatConversionUtils::expandVertexFormatComponentsVS()
683     angle::Result expandVertexFormatComponentsVS(const gl::Context *context,
684                                                  RenderCommandEncoder *renderEncoder,
685                                                  const angle::Format &srcAngleFormat,
686                                                  const VertexFormatConvertParams &params);
687 
688     angle::Result generatePrimitiveRestartPointsBuffer(ContextMtl *contextMtl,
689                                                        const IndexGenerationParams &params,
690                                                        size_t *indicesGenerated);
691     angle::Result generatePrimitiveRestartLinesBuffer(ContextMtl *contextMtl,
692                                                       const IndexGenerationParams &params,
693                                                       size_t *indicesGenerated);
694     angle::Result generatePrimitiveRestartTrianglesBuffer(ContextMtl *contextMtl,
695                                                           const IndexGenerationParams &params,
696                                                           size_t *indicesGenerated);
697 
698   private:
699     // override ErrorHandler
700     void handleError(GLenum error,
701                      const char *message,
702                      const char *file,
703                      const char *function,
704                      unsigned int line) override;
705     void handleError(NSError *error,
706                      const char *message,
707                      const char *file,
708                      const char *function,
709                      unsigned int line) override;
710 
711     std::array<ClearUtils, angle::EnumSize<PixelType>()> mClearUtils;
712 
713     std::array<ColorBlitUtils, angle::EnumSize<PixelType>()> mColorBlitUtils;
714     ColorBlitUtils mCopyTextureFloatToUIntUtils;
715 
716     DepthStencilBlitUtils mDepthStencilBlitUtils;
717     IndexGeneratorUtils mIndexUtils;
718     VisibilityResultUtils mVisibilityResultUtils;
719     MipmapUtils mMipmapUtils;
720     std::array<CopyPixelsUtils, angle::EnumSize<PixelType>()> mCopyPixelsUtils;
721     VertexFormatConversionUtils mVertexFormatUtils;
722 };
723 
724 }  // namespace mtl
725 }  // namespace rx
726 
727 #endif /* LIBANGLE_RENDERER_METAL_MTL_RENDER_UTILS_H_ */
728