// // Copyright 2019 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // mtl_render_utils.h: // Defines the class interface for RenderUtils, which contains many utility functions and shaders // for converting, blitting, copying as well as generating data, and many more. // #ifndef LIBANGLE_RENDERER_METAL_MTL_RENDER_UTILS_H_ #define LIBANGLE_RENDERER_METAL_MTL_RENDER_UTILS_H_ #import #include "libANGLE/angletypes.h" #include "libANGLE/renderer/metal/RenderTargetMtl.h" #include "libANGLE/renderer/metal/mtl_command_buffer.h" #include "libANGLE/renderer/metal/mtl_context_device.h" #include "libANGLE/renderer/metal/mtl_state_cache.h" #include "libANGLE/renderer/metal/shaders/constants.h" namespace rx { class BufferMtl; class ContextMtl; class DisplayMtl; class VisibilityBufferOffsetsMtl; namespace mtl { struct ClearRectParams { ClearRectParams() { clearWriteMaskArray.fill(MTLColorWriteMaskAll); } Optional clearColor; Optional clearDepth; Optional clearStencil; WriteMaskArray clearWriteMaskArray; const mtl::Format *colorFormat = nullptr; gl::Extents dstTextureSize; // Only clear enabled buffers gl::DrawBufferMask enabledBuffers; gl::Rectangle clearArea; bool flipY = false; }; struct NormalizedCoords { NormalizedCoords(); NormalizedCoords(float x, float y, float width, float height, const gl::Rectangle &rect); NormalizedCoords(const gl::Rectangle &rect, const gl::Extents &extents); float v[4]; }; struct BlitParams { gl::Extents dstTextureSize; gl::Rectangle dstRect; gl::Rectangle dstScissorRect; // Destination texture needs to have viewport Y flipped? // The difference between this param and unpackFlipY is that unpackFlipY is from // glCopyImageCHROMIUM()/glBlitFramebuffer(), and dstFlipY controls whether the final viewport // needs to be flipped when drawing to destination texture. It is possible to combine the two // flags before passing to RenderUtils. However, to avoid duplicated works, just pass the two // flags to RenderUtils, they will be combined internally by RenderUtils logic. bool dstFlipY = false; bool dstFlipX = false; TextureRef src; MipmapNativeLevel srcLevel = kZeroNativeMipLevel; uint32_t srcLayer = 0; // Source rectangle: // NOTE: if srcYFlipped=true, this rectangle will be converted internally to flipped rect before // blitting. NormalizedCoords srcNormalizedCoords; bool srcYFlipped = false; // source texture has data flipped in Y direction bool unpackFlipX = false; // flip texture data copying process in X direction bool unpackFlipY = false; // flip texture data copying process in Y direction }; struct ColorBlitParams : public BlitParams { ColorBlitParams() {} gl::DrawBufferMask enabledBuffers; GLenum filter = GL_NEAREST; bool unpackPremultiplyAlpha = false; bool unpackUnmultiplyAlpha = false; bool dstLuminance = false; }; struct DepthStencilBlitParams : public BlitParams { TextureRef srcStencil; }; // Stencil blit via an intermediate buffer. NOTE: source depth texture parameter is ignored. // See DepthStencilBlitUtils::blitStencilViaCopyBuffer() struct StencilBlitViaBufferParams : public DepthStencilBlitParams { StencilBlitViaBufferParams(); StencilBlitViaBufferParams(const DepthStencilBlitParams &src); TextureRef dstStencil; MipmapNativeLevel dstStencilLevel = kZeroNativeMipLevel; uint32_t dstStencilLayer = 0; bool dstPackedDepthStencilFormat = false; }; struct TriFanOrLineLoopFromArrayParams { uint32_t firstVertex; uint32_t vertexCount; BufferRef dstBuffer; // Must be multiples of kIndexBufferOffsetAlignment uint32_t dstOffset; }; struct IndexConversionParams { gl::DrawElementsType srcType; uint32_t indexCount; const BufferRef &srcBuffer; uint32_t srcOffset; const BufferRef &dstBuffer; // Must be multiples of kIndexBufferOffsetAlignment uint32_t dstOffset; bool primitiveRestartEnabled = false; }; struct IndexGenerationParams { gl::DrawElementsType srcType; GLsizei indexCount; const void *indices; BufferRef dstBuffer; uint32_t dstOffset; bool primitiveRestartEnabled = false; }; struct CopyPixelsCommonParams { BufferRef buffer; uint32_t bufferStartOffset = 0; uint32_t bufferRowPitch = 0; TextureRef texture; }; struct CopyPixelsFromBufferParams : CopyPixelsCommonParams { uint32_t bufferDepthPitch = 0; // z offset is: // - slice index if texture is array. // - depth if texture is 3d. gl::Box textureArea; }; struct CopyPixelsToBufferParams : CopyPixelsCommonParams { gl::Rectangle textureArea; MipmapNativeLevel textureLevel = kZeroNativeMipLevel; uint32_t textureSliceOrDeph = 0; bool reverseTextureRowOrder; }; struct VertexFormatConvertParams { BufferRef srcBuffer; uint32_t srcBufferStartOffset = 0; uint32_t srcStride = 0; uint32_t srcDefaultAlphaData = 0; // casted as uint BufferRef dstBuffer; uint32_t dstBufferStartOffset = 0; uint32_t dstStride = 0; uint32_t dstComponents = 0; uint32_t vertexCount = 0; }; // Utils class for clear & blitting class ClearUtils final : angle::NonCopyable { public: ClearUtils() = delete; ClearUtils(const std::string &fragmentShaderName); // Clear current framebuffer angle::Result clearWithDraw(const gl::Context *context, RenderCommandEncoder *cmdEncoder, const ClearRectParams ¶ms); private: angle::Result ensureShadersInitialized(ContextMtl *ctx, uint32_t numColorAttachments); angle::Result setupClearWithDraw(const gl::Context *context, RenderCommandEncoder *cmdEncoder, const ClearRectParams ¶ms); id getClearDepthStencilState(const gl::Context *context, const ClearRectParams ¶ms); angle::Result getClearRenderPipelineState( const gl::Context *context, RenderCommandEncoder *cmdEncoder, const ClearRectParams ¶ms, AutoObjCPtr> *outPipelineState); const std::string mFragmentShaderName; AutoObjCPtr> mVertexShader; std::array>, kMaxRenderTargets + 1> mFragmentShaders; }; class ColorBlitUtils final : angle::NonCopyable { public: ColorBlitUtils() = delete; ColorBlitUtils(const std::string &fragmentShaderName); // Blit texture data to current framebuffer angle::Result blitColorWithDraw(const gl::Context *context, RenderCommandEncoder *cmdEncoder, const ColorBlitParams ¶ms); private: angle::Result ensureShadersInitialized(ContextMtl *ctx, uint32_t numColorAttachments, int alphaPremultiplyType, int sourceTextureType, AutoObjCPtr> *fragmentShaderOut); angle::Result setupColorBlitWithDraw(const gl::Context *context, RenderCommandEncoder *cmdEncoder, const ColorBlitParams ¶ms); angle::Result getColorBlitRenderPipelineState( const gl::Context *context, RenderCommandEncoder *cmdEncoder, const ColorBlitParams ¶ms, AutoObjCPtr> *outPipelineState); const std::string mFragmentShaderName; AutoObjCPtr> mVertexShader; // Blit fragment shaders: // First array dimension: number of outputs. // Second array dimension: source texture type (2d, ms, array, 3d, etc) using ColorBlitFragmentShaderArray = std::array>, mtl_shader::kTextureTypeCount>, kMaxRenderTargets>; ColorBlitFragmentShaderArray mBlitFragmentShaders; ColorBlitFragmentShaderArray mBlitPremultiplyAlphaFragmentShaders; ColorBlitFragmentShaderArray mBlitUnmultiplyAlphaFragmentShaders; }; class DepthStencilBlitUtils final : angle::NonCopyable { public: angle::Result blitDepthStencilWithDraw(const gl::Context *context, RenderCommandEncoder *cmdEncoder, const DepthStencilBlitParams ¶ms); // Blit stencil data using intermediate buffer. This function is used on devices with no // support for direct stencil write in shader. Thus an intermediate buffer storing copied // stencil data is needed. // NOTE: this function shares the params struct with depth & stencil blit, but depth texture // parameter is not used. This function will break existing render pass. angle::Result blitStencilViaCopyBuffer(const gl::Context *context, const StencilBlitViaBufferParams ¶ms); private: angle::Result ensureShadersInitialized(ContextMtl *ctx, int sourceDepthTextureType, int sourceStencilTextureType, AutoObjCPtr> *fragmentShaderOut); angle::Result setupDepthStencilBlitWithDraw(const gl::Context *context, RenderCommandEncoder *cmdEncoder, const DepthStencilBlitParams ¶ms); angle::Result getDepthStencilBlitRenderPipelineState( const gl::Context *context, RenderCommandEncoder *cmdEncoder, const DepthStencilBlitParams ¶ms, AutoObjCPtr> *outRenderPipelineState); angle::Result getStencilToBufferComputePipelineState( ContextMtl *ctx, const StencilBlitViaBufferParams ¶ms, AutoObjCPtr> *outComputePipelineState); AutoObjCPtr> mVertexShader; std::array>, mtl_shader::kTextureTypeCount> mDepthBlitFragmentShaders; std::array>, mtl_shader::kTextureTypeCount> mStencilBlitFragmentShaders; std::array>, mtl_shader::kTextureTypeCount>, mtl_shader::kTextureTypeCount> mDepthStencilBlitFragmentShaders; std::array>, mtl_shader::kTextureTypeCount> mStencilBlitToBufferComputeShaders; // Intermediate buffer for storing copied stencil data. Used when device doesn't support // writing stencil in shader. BufferRef mStencilCopyBuffer; }; // util class for generating index buffer class IndexGeneratorUtils final : angle::NonCopyable { public: angle::Result convertIndexBufferGPU(ContextMtl *contextMtl, const IndexConversionParams ¶ms); angle::Result generateTriFanBufferFromArrays(ContextMtl *contextMtl, const TriFanOrLineLoopFromArrayParams ¶ms); // Generate triangle fan index buffer for glDrawElements(). angle::Result generateTriFanBufferFromElementsArray(ContextMtl *contextMtl, const IndexGenerationParams ¶ms, uint32_t *indicesGenerated); angle::Result generateLineLoopBufferFromArrays(ContextMtl *contextMtl, const TriFanOrLineLoopFromArrayParams ¶ms); angle::Result generateLineLoopLastSegment(ContextMtl *contextMtl, uint32_t firstVertex, uint32_t lastVertex, const BufferRef &dstBuffer, uint32_t dstOffset); // Generate line loop index buffer for glDrawElements(). // Destination buffer must have at least 2x the number of original indices if primitive restart // is enabled. angle::Result generateLineLoopBufferFromElementsArray(ContextMtl *contextMtl, const IndexGenerationParams ¶ms, uint32_t *indicesGenerated); // Generate line loop's last segment index buffer for glDrawElements(). // NOTE: this function assumes primitive restart is not enabled. angle::Result generateLineLoopLastSegmentFromElementsArray(ContextMtl *contextMtl, const IndexGenerationParams ¶ms); angle::Result generatePrimitiveRestartPointsBuffer(ContextMtl *contextMtl, const IndexGenerationParams ¶ms, size_t *indicesGenerated); angle::Result generatePrimitiveRestartLinesBuffer(ContextMtl *contextMtl, const IndexGenerationParams ¶ms, size_t *indicesGenerated); angle::Result generatePrimitiveRestartTrianglesBuffer(ContextMtl *contextMtl, const IndexGenerationParams ¶ms, size_t *indicesGenerated); private: // Index generator compute shaders: // - First dimension: index type. // - second dimension: source buffer's offset is aligned or not. using IndexConversionShaderArray = std::array>, 2>, angle::EnumSize()>; angle::Result getIndexConversionPipeline( ContextMtl *contextMtl, gl::DrawElementsType srcType, uint32_t srcOffset, AutoObjCPtr> *outComputePipeline); // Get compute pipeline to generate tri fan/line loop index for glDrawElements(). angle::Result getIndicesFromElemArrayGeneratorPipeline( ContextMtl *contextMtl, gl::DrawElementsType srcType, uint32_t srcOffset, NSString *shaderName, IndexConversionShaderArray *pipelineCacheArray, AutoObjCPtr> *outComputePipeline); // Defer loading of compute pipeline to generate tri fan index for glDrawArrays(). angle::Result getTriFanFromArrayGeneratorPipeline( ContextMtl *contextMtl, AutoObjCPtr> *outComputePipeline); // Defer loading of compute pipeline to generate line loop index for glDrawArrays(). angle::Result getLineLoopFromArrayGeneratorPipeline( ContextMtl *contextMtl, AutoObjCPtr> *outComputePipeline); angle::Result generateTriFanBufferFromElementsArrayGPU( ContextMtl *contextMtl, gl::DrawElementsType srcType, uint32_t indexCount, const BufferRef &srcBuffer, uint32_t srcOffset, const BufferRef &dstBuffer, // Must be multiples of kIndexBufferOffsetAlignment uint32_t dstOffset); angle::Result generateTriFanBufferFromElementsArrayCPU(ContextMtl *contextMtl, const IndexGenerationParams ¶ms, uint32_t *indicesGenerated); angle::Result generateLineLoopBufferFromElementsArrayGPU( ContextMtl *contextMtl, gl::DrawElementsType srcType, uint32_t indexCount, const BufferRef &srcBuffer, uint32_t srcOffset, const BufferRef &dstBuffer, // Must be multiples of kIndexBufferOffsetAlignment uint32_t dstOffset); angle::Result generateLineLoopBufferFromElementsArrayCPU(ContextMtl *contextMtl, const IndexGenerationParams ¶ms, uint32_t *indicesGenerated); angle::Result generateLineLoopLastSegmentFromElementsArrayCPU( ContextMtl *contextMtl, const IndexGenerationParams ¶ms); angle::Result generatePrimitiveRestartBuffer(ContextMtl *contextMtl, unsigned numVerticesPerPrimitive, const IndexGenerationParams ¶ms, size_t *indicesGenerated); IndexConversionShaderArray mIndexConversionShaders; IndexConversionShaderArray mTriFanFromElemArrayGeneratorShaders; AutoObjCPtr> mTriFanFromArraysGeneratorShader; IndexConversionShaderArray mLineLoopFromElemArrayGeneratorShaders; AutoObjCPtr> mLineLoopFromArraysGeneratorShader; }; // Util class for handling visibility query result class VisibilityResultUtils final : angle::NonCopyable { public: angle::Result combineVisibilityResult( ContextMtl *contextMtl, bool keepOldValue, const VisibilityBufferOffsetsMtl &renderPassResultBufOffsets, const BufferRef &renderPassResultBuf, const BufferRef &finalResultBuf); private: angle::Result getVisibilityResultCombinePipeline( ContextMtl *contextMtl, bool keepOldValue, AutoObjCPtr> *outComputePipeline); // Visibility combination compute shaders: // - 0: This compute shader only combines the new values and discard old value. // - 1: This compute shader keep the old value and combines with new values. std::array>, 2> mVisibilityResultCombineComputeShaders; }; // Util class for handling mipmap generation class MipmapUtils final : angle::NonCopyable { public: // Compute based mipmap generation. angle::Result generateMipmapCS(ContextMtl *contextMtl, const TextureRef &srcTexture, bool sRGBMipmap, NativeTexLevelArray *mipmapOutputViews); private: angle::Result get3DMipGeneratorPipeline( ContextMtl *contextMtl, AutoObjCPtr> *outComputePipeline); angle::Result get2DMipGeneratorPipeline( ContextMtl *contextMtl, AutoObjCPtr> *outComputePipeline); angle::Result get2DArrayMipGeneratorPipeline( ContextMtl *contextMtl, AutoObjCPtr> *outComputePipeline); angle::Result getCubeMipGeneratorPipeline( ContextMtl *contextMtl, AutoObjCPtr> *outComputePipeline); // Mipmaps generating compute pipeline: AutoObjCPtr> m3DMipGeneratorShader; AutoObjCPtr> m2DMipGeneratorShader; AutoObjCPtr> m2DArrayMipGeneratorShader; AutoObjCPtr> mCubeMipGeneratorShader; }; // Util class for handling pixels copy between buffers and textures class CopyPixelsUtils final : angle::NonCopyable { public: CopyPixelsUtils() = default; CopyPixelsUtils(const std::string &readShaderName, const std::string &writeShaderName); angle::Result unpackPixelsFromBufferToTexture(ContextMtl *contextMtl, const angle::Format &srcAngleFormat, const CopyPixelsFromBufferParams ¶ms); angle::Result packPixelsFromTextureToBuffer(ContextMtl *contextMtl, const angle::Format &dstAngleFormat, const CopyPixelsToBufferParams ¶ms); private: angle::Result getPixelsCopyPipeline( ContextMtl *contextMtl, const angle::Format &angleFormat, const TextureRef &texture, bool bufferWrite, AutoObjCPtr> *outComputePipeline); // Copy pixels between buffer and texture compute pipelines: // - First dimension: pixel format. // - Second dimension: texture type * (buffer read/write flag) using PixelsCopyComputeShaderArray = std::array>, mtl_shader::kTextureTypeCount * 2>, angle::kNumANGLEFormats>; PixelsCopyComputeShaderArray mPixelsCopyComputeShaders; const std::string mReadShaderName; const std::string mWriteShaderName; }; // Util class for handling vertex format conversion on GPU class VertexFormatConversionUtils final : angle::NonCopyable { public: // Convert vertex format to float. Compute shader version. angle::Result convertVertexFormatToFloatCS(ContextMtl *contextMtl, const angle::Format &srcAngleFormat, const VertexFormatConvertParams ¶ms); // Convert vertex format to float. Vertex shader version. This version should be used if // a render pass is active and we don't want to break it. Explicit memory barrier must be // supported. angle::Result convertVertexFormatToFloatVS(const gl::Context *context, RenderCommandEncoder *renderEncoder, const angle::Format &srcAngleFormat, const VertexFormatConvertParams ¶ms); // Expand number of components per vertex's attribute (or just simply copy components between // buffers with different stride and offset) angle::Result expandVertexFormatComponentsCS(ContextMtl *contextMtl, const angle::Format &srcAngleFormat, const VertexFormatConvertParams ¶ms); angle::Result expandVertexFormatComponentsVS(const gl::Context *context, RenderCommandEncoder *renderEncoder, const angle::Format &srcAngleFormat, const VertexFormatConvertParams ¶ms); private: angle::Result getComponentsExpandComputePipeline( ContextMtl *contextMtl, AutoObjCPtr> *outPipelineState); angle::Result getComponentsExpandRenderPipeline( ContextMtl *contextMtl, RenderCommandEncoder *renderEncoder, AutoObjCPtr> *outPipelineState); angle::Result getFloatConverstionComputePipeline( ContextMtl *contextMtl, const angle::Format &srcAngleFormat, AutoObjCPtr> *outPipelineState); angle::Result getFloatConverstionRenderPipeline( ContextMtl *contextMtl, RenderCommandEncoder *renderEncoder, const angle::Format &srcAngleFormat, AutoObjCPtr> *outPipelineState); template angle::Result setupCommonConvertVertexFormatToFloat(ContextMtl *contextMtl, EncoderType cmdEncoder, const PipelineType &pipeline, const angle::Format &srcAngleFormat, const VertexFormatConvertParams ¶ms); template angle::Result setupCommonExpandVertexFormatComponents(ContextMtl *contextMtl, EncoderType cmdEncoder, const PipelineType &pipeline, const angle::Format &srcAngleFormat, const VertexFormatConvertParams ¶ms); using ConvertToFloatComputeShaderArray = std::array>, angle::kNumANGLEFormats>; using ConvertToFloatVertexShaderArray = std::array>, angle::kNumANGLEFormats>; ConvertToFloatComputeShaderArray mConvertToFloatCompPipelineCaches; ConvertToFloatVertexShaderArray mConvertToFloatVertexShaders; AutoObjCPtr> mComponentsExpandComputeShader; AutoObjCPtr> mComponentsExpandVertexShader; }; // RenderUtils: container class of various util classes above class RenderUtils : public Context, angle::NonCopyable { public: RenderUtils(DisplayMtl *display); ~RenderUtils() override; // Clear current framebuffer angle::Result clearWithDraw(const gl::Context *context, RenderCommandEncoder *cmdEncoder, const ClearRectParams ¶ms); // Blit texture data to current framebuffer angle::Result blitColorWithDraw(const gl::Context *context, RenderCommandEncoder *cmdEncoder, const angle::Format &srcAngleFormat, const ColorBlitParams ¶ms); // Same as above but blit the whole texture to the whole of current framebuffer. // This function assumes the framebuffer and the source texture have same size. angle::Result blitColorWithDraw(const gl::Context *context, RenderCommandEncoder *cmdEncoder, const angle::Format &srcAngleFormat, const TextureRef &srcTexture); angle::Result copyTextureWithDraw(const gl::Context *context, RenderCommandEncoder *cmdEncoder, const angle::Format &srcAngleFormat, const angle::Format &dstAngleFormat, const ColorBlitParams ¶ms); angle::Result blitDepthStencilWithDraw(const gl::Context *context, RenderCommandEncoder *cmdEncoder, const DepthStencilBlitParams ¶ms); // See DepthStencilBlitUtils::blitStencilViaCopyBuffer() angle::Result blitStencilViaCopyBuffer(const gl::Context *context, const StencilBlitViaBufferParams ¶ms); // See IndexGeneratorUtils angle::Result convertIndexBufferGPU(ContextMtl *contextMtl, const IndexConversionParams ¶ms); angle::Result generateTriFanBufferFromArrays(ContextMtl *contextMtl, const TriFanOrLineLoopFromArrayParams ¶ms); angle::Result generateTriFanBufferFromElementsArray(ContextMtl *contextMtl, const IndexGenerationParams ¶ms, uint32_t *indicesGenerated); angle::Result generateLineLoopBufferFromArrays(ContextMtl *contextMtl, const TriFanOrLineLoopFromArrayParams ¶ms); angle::Result generateLineLoopLastSegment(ContextMtl *contextMtl, uint32_t firstVertex, uint32_t lastVertex, const BufferRef &dstBuffer, uint32_t dstOffset); angle::Result generateLineLoopBufferFromElementsArray(ContextMtl *contextMtl, const IndexGenerationParams ¶ms, uint32_t *indicesGenerated); angle::Result generateLineLoopLastSegmentFromElementsArray(ContextMtl *contextMtl, const IndexGenerationParams ¶ms); void combineVisibilityResult(ContextMtl *contextMtl, bool keepOldValue, const VisibilityBufferOffsetsMtl &renderPassResultBufOffsets, const BufferRef &renderPassResultBuf, const BufferRef &finalResultBuf); // Compute based mipmap generation. Only possible for 3D texture for now. angle::Result generateMipmapCS(ContextMtl *contextMtl, const TextureRef &srcTexture, bool sRGBMipmap, NativeTexLevelArray *mipmapOutputViews); angle::Result unpackPixelsFromBufferToTexture(ContextMtl *contextMtl, const angle::Format &srcAngleFormat, const CopyPixelsFromBufferParams ¶ms); angle::Result packPixelsFromTextureToBuffer(ContextMtl *contextMtl, const angle::Format &dstAngleFormat, const CopyPixelsToBufferParams ¶ms); // See VertexFormatConversionUtils::convertVertexFormatToFloatCS() angle::Result convertVertexFormatToFloatCS(ContextMtl *contextMtl, const angle::Format &srcAngleFormat, const VertexFormatConvertParams ¶ms); // See VertexFormatConversionUtils::convertVertexFormatToFloatVS() angle::Result convertVertexFormatToFloatVS(const gl::Context *context, RenderCommandEncoder *renderEncoder, const angle::Format &srcAngleFormat, const VertexFormatConvertParams ¶ms); // See VertexFormatConversionUtils::expandVertexFormatComponentsCS() angle::Result expandVertexFormatComponentsCS(ContextMtl *contextMtl, const angle::Format &srcAngleFormat, const VertexFormatConvertParams ¶ms); // See VertexFormatConversionUtils::expandVertexFormatComponentsVS() angle::Result expandVertexFormatComponentsVS(const gl::Context *context, RenderCommandEncoder *renderEncoder, const angle::Format &srcAngleFormat, const VertexFormatConvertParams ¶ms); angle::Result generatePrimitiveRestartPointsBuffer(ContextMtl *contextMtl, const IndexGenerationParams ¶ms, size_t *indicesGenerated); angle::Result generatePrimitiveRestartLinesBuffer(ContextMtl *contextMtl, const IndexGenerationParams ¶ms, size_t *indicesGenerated); angle::Result generatePrimitiveRestartTrianglesBuffer(ContextMtl *contextMtl, const IndexGenerationParams ¶ms, size_t *indicesGenerated); private: // override ErrorHandler void handleError(GLenum error, const char *message, const char *file, const char *function, unsigned int line) override; void handleError(NSError *error, const char *message, const char *file, const char *function, unsigned int line) override; std::array()> mClearUtils; std::array()> mColorBlitUtils; ColorBlitUtils mCopyTextureFloatToUIntUtils; DepthStencilBlitUtils mDepthStencilBlitUtils; IndexGeneratorUtils mIndexUtils; VisibilityResultUtils mVisibilityResultUtils; MipmapUtils mMipmapUtils; std::array()> mCopyPixelsUtils; VertexFormatConversionUtils mVertexFormatUtils; }; } // namespace mtl } // namespace rx #endif /* LIBANGLE_RENDERER_METAL_MTL_RENDER_UTILS_H_ */