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 // TextureMtl.h: 7 // Defines the class interface for TextureMtl, implementing TextureImpl. 8 // 9 10 #ifndef LIBANGLE_RENDERER_METAL_TEXTUREMTL_H_ 11 #define LIBANGLE_RENDERER_METAL_TEXTUREMTL_H_ 12 13 #include <map> 14 15 #include "common/PackedEnums.h" 16 #include "libANGLE/renderer/TextureImpl.h" 17 #include "libANGLE/renderer/metal/RenderTargetMtl.h" 18 #include "libANGLE/renderer/metal/SurfaceMtl.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_resources.h" 22 namespace rx 23 { 24 25 // structure represents one image definition of a texture created by glTexImage* call. 26 struct ImageDefinitionMtl 27 { 28 mtl::TextureRef image; 29 angle::FormatID formatID = angle::FormatID::NONE; 30 }; 31 32 class TextureMtl : public TextureImpl 33 { 34 public: 35 using TextureViewVector = std::vector<mtl::TextureRef>; 36 using LayerLevelTextureViewVector = std::vector<TextureViewVector>; 37 38 TextureMtl(const gl::TextureState &state); 39 // Texture view 40 TextureMtl(const TextureMtl &mtl, GLenum format); 41 ~TextureMtl() override; 42 void onDestroy(const gl::Context *context) override; 43 44 angle::Result setImage(const gl::Context *context, 45 const gl::ImageIndex &index, 46 GLenum internalFormat, 47 const gl::Extents &size, 48 GLenum format, 49 GLenum type, 50 const gl::PixelUnpackState &unpack, 51 gl::Buffer *unpackBuffer, 52 const uint8_t *pixels) override; 53 angle::Result setSubImage(const gl::Context *context, 54 const gl::ImageIndex &index, 55 const gl::Box &area, 56 GLenum format, 57 GLenum type, 58 const gl::PixelUnpackState &unpack, 59 gl::Buffer *unpackBuffer, 60 const uint8_t *pixels) override; 61 62 angle::Result setCompressedImage(const gl::Context *context, 63 const gl::ImageIndex &index, 64 GLenum internalFormat, 65 const gl::Extents &size, 66 const gl::PixelUnpackState &unpack, 67 size_t imageSize, 68 const uint8_t *pixels) override; 69 angle::Result setCompressedSubImage(const gl::Context *context, 70 const gl::ImageIndex &index, 71 const gl::Box &area, 72 GLenum format, 73 const gl::PixelUnpackState &unpack, 74 size_t imageSize, 75 const uint8_t *pixels) override; 76 77 angle::Result copyImage(const gl::Context *context, 78 const gl::ImageIndex &index, 79 const gl::Rectangle &sourceArea, 80 GLenum internalFormat, 81 gl::Framebuffer *source) override; 82 angle::Result copySubImage(const gl::Context *context, 83 const gl::ImageIndex &index, 84 const gl::Offset &destOffset, 85 const gl::Rectangle &sourceArea, 86 gl::Framebuffer *source) override; 87 88 angle::Result copyTexture(const gl::Context *context, 89 const gl::ImageIndex &index, 90 GLenum internalFormat, 91 GLenum type, 92 GLint sourceLevel, 93 bool unpackFlipY, 94 bool unpackPremultiplyAlpha, 95 bool unpackUnmultiplyAlpha, 96 const gl::Texture *source) override; 97 angle::Result copySubTexture(const gl::Context *context, 98 const gl::ImageIndex &index, 99 const gl::Offset &destOffset, 100 GLint sourceLevel, 101 const gl::Box &sourceBox, 102 bool unpackFlipY, 103 bool unpackPremultiplyAlpha, 104 bool unpackUnmultiplyAlpha, 105 const gl::Texture *source) override; 106 107 angle::Result copyCompressedTexture(const gl::Context *context, 108 const gl::Texture *source) override; 109 110 angle::Result setStorage(const gl::Context *context, 111 gl::TextureType type, 112 size_t levels, 113 GLenum internalFormat, 114 const gl::Extents &size) override; 115 116 angle::Result setStorageExternalMemory(const gl::Context *context, 117 gl::TextureType type, 118 size_t levels, 119 GLenum internalFormat, 120 const gl::Extents &size, 121 gl::MemoryObject *memoryObject, 122 GLuint64 offset, 123 GLbitfield createFlags, 124 GLbitfield usageFlags, 125 const void *imageCreateInfoPNext) override; 126 127 angle::Result setEGLImageTarget(const gl::Context *context, 128 gl::TextureType type, 129 egl::Image *image) override; 130 131 angle::Result setImageExternal(const gl::Context *context, 132 gl::TextureType type, 133 egl::Stream *stream, 134 const egl::Stream::GLTextureDescription &desc) override; 135 136 angle::Result generateMipmap(const gl::Context *context) override; 137 138 angle::Result setBaseLevel(const gl::Context *context, GLuint baseLevel) override; 139 140 angle::Result bindTexImage(const gl::Context *context, egl::Surface *surface) override; 141 angle::Result releaseTexImage(const gl::Context *context) override; 142 143 angle::Result getAttachmentRenderTarget(const gl::Context *context, 144 GLenum binding, 145 const gl::ImageIndex &imageIndex, 146 GLsizei samples, 147 FramebufferAttachmentRenderTarget **rtOut) override; 148 149 angle::Result syncState(const gl::Context *context, 150 const gl::Texture::DirtyBits &dirtyBits, 151 gl::Command source) override; 152 153 angle::Result setStorageMultisample(const gl::Context *context, 154 gl::TextureType type, 155 GLsizei samples, 156 GLint internalformat, 157 const gl::Extents &size, 158 bool fixedSampleLocations) override; 159 160 angle::Result initializeContents(const gl::Context *context, 161 GLenum binding, 162 const gl::ImageIndex &imageIndex) override; 163 164 // The texture's data is initially initialized and stored in an array 165 // of images through glTexImage*/glCopyTex* calls. During draw calls, the caller must make sure 166 // the actual texture is created by calling this method to transfer the stored images data 167 // to the actual texture. 168 angle::Result ensureTextureCreated(const gl::Context *context); 169 170 angle::Result bindToShader(const gl::Context *context, 171 mtl::RenderCommandEncoder *cmdEncoder, 172 gl::ShaderType shaderType, 173 gl::Sampler *sampler, /** nullable */ 174 int textureSlotIndex, 175 int samplerSlotIndex); 176 177 angle::Result bindToShaderImage(const gl::Context *context, 178 mtl::RenderCommandEncoder *cmdEncoder, 179 gl::ShaderType shaderType, 180 int textureSlotIndex, 181 int level, 182 int layer, 183 GLenum format); 184 getFormat()185 const mtl::Format &getFormat() const { return mFormat; } 186 187 private: 188 void releaseTexture(bool releaseImages); 189 void releaseTexture(bool releaseImages, bool releaseTextureObjectsOnly); 190 angle::Result createNativeTexture(const gl::Context *context, 191 gl::TextureType type, 192 GLuint mips, 193 const gl::Extents &size); 194 angle::Result onBaseMaxLevelsChanged(const gl::Context *context); 195 angle::Result ensureSamplerStateCreated(const gl::Context *context); 196 // Ensure image at given index is created: 197 angle::Result ensureImageCreated(const gl::Context *context, const gl::ImageIndex &index); 198 // Ensure all image views at all faces/levels are retained. 199 void retainImageDefinitions(); 200 mtl::TextureRef createImageViewFromTextureStorage(GLuint cubeFaceOrZero, GLuint glLevel); 201 angle::Result createViewFromBaseToMaxLevel(); 202 angle::Result ensureLevelViewsWithinBaseMaxCreated(); 203 angle::Result checkForEmulatedChannels(const gl::Context *context, 204 const mtl::Format &mtlFormat, 205 const mtl::TextureRef &texture); 206 mtl::TextureRef &getImage(const gl::ImageIndex &imageIndex); 207 ImageDefinitionMtl &getImageDefinition(const gl::ImageIndex &imageIndex); 208 RenderTargetMtl &getRenderTarget(const gl::ImageIndex &imageIndex); 209 mtl::TextureRef &getImplicitMSTexture(const gl::ImageIndex &imageIndex); 210 211 // If levels = 0, this function will create full mipmaps texture. 212 angle::Result setStorageImpl(const gl::Context *context, 213 gl::TextureType type, 214 size_t levels, 215 const mtl::Format &mtlFormat, 216 const gl::Extents &size); 217 218 angle::Result redefineImage(const gl::Context *context, 219 const gl::ImageIndex &index, 220 const mtl::Format &mtlFormat, 221 const gl::Extents &size); 222 223 angle::Result setImageImpl(const gl::Context *context, 224 const gl::ImageIndex &index, 225 const gl::InternalFormat &dstFormatInfo, 226 const gl::Extents &size, 227 GLenum srcFormat, 228 GLenum srcType, 229 const gl::PixelUnpackState &unpack, 230 gl::Buffer *unpackBuffer, 231 const uint8_t *pixels); 232 angle::Result setSubImageImpl(const gl::Context *context, 233 const gl::ImageIndex &index, 234 const gl::Box &area, 235 const gl::InternalFormat &formatInfo, 236 GLenum type, 237 const gl::PixelUnpackState &unpack, 238 gl::Buffer *unpackBuffer, 239 const uint8_t *pixels); 240 241 angle::Result copySubImageImpl(const gl::Context *context, 242 const gl::ImageIndex &index, 243 const gl::Offset &destOffset, 244 const gl::Rectangle &sourceArea, 245 const gl::InternalFormat &internalFormat, 246 const FramebufferMtl *source, 247 const RenderTargetMtl *sourceRtt); 248 angle::Result copySubImageWithDraw(const gl::Context *context, 249 const gl::ImageIndex &index, 250 const gl::Offset &destOffset, 251 const gl::Rectangle &sourceArea, 252 const gl::InternalFormat &internalFormat, 253 const FramebufferMtl *source, 254 const RenderTargetMtl *sourceRtt); 255 angle::Result copySubImageCPU(const gl::Context *context, 256 const gl::ImageIndex &index, 257 const gl::Offset &destOffset, 258 const gl::Rectangle &sourceArea, 259 const gl::InternalFormat &internalFormat, 260 const FramebufferMtl *source, 261 const RenderTargetMtl *sourceRtt); 262 263 angle::Result copySubTextureImpl(const gl::Context *context, 264 const gl::ImageIndex &index, 265 const gl::Offset &destOffset, 266 const gl::InternalFormat &internalFormat, 267 GLint sourceLevel, 268 const gl::Box &sourceBox, 269 bool unpackFlipY, 270 bool unpackPremultiplyAlpha, 271 bool unpackUnmultiplyAlpha, 272 const gl::Texture *source); 273 274 angle::Result copySubTextureWithDraw(const gl::Context *context, 275 const gl::ImageIndex &index, 276 const gl::Offset &destOffset, 277 const gl::InternalFormat &internalFormat, 278 const mtl::MipmapNativeLevel &sourceNativeLevel, 279 const gl::Box &sourceBox, 280 const angle::Format &sourceAngleFormat, 281 bool unpackFlipY, 282 bool unpackPremultiplyAlpha, 283 bool unpackUnmultiplyAlpha, 284 const mtl::TextureRef &sourceTexture); 285 286 angle::Result copySubTextureCPU(const gl::Context *context, 287 const gl::ImageIndex &index, 288 const gl::Offset &destOffset, 289 const gl::InternalFormat &internalFormat, 290 const mtl::MipmapNativeLevel &sourceNativeLevel, 291 const gl::Box &sourceBox, 292 const angle::Format &sourceAngleFormat, 293 bool unpackFlipY, 294 bool unpackPremultiplyAlpha, 295 bool unpackUnmultiplyAlpha, 296 const mtl::TextureRef &sourceTexture); 297 298 // Copy data to texture's per array's slice/cube's face. NOTE: This function doesn't upload 299 // data to 3D texture's z layer. Metal treats 3D texture's z layer & array texture's slice 300 // differently. For array/cube texture, it is only possible to upload to one slice at a time. 301 angle::Result setPerSliceSubImage(const gl::Context *context, 302 int slice, 303 const MTLRegion &mtlArea, 304 const gl::InternalFormat &internalFormat, 305 GLenum type, 306 const angle::Format &pixelsAngleFormat, 307 size_t pixelsRowPitch, 308 size_t pixelsDepthPitch, 309 gl::Buffer *unpackBuffer, 310 const uint8_t *pixels, 311 const mtl::TextureRef &image); 312 313 // Convert pixels to suported format before uploading to texture 314 angle::Result convertAndSetPerSliceSubImage(const gl::Context *context, 315 int slice, 316 const MTLRegion &mtlArea, 317 const gl::InternalFormat &internalFormat, 318 GLenum type, 319 const angle::Format &pixelsAngleFormat, 320 size_t pixelsRowPitch, 321 size_t pixelsDepthPitch, 322 gl::Buffer *unpackBuffer, 323 const uint8_t *pixels, 324 const mtl::TextureRef &image); 325 326 angle::Result generateMipmapCPU(const gl::Context *context); 327 328 bool needsFormatViewForPixelLocalStorage(const ShPixelLocalStorageOptions &) const; 329 bool isImmutableOrPBuffer() const; 330 331 mtl::Format mFormat; 332 egl::Surface *mBoundSurface = nullptr; 333 class NativeTextureWrapper; 334 class NativeTextureWrapperWithViewSupport; 335 // The real texture used by Metal. 336 // For non-immutable texture, this usually contains levels from (GL base level -> GL max level). 337 // For immutable texture, this contains levels allocated with glTexStorage which could be 338 // outside (GL base level -> GL max level) range. 339 std::unique_ptr<NativeTextureWrapperWithViewSupport> mNativeTextureStorage; 340 // The view of mNativeTextureStorage from (GL base level -> GL max level) 341 std::unique_ptr<NativeTextureWrapper> mViewFromBaseToMaxLevel; 342 id<MTLSamplerState> mMetalSamplerState = nil; 343 344 // Number of slices 345 uint32_t mSlices = 1; 346 347 // Stored images array defined by glTexImage/glCopy*. 348 // Once the images array is complete, they will be transferred to real texture object. 349 // NOTE: 350 // - The second dimension is indexed by configured base level + actual native level 351 // - For Cube map, there will be at most 6 entries in the map table, one for each face. This is 352 // because the Cube map's image is defined per face & per level. 353 // - For other texture types, there will be only one entry in the map table. All other textures 354 // except Cube map has texture image defined per level (all slices included). 355 // - These three variables' second dimension are indexed by image index (base level included). 356 std::map<int, gl::TexLevelArray<ImageDefinitionMtl>> mTexImageDefs; 357 std::map<int, gl::TexLevelArray<RenderTargetMtl>> mPerLayerRenderTargets; 358 std::map<int, gl::TexLevelArray<mtl::TextureRef>> mImplicitMSTextures; 359 360 // Lazily populated 2D views for shader storage images. 361 // May have different formats than the original texture. 362 // Indexed by format, then layer, then level. 363 std::map<MTLPixelFormat, LayerLevelTextureViewVector> mShaderImageViews; 364 365 // Mipmap views are indexed from (base GL level -> max GL level): 366 mtl::NativeTexLevelArray mLevelViewsWithinBaseMax; 367 368 // The swizzled or stencil view used for shader sampling. 369 mtl::TextureRef mSwizzleStencilSamplingView; 370 }; 371 372 } // namespace rx 373 374 #endif /* LIBANGLE_RENDERER_METAL_TEXTUREMTL_H_ */ 375