1 // 2 // Copyright 2016 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 // TextureVk.h: 7 // Defines the class interface for TextureVk, implementing TextureImpl. 8 // 9 10 #ifndef LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_ 11 #define LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_ 12 13 #include "libANGLE/renderer/TextureImpl.h" 14 #include "libANGLE/renderer/vulkan/RenderTargetVk.h" 15 #include "libANGLE/renderer/vulkan/ResourceVk.h" 16 #include "libANGLE/renderer/vulkan/SamplerVk.h" 17 #include "libANGLE/renderer/vulkan/vk_helpers.h" 18 19 namespace rx 20 { 21 22 enum class ImageMipLevels 23 { 24 EnabledLevels = 0, 25 FullMipChain = 1, 26 27 InvalidEnum = 2, 28 }; 29 30 // vkCmdCopyBufferToImage buffer offset multiple 31 constexpr VkDeviceSize kBufferOffsetMultiple = 4; 32 33 class TextureVk : public TextureImpl, public angle::ObserverInterface 34 { 35 public: 36 TextureVk(const gl::TextureState &state, RendererVk *renderer); 37 ~TextureVk() override; 38 void onDestroy(const gl::Context *context) override; 39 40 angle::Result setImage(const gl::Context *context, 41 const gl::ImageIndex &index, 42 GLenum internalFormat, 43 const gl::Extents &size, 44 GLenum format, 45 GLenum type, 46 const gl::PixelUnpackState &unpack, 47 gl::Buffer *unpackBuffer, 48 const uint8_t *pixels) override; 49 angle::Result setSubImage(const gl::Context *context, 50 const gl::ImageIndex &index, 51 const gl::Box &area, 52 GLenum format, 53 GLenum type, 54 const gl::PixelUnpackState &unpack, 55 gl::Buffer *unpackBuffer, 56 const uint8_t *pixels) override; 57 58 angle::Result setCompressedImage(const gl::Context *context, 59 const gl::ImageIndex &index, 60 GLenum internalFormat, 61 const gl::Extents &size, 62 const gl::PixelUnpackState &unpack, 63 size_t imageSize, 64 const uint8_t *pixels) override; 65 angle::Result setCompressedSubImage(const gl::Context *context, 66 const gl::ImageIndex &index, 67 const gl::Box &area, 68 GLenum format, 69 const gl::PixelUnpackState &unpack, 70 size_t imageSize, 71 const uint8_t *pixels) override; 72 73 angle::Result copyImage(const gl::Context *context, 74 const gl::ImageIndex &index, 75 const gl::Rectangle &sourceArea, 76 GLenum internalFormat, 77 gl::Framebuffer *source) override; 78 angle::Result copySubImage(const gl::Context *context, 79 const gl::ImageIndex &index, 80 const gl::Offset &destOffset, 81 const gl::Rectangle &sourceArea, 82 gl::Framebuffer *source) override; 83 84 angle::Result copyTexture(const gl::Context *context, 85 const gl::ImageIndex &index, 86 GLenum internalFormat, 87 GLenum type, 88 GLint sourceLevelGL, 89 bool unpackFlipY, 90 bool unpackPremultiplyAlpha, 91 bool unpackUnmultiplyAlpha, 92 const gl::Texture *source) override; 93 angle::Result copySubTexture(const gl::Context *context, 94 const gl::ImageIndex &index, 95 const gl::Offset &destOffset, 96 GLint sourceLevelGL, 97 const gl::Box &sourceBox, 98 bool unpackFlipY, 99 bool unpackPremultiplyAlpha, 100 bool unpackUnmultiplyAlpha, 101 const gl::Texture *source) override; 102 103 angle::Result copyRenderbufferSubData(const gl::Context *context, 104 const gl::Renderbuffer *srcBuffer, 105 GLint srcLevel, 106 GLint srcX, 107 GLint srcY, 108 GLint srcZ, 109 GLint dstLevel, 110 GLint dstX, 111 GLint dstY, 112 GLint dstZ, 113 GLsizei srcWidth, 114 GLsizei srcHeight, 115 GLsizei srcDepth) override; 116 117 angle::Result copyTextureSubData(const gl::Context *context, 118 const gl::Texture *srcTexture, 119 GLint srcLevel, 120 GLint srcX, 121 GLint srcY, 122 GLint srcZ, 123 GLint dstLevel, 124 GLint dstX, 125 GLint dstY, 126 GLint dstZ, 127 GLsizei srcWidth, 128 GLsizei srcHeight, 129 GLsizei srcDepth) override; 130 131 angle::Result copyCompressedTexture(const gl::Context *context, 132 const gl::Texture *source) override; 133 134 angle::Result setStorage(const gl::Context *context, 135 gl::TextureType type, 136 size_t levels, 137 GLenum internalFormat, 138 const gl::Extents &size) override; 139 140 angle::Result setStorageExternalMemory(const gl::Context *context, 141 gl::TextureType type, 142 size_t levels, 143 GLenum internalFormat, 144 const gl::Extents &size, 145 gl::MemoryObject *memoryObject, 146 GLuint64 offset, 147 GLbitfield createFlags, 148 GLbitfield usageFlags) override; 149 150 angle::Result setEGLImageTarget(const gl::Context *context, 151 gl::TextureType type, 152 egl::Image *image) override; 153 154 angle::Result setImageExternal(const gl::Context *context, 155 gl::TextureType type, 156 egl::Stream *stream, 157 const egl::Stream::GLTextureDescription &desc) override; 158 159 angle::Result setBuffer(const gl::Context *context, GLenum internalFormat) override; 160 161 angle::Result generateMipmap(const gl::Context *context) override; 162 163 angle::Result setBaseLevel(const gl::Context *context, GLuint baseLevel) override; 164 165 angle::Result bindTexImage(const gl::Context *context, egl::Surface *surface) override; 166 angle::Result releaseTexImage(const gl::Context *context) override; 167 168 angle::Result getAttachmentRenderTarget(const gl::Context *context, 169 GLenum binding, 170 const gl::ImageIndex &imageIndex, 171 GLsizei samples, 172 FramebufferAttachmentRenderTarget **rtOut) override; 173 174 angle::Result syncState(const gl::Context *context, 175 const gl::Texture::DirtyBits &dirtyBits, 176 gl::Command source) override; 177 178 angle::Result setStorageMultisample(const gl::Context *context, 179 gl::TextureType type, 180 GLsizei samples, 181 GLint internalformat, 182 const gl::Extents &size, 183 bool fixedSampleLocations) override; 184 185 angle::Result initializeContents(const gl::Context *context, 186 const gl::ImageIndex &imageIndex) override; 187 getImage()188 const vk::ImageHelper &getImage() const 189 { 190 ASSERT(mImage && mImage->valid()); 191 return *mImage; 192 } 193 getImage()194 vk::ImageHelper &getImage() 195 { 196 ASSERT(mImage && mImage->valid()); 197 return *mImage; 198 } 199 retainImageViews(vk::ResourceUseList * resourceUseList)200 void retainImageViews(vk::ResourceUseList *resourceUseList) 201 { 202 getImageViews().retain(resourceUseList); 203 } 204 retainBufferViews(vk::ResourceUseList * resourceUseList)205 void retainBufferViews(vk::ResourceUseList *resourceUseList) 206 { 207 mBufferViews.retain(resourceUseList); 208 } 209 210 void releaseOwnershipOfImage(const gl::Context *context); 211 212 const vk::ImageView &getReadImageViewAndRecordUse(ContextVk *contextVk, 213 GLenum srgbDecode, 214 bool texelFetchStaticUse) const; 215 216 // A special view for cube maps as a 2D array, used with shaders that do texelFetch() and for 217 // seamful cube map emulation. 218 const vk::ImageView &getFetchImageViewAndRecordUse(ContextVk *contextVk, 219 GLenum srgbDecode, 220 bool texelFetchStaticUse) const; 221 222 // A special view used for texture copies that shouldn't perform swizzle. 223 const vk::ImageView &getCopyImageViewAndRecordUse(ContextVk *contextVk) const; 224 angle::Result getStorageImageView(ContextVk *contextVk, 225 const gl::ImageUnit &binding, 226 const vk::ImageView **imageViewOut); 227 getSampler()228 const vk::SamplerHelper &getSampler() const 229 { 230 ASSERT(mSampler.valid()); 231 return mSampler.get(); 232 } 233 234 angle::Result getBufferViewAndRecordUse(ContextVk *contextVk, 235 const vk::Format *imageUniformFormat, 236 bool isImage, 237 const vk::BufferView **viewOut); 238 239 // Normally, initialize the image with enabled mipmap level counts. 240 angle::Result ensureImageInitialized(ContextVk *contextVk, ImageMipLevels mipLevels); 241 242 vk::ImageOrBufferViewSubresourceSerial getImageViewSubresourceSerial( 243 const gl::SamplerState &samplerState) const; 244 vk::ImageOrBufferViewSubresourceSerial getBufferViewSerial() const; 245 overrideStagingBufferSizeForTesting(size_t initialSizeForTesting)246 void overrideStagingBufferSizeForTesting(size_t initialSizeForTesting) 247 { 248 mStagingBufferInitialSize = initialSizeForTesting; 249 } 250 251 GLenum getColorReadFormat(const gl::Context *context) override; 252 GLenum getColorReadType(const gl::Context *context) override; 253 254 angle::Result getTexImage(const gl::Context *context, 255 const gl::PixelPackState &packState, 256 gl::Buffer *packBuffer, 257 gl::TextureTarget target, 258 GLint level, 259 GLenum format, 260 GLenum type, 261 void *pixels) override; 262 hasBeenBoundAsImage()263 ANGLE_INLINE bool hasBeenBoundAsImage() const { return mState.hasBeenBoundAsImage(); } getBuffer()264 ANGLE_INLINE const gl::OffsetBindingPointer<gl::Buffer> &getBuffer() const 265 { 266 return mState.getBuffer(); 267 } 268 isSRGBOverrideEnabled()269 bool isSRGBOverrideEnabled() const 270 { 271 return mState.getSRGBOverride() != gl::SrgbOverride::Default; 272 } 273 274 angle::Result ensureMutable(ContextVk *contextVk); 275 getAndResetImmutableSamplerDirtyState()276 bool getAndResetImmutableSamplerDirtyState() 277 { 278 bool isDirty = mImmutableSamplerDirty; 279 mImmutableSamplerDirty = false; 280 return isDirty; 281 } 282 283 private: 284 // Transform an image index from the frontend into one that can be used on the backing 285 // ImageHelper, taking into account mipmap or cube face offsets 286 gl::ImageIndex getNativeImageIndex(const gl::ImageIndex &inputImageIndex) const; 287 gl::LevelIndex getNativeImageLevel(gl::LevelIndex frontendLevel) const; 288 uint32_t getNativeImageLayer(uint32_t frontendLayer) const; 289 290 void releaseAndDeleteImageAndViews(ContextVk *contextVk); 291 angle::Result ensureImageAllocated(ContextVk *contextVk, const vk::Format &format); 292 void setImageHelper(ContextVk *contextVk, 293 vk::ImageHelper *imageHelper, 294 gl::TextureType imageType, 295 const vk::Format &format, 296 uint32_t imageLevelOffset, 297 uint32_t imageLayerOffset, 298 gl::LevelIndex imageBaseLevel, 299 bool selfOwned); 300 void updateImageHelper(ContextVk *contextVk, size_t imageCopyBufferAlignment); getImageViews()301 vk::ImageViewHelper &getImageViews() 302 { 303 return mMultisampledImageViews[gl::RenderToTextureImageIndex::Default]; 304 } getImageViews()305 const vk::ImageViewHelper &getImageViews() const 306 { 307 return mMultisampledImageViews[gl::RenderToTextureImageIndex::Default]; 308 } 309 310 // Redefine a mip level of the texture. If the new size and format don't match the allocated 311 // image, the image may be released. When redefining a mip of a multi-level image, updates are 312 // forced to be staged, as another mip of the image may be bound to a framebuffer. For example, 313 // assume texture has two mips, and framebuffer is bound to mip 0. Redefining mip 1 to an 314 // incompatible size shouldn't affect the framebuffer, especially if the redefinition comes from 315 // something like glCopyTexSubImage2D() (which simultaneously is reading from said framebuffer, 316 // i.e. mip 0 of the texture). 317 angle::Result redefineLevel(const gl::Context *context, 318 const gl::ImageIndex &index, 319 const vk::Format &format, 320 const gl::Extents &size); 321 322 angle::Result setImageImpl(const gl::Context *context, 323 const gl::ImageIndex &index, 324 const gl::InternalFormat &formatInfo, 325 const gl::Extents &size, 326 GLenum type, 327 const gl::PixelUnpackState &unpack, 328 gl::Buffer *unpackBuffer, 329 const uint8_t *pixels); 330 angle::Result setSubImageImpl(const gl::Context *context, 331 const gl::ImageIndex &index, 332 const gl::Box &area, 333 const gl::InternalFormat &formatInfo, 334 GLenum type, 335 const gl::PixelUnpackState &unpack, 336 gl::Buffer *unpackBuffer, 337 const uint8_t *pixels, 338 const vk::Format &vkFormat); 339 340 angle::Result copyImageDataToBufferAndGetData(ContextVk *contextVk, 341 gl::LevelIndex sourceLevelGL, 342 uint32_t layerCount, 343 const gl::Box &sourceArea, 344 uint8_t **outDataPtr); 345 346 angle::Result copyBufferDataToImage(ContextVk *contextVk, 347 vk::BufferHelper *srcBuffer, 348 const gl::ImageIndex index, 349 uint32_t rowLength, 350 uint32_t imageHeight, 351 const gl::Box &sourceArea, 352 size_t offset, 353 VkImageAspectFlags aspectFlags); 354 355 // Called from syncState to prepare the image for mipmap generation. 356 void prepareForGenerateMipmap(ContextVk *contextVk); 357 358 // Generate mipmaps from level 0 into the rest of the mips. This requires the image to have 359 // STORAGE usage. 360 angle::Result generateMipmapsWithCompute(ContextVk *contextVk); 361 362 angle::Result generateMipmapsWithCPU(const gl::Context *context); 363 364 angle::Result generateMipmapLevelsWithCPU(ContextVk *contextVk, 365 const angle::Format &sourceFormat, 366 GLuint layer, 367 gl::LevelIndex firstMipLevel, 368 gl::LevelIndex maxMipLevel, 369 const size_t sourceWidth, 370 const size_t sourceHeight, 371 const size_t sourceDepth, 372 const size_t sourceRowPitch, 373 const size_t sourceDepthPitch, 374 uint8_t *sourceData); 375 376 angle::Result copySubImageImpl(const gl::Context *context, 377 const gl::ImageIndex &index, 378 const gl::Offset &destOffset, 379 const gl::Rectangle &sourceArea, 380 const gl::InternalFormat &internalFormat, 381 gl::Framebuffer *source); 382 383 angle::Result copySubTextureImpl(ContextVk *contextVk, 384 const gl::ImageIndex &index, 385 const gl::Offset &destOffset, 386 const gl::InternalFormat &destFormat, 387 gl::LevelIndex sourceLevelGL, 388 const gl::Box &sourceBox, 389 bool unpackFlipY, 390 bool unpackPremultiplyAlpha, 391 bool unpackUnmultiplyAlpha, 392 TextureVk *source); 393 394 angle::Result copySubImageImplWithTransfer(ContextVk *contextVk, 395 const gl::ImageIndex &index, 396 const gl::Offset &destOffset, 397 const vk::Format &destFormat, 398 gl::LevelIndex sourceLevelGL, 399 size_t sourceLayer, 400 const gl::Box &sourceBox, 401 vk::ImageHelper *srcImage); 402 403 angle::Result copySubImageImplWithDraw(ContextVk *contextVk, 404 const gl::ImageIndex &index, 405 const gl::Offset &destOffset, 406 const vk::Format &destFormat, 407 gl::LevelIndex sourceLevelGL, 408 const gl::Box &sourceBox, 409 bool isSrcFlipY, 410 bool unpackFlipY, 411 bool unpackPremultiplyAlpha, 412 bool unpackUnmultiplyAlpha, 413 vk::ImageHelper *srcImage, 414 const vk::ImageView *srcView, 415 SurfaceRotation srcFramebufferRotation); 416 417 angle::Result initImage(ContextVk *contextVk, 418 const vk::Format &format, 419 const bool sized, 420 const gl::Extents &firstLevelExtents, 421 const uint32_t firstLevel, 422 const uint32_t levelCount); 423 void releaseImage(ContextVk *contextVk); 424 void releaseStagingBuffer(ContextVk *contextVk); 425 uint32_t getMipLevelCount(ImageMipLevels mipLevels) const; 426 uint32_t getMaxLevelCount() const; 427 angle::Result copyAndStageImageData(ContextVk *contextVk, 428 gl::LevelIndex previousFirstAllocateLevel, 429 vk::ImageHelper *srcImage, 430 vk::ImageHelper *dstImage); 431 angle::Result initImageViews(ContextVk *contextVk, 432 const vk::Format &format, 433 const bool sized, 434 uint32_t levelCount, 435 uint32_t layerCount); 436 void initSingleLayerRenderTargets(ContextVk *contextVk, 437 GLuint layerCount, 438 gl::LevelIndex levelIndexGL, 439 gl::RenderToTextureImageIndex renderToTextureIndex); 440 RenderTargetVk *getMultiLayerRenderTarget(ContextVk *contextVk, 441 gl::LevelIndex level, 442 GLuint layerIndex, 443 GLuint layerCount); 444 angle::Result getLevelLayerImageView(ContextVk *contextVk, 445 gl::LevelIndex levelGL, 446 size_t layer, 447 const vk::ImageView **imageViewOut); 448 449 // Flush image's staged updates for all levels and layers. 450 angle::Result flushImageStagedUpdates(ContextVk *contextVk); 451 452 const gl::InternalFormat &getImplementationSizedFormat(const gl::Context *context) const; 453 const vk::Format &getBaseLevelFormat(RendererVk *renderer) const; 454 // Queues a flush of any modified image attributes. The image will be reallocated with its new 455 // attributes at the next opportunity. 456 angle::Result respecifyImageStorage(ContextVk *contextVk); 457 angle::Result respecifyImageStorageAndLevels(ContextVk *contextVk, 458 gl::LevelIndex previousFirstAllocateLevelGL, 459 gl::LevelIndex baseLevelGL, 460 gl::LevelIndex maxLevelGL); 461 462 // Update base and max levels, and re-create image if needed. 463 angle::Result updateBaseMaxLevels(ContextVk *contextVk, 464 bool baseLevelChanged, 465 bool maxLevelChanged); 466 467 bool isFastUnpackPossible(const vk::Format &vkFormat, size_t offset) const; 468 469 bool shouldUpdateBeStaged(gl::LevelIndex textureLevelIndexGL) const; 470 471 // We monitor the staging buffer and set dirty bits if the staging buffer changes. Note that we 472 // support changes in the staging buffer even outside the TextureVk class. 473 void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override; 474 getTilingMode()475 ANGLE_INLINE VkImageTiling getTilingMode() 476 { 477 return (mImage->valid()) ? mImage->getTilingMode() : VK_IMAGE_TILING_OPTIMAL; 478 } 479 480 angle::Result refreshImageViews(ContextVk *contextVk); 481 bool shouldDecodeSRGB(ContextVk *contextVk, GLenum srgbDecode, bool texelFetchStaticUse) const; 482 void initImageUsageFlags(ContextVk *contextVk, const vk::Format &format); 483 void handleImmutableSamplerTransition(const vk::ImageHelper *previousImage, 484 const vk::ImageHelper *nextImage); 485 486 bool mOwnsImage; 487 bool mRequiresMutableStorage; 488 bool mImmutableSamplerDirty; 489 490 gl::TextureType mImageNativeType; 491 492 // The layer offset to apply when converting from a frontend texture layer to a texture layer in 493 // mImage. Used when this texture sources a cube map face or 3D texture layer from an EGL image. 494 uint32_t mImageLayerOffset; 495 496 // The level offset to apply when converting from a frontend texture level to texture level in 497 // mImage. 498 uint32_t mImageLevelOffset; 499 500 // If multisampled rendering to texture, an intermediate multisampled image is created for use 501 // as renderpass color attachment. An array of images and image views are used based on the 502 // number of samples used with multisampled rendering to texture. Index 0 corresponds to the 503 // non-multisampled-render-to-texture usage of the texture. 504 505 // - index 0: Unused. See description of |mImage|. 506 // - index N: intermediate multisampled image used for multisampled rendering to texture with 507 // 1 << N samples 508 gl::RenderToTextureImageMap<vk::ImageHelper> mMultisampledImages; 509 510 // |ImageViewHelper| contains all the current views for the Texture. The views are always owned 511 // by the Texture and are not shared like |mImage|. They also have different lifetimes and can 512 // be reallocated independently of |mImage| on state changes. 513 // 514 // - index 0: views for the texture's image (regardless of |mOwnsImage|). 515 // - index N: views for mMultisampledImages[N] 516 gl::RenderToTextureImageMap<vk::ImageViewHelper> mMultisampledImageViews; 517 518 // Texture buffers create texel buffer views instead. |BufferViewHelper| contains the views 519 // corresponding to the attached buffer range. 520 vk::BufferViewHelper mBufferViews; 521 522 // Render targets stored as array of vector of vectors 523 // 524 // - First dimension: index N contains render targets with views from mMultisampledImageViews[N] 525 // - Second dimension: level 526 // - Third dimension: layer 527 gl::RenderToTextureImageMap<std::vector<RenderTargetVector>> mSingleLayerRenderTargets; 528 // Multi-layer render targets stored as a hash map. This is used for layered attachments 529 // which covers the entire layer (glFramebufferTextureLayer) or multiview attachments which 530 // cover a range of layers (glFramebufferTextureMultiviewOVR). 531 angle::HashMap<vk::ImageSubresourceRange, std::unique_ptr<RenderTargetVk>> 532 mMultiLayerRenderTargets; 533 534 // |mImage| wraps a VkImage and VkDeviceMemory that represents the gl::Texture. |mOwnsImage| 535 // indicates that |TextureVk| owns the image. Otherwise it is a weak pointer shared with another 536 // class. Due to this sharing, for example through EGL images, the image must always be 537 // dynamically allocated as the texture can release ownership for example and it can be 538 // transferred to another |TextureVk|. 539 vk::ImageHelper *mImage; 540 541 // |mSampler| contains the relevant Vulkan sampler states representing the OpenGL Texture 542 // sampling states for the Texture. 543 vk::SamplerBinding mSampler; 544 545 // Overridden in some tests. 546 size_t mStagingBufferInitialSize; 547 548 // The created vkImage usage flag. 549 VkImageUsageFlags mImageUsageFlags; 550 551 // Additional image create flags 552 VkImageCreateFlags mImageCreateFlags; 553 554 // If an image level is incompatibly redefined, the image lives through the call that did this 555 // (i.e. set and copy levels), because the image may be used by the framebuffer in the very same 556 // call. As a result, updates to this redefined level are staged (in both the call that 557 // redefines it, and any future calls such as subimage updates). This bitset flags redefined 558 // levels so that their updates will be force-staged until image is recreated. 559 // 560 // In common cases with mipmapped textures, the base/max level would need adjusting as the 561 // texture is no longer mip-complete. However, if every level is redefined such that at the end 562 // the image becomes mip-complete again, no reinitialization of the image is done. This bitset 563 // is additionally used to ensure the image is recreated in the next syncState, if not already. 564 gl::TexLevelMask mRedefinedLevels; 565 566 angle::ObserverBinding mImageObserverBinding; 567 }; 568 569 } // namespace rx 570 571 #endif // LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_ 572