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