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