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