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 size_t sourceLevel, 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 size_t sourceLevel, 97 const gl::Box &sourceBox, 98 bool unpackFlipY, 99 bool unpackPremultiplyAlpha, 100 bool unpackUnmultiplyAlpha, 101 const gl::Texture *source) override; 102 103 angle::Result copyCompressedTexture(const gl::Context *context, 104 const gl::Texture *source) override; 105 106 angle::Result setStorage(const gl::Context *context, 107 gl::TextureType type, 108 size_t levels, 109 GLenum internalFormat, 110 const gl::Extents &size) override; 111 112 angle::Result setStorageExternalMemory(const gl::Context *context, 113 gl::TextureType type, 114 size_t levels, 115 GLenum internalFormat, 116 const gl::Extents &size, 117 gl::MemoryObject *memoryObject, 118 GLuint64 offset) override; 119 120 angle::Result setEGLImageTarget(const gl::Context *context, 121 gl::TextureType type, 122 egl::Image *image) override; 123 124 angle::Result setImageExternal(const gl::Context *context, 125 gl::TextureType type, 126 egl::Stream *stream, 127 const egl::Stream::GLTextureDescription &desc) override; 128 129 angle::Result generateMipmap(const gl::Context *context) override; 130 131 angle::Result setBaseLevel(const gl::Context *context, GLuint baseLevel) override; 132 133 angle::Result bindTexImage(const gl::Context *context, egl::Surface *surface) override; 134 angle::Result releaseTexImage(const gl::Context *context) override; 135 136 angle::Result getAttachmentRenderTarget(const gl::Context *context, 137 GLenum binding, 138 const gl::ImageIndex &imageIndex, 139 GLsizei samples, 140 FramebufferAttachmentRenderTarget **rtOut) override; 141 142 angle::Result syncState(const gl::Context *context, 143 const gl::Texture::DirtyBits &dirtyBits) override; 144 145 angle::Result setStorageMultisample(const gl::Context *context, 146 gl::TextureType type, 147 GLsizei samples, 148 GLint internalformat, 149 const gl::Extents &size, 150 bool fixedSampleLocations) override; 151 152 angle::Result initializeContents(const gl::Context *context, 153 const gl::ImageIndex &imageIndex) override; 154 isFastUnpackPossible(const vk::Format & vkFormat,size_t offset)155 ANGLE_INLINE bool isFastUnpackPossible(const vk::Format &vkFormat, size_t offset) 156 { 157 // Conditions to determine if fast unpacking is possible 158 // 1. Image must be well defined to unpack directly to it 159 // TODO(http://anglebug.com/3777) Create and stage a temp image instead 160 // 2. Can't perform a fast copy for emulated formats 161 // 3. vkCmdCopyBufferToImage requires byte offset to be a multiple of 4 162 if (mImage->valid() && (vkFormat.intendedFormatID == vkFormat.actualImageFormatID) && 163 ((offset & (kBufferOffsetMultiple - 1)) == 0)) 164 { 165 return true; 166 } 167 168 return false; 169 } 170 getImage()171 const vk::ImageHelper &getImage() const 172 { 173 ASSERT(mImage && mImage->valid()); 174 return *mImage; 175 } 176 getImage()177 vk::ImageHelper &getImage() 178 { 179 ASSERT(mImage && mImage->valid()); 180 return *mImage; 181 } 182 retainImageViews(vk::ResourceUseList * resourceUseList)183 void retainImageViews(vk::ResourceUseList *resourceUseList) 184 { 185 mImageViews.retain(resourceUseList); 186 } 187 188 void releaseOwnershipOfImage(const gl::Context *context); 189 190 const vk::ImageView &getReadImageViewAndRecordUse(ContextVk *contextVk) const; 191 // A special view for cube maps as a 2D array, used with shaders that do texelFetch() and for 192 // seamful cube map emulation. 193 const vk::ImageView &getFetchImageViewAndRecordUse(ContextVk *contextVk) const; 194 angle::Result getStorageImageView(ContextVk *contextVk, 195 bool allLayers, 196 size_t level, 197 size_t singleLayer, 198 const vk::ImageView **imageViewOut); 199 getSampler()200 const vk::Sampler &getSampler() const 201 { 202 ASSERT(mSampler.valid()); 203 return mSampler.get(); 204 } 205 206 // Normally, initialize the image with enabled mipmap level counts. 207 angle::Result ensureImageInitialized(ContextVk *contextVk, ImageMipLevels mipLevels); 208 getSerial()209 Serial getSerial() const { return mSerial; } 210 overrideStagingBufferSizeForTesting(size_t initialSizeForTesting)211 void overrideStagingBufferSizeForTesting(size_t initialSizeForTesting) 212 { 213 mStagingBufferInitialSize = initialSizeForTesting; 214 } 215 216 GLenum getColorReadFormat(const gl::Context *context) override; 217 GLenum getColorReadType(const gl::Context *context) override; 218 219 angle::Result getTexImage(const gl::Context *context, 220 const gl::PixelPackState &packState, 221 gl::Buffer *packBuffer, 222 gl::TextureTarget target, 223 GLint level, 224 GLenum format, 225 GLenum type, 226 void *pixels) override; 227 isBoundAsImageTexture(gl::ContextID contextID)228 ANGLE_INLINE bool isBoundAsImageTexture(gl::ContextID contextID) const 229 { 230 return mState.isBoundAsImageTexture(contextID); 231 } 232 233 private: 234 // Transform an image index from the frontend into one that can be used on the backing 235 // ImageHelper, taking into account mipmap or cube face offsets 236 gl::ImageIndex getNativeImageIndex(const gl::ImageIndex &inputImageIndex) const; 237 uint32_t getNativeImageLevel(uint32_t frontendLevel) const; 238 uint32_t getNativeImageLayer(uint32_t frontendLayer) const; 239 240 void releaseAndDeleteImage(ContextVk *contextVk); 241 angle::Result ensureImageAllocated(ContextVk *contextVk, const vk::Format &format); 242 void setImageHelper(ContextVk *contextVk, 243 vk::ImageHelper *imageHelper, 244 gl::TextureType imageType, 245 const vk::Format &format, 246 uint32_t imageLevelOffset, 247 uint32_t imageLayerOffset, 248 uint32_t imageBaseLevel, 249 bool selfOwned); 250 void updateImageHelper(ContextVk *contextVk, const vk::Format &internalFormat); 251 252 angle::Result redefineImage(const gl::Context *context, 253 const gl::ImageIndex &index, 254 const vk::Format &format, 255 const gl::Extents &size); 256 257 angle::Result setImageImpl(const gl::Context *context, 258 const gl::ImageIndex &index, 259 const gl::InternalFormat &formatInfo, 260 const gl::Extents &size, 261 GLenum type, 262 const gl::PixelUnpackState &unpack, 263 gl::Buffer *unpackBuffer, 264 const uint8_t *pixels); 265 angle::Result setSubImageImpl(const gl::Context *context, 266 const gl::ImageIndex &index, 267 const gl::Box &area, 268 const gl::InternalFormat &formatInfo, 269 GLenum type, 270 const gl::PixelUnpackState &unpack, 271 gl::Buffer *unpackBuffer, 272 const uint8_t *pixels, 273 const vk::Format &vkFormat); 274 275 angle::Result copyImageDataToBufferAndGetData(ContextVk *contextVk, 276 size_t sourceLevel, 277 uint32_t layerCount, 278 const gl::Box &sourceArea, 279 uint8_t **outDataPtr); 280 281 angle::Result copyBufferDataToImage(ContextVk *contextVk, 282 vk::BufferHelper *srcBuffer, 283 const gl::ImageIndex index, 284 uint32_t rowLength, 285 uint32_t imageHeight, 286 const gl::Box &sourceArea, 287 size_t offset); 288 289 angle::Result generateMipmapsWithCPU(const gl::Context *context); 290 291 angle::Result generateMipmapLevelsWithCPU(ContextVk *contextVk, 292 const angle::Format &sourceFormat, 293 GLuint layer, 294 GLuint firstMipLevel, 295 GLuint maxMipLevel, 296 const size_t sourceWidth, 297 const size_t sourceHeight, 298 const size_t sourceDepth, 299 const size_t sourceRowPitch, 300 const size_t sourceDepthPitch, 301 uint8_t *sourceData); 302 303 angle::Result copySubImageImpl(const gl::Context *context, 304 const gl::ImageIndex &index, 305 const gl::Offset &destOffset, 306 const gl::Rectangle &sourceArea, 307 const gl::InternalFormat &internalFormat, 308 gl::Framebuffer *source); 309 310 angle::Result copySubTextureImpl(ContextVk *contextVk, 311 const gl::ImageIndex &index, 312 const gl::Offset &destOffset, 313 const gl::InternalFormat &destFormat, 314 size_t sourceLevel, 315 const gl::Rectangle &sourceArea, 316 bool unpackFlipY, 317 bool unpackPremultiplyAlpha, 318 bool unpackUnmultiplyAlpha, 319 TextureVk *source); 320 321 angle::Result copySubImageImplWithTransfer(ContextVk *contextVk, 322 const gl::ImageIndex &index, 323 const gl::Offset &destOffset, 324 const vk::Format &destFormat, 325 size_t sourceLevel, 326 size_t sourceLayer, 327 const gl::Rectangle &sourceArea, 328 vk::ImageHelper *srcImage); 329 330 angle::Result copySubImageImplWithDraw(ContextVk *contextVk, 331 const gl::ImageIndex &index, 332 const gl::Offset &destOffset, 333 const vk::Format &destFormat, 334 size_t sourceLevel, 335 const gl::Rectangle &sourceArea, 336 bool isSrcFlipY, 337 bool unpackFlipY, 338 bool unpackPremultiplyAlpha, 339 bool unpackUnmultiplyAlpha, 340 vk::ImageHelper *srcImage, 341 const vk::ImageView *srcView); 342 343 angle::Result initImage(ContextVk *contextVk, 344 const vk::Format &format, 345 const bool sized, 346 const gl::Extents &extents, 347 const uint32_t levelCount); 348 void releaseImage(ContextVk *contextVk); 349 void releaseStagingBuffer(ContextVk *contextVk); 350 uint32_t getMipLevelCount(ImageMipLevels mipLevels) const; 351 uint32_t getMaxLevelCount() const; 352 // Used when the image is being redefined (for example to add mips or change base level) to copy 353 // each subresource of the image and stage it for another subresource. When all subresources 354 // are taken care of, the image is recreated. 355 angle::Result copyAndStageImageSubresource(ContextVk *contextVk, 356 const gl::ImageDesc &desc, 357 bool ignoreLayerCount, 358 uint32_t currentLayer, 359 uint32_t sourceLevel, 360 uint32_t stagingDstMipLevel); 361 angle::Result initImageViews(ContextVk *contextVk, 362 const vk::Format &format, 363 const bool sized, 364 uint32_t levelCount, 365 uint32_t layerCount); 366 angle::Result initRenderTargets(ContextVk *contextVk, GLuint layerCount, GLuint levelIndex); 367 angle::Result getLevelLayerImageView(ContextVk *contextVk, 368 size_t level, 369 size_t layer, 370 const vk::ImageView **imageViewOut); 371 372 angle::Result ensureImageInitializedImpl(ContextVk *contextVk, 373 const gl::Extents &baseLevelExtents, 374 uint32_t levelCount, 375 const vk::Format &format); 376 377 const gl::InternalFormat &getImplementationSizedFormat(const gl::Context *context) const; 378 const vk::Format &getBaseLevelFormat(RendererVk *renderer) const; 379 // Queues a flush of any modified image attributes. The image will be reallocated with its new 380 // attributes at the next opportunity. 381 angle::Result respecifyImageAttributes(ContextVk *contextVk); 382 angle::Result respecifyImageAttributesAndLevels(ContextVk *contextVk, 383 GLuint previousBaseLevel, 384 GLuint baseLevel, 385 GLuint maxLevel); 386 387 // Update base and max levels, and re-create image if needed. 388 angle::Result updateBaseMaxLevels(ContextVk *contextVk, GLuint baseLevel, GLuint maxLevel); 389 390 // We monitor the staging buffer and set dirty bits if the staging buffer changes. Note that we 391 // support changes in the staging buffer even outside the TextureVk class. 392 void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override; 393 394 bool mOwnsImage; 395 396 gl::TextureType mImageNativeType; 397 398 // The layer offset to apply when converting from a frontend texture layer to a texture layer in 399 // mImage. Used when this texture sources a cube map face or 3D texture layer from an EGL image. 400 uint32_t mImageLayerOffset; 401 402 // The level offset to apply when converting from a frontend texture level to texture level in 403 // mImage. 404 uint32_t mImageLevelOffset; 405 406 // |mImage| wraps a VkImage and VkDeviceMemory that represents the gl::Texture. |mOwnsImage| 407 // indicates that |TextureVk| owns the image. Otherwise it is a weak pointer shared with another 408 // class. 409 vk::ImageHelper *mImage; 410 411 // |mImageViews| contains all the current views for the Texture. The views are always owned by 412 // the Texture and are not shared like |mImage|. They also have different lifetimes and can be 413 // reallocated independently of |mImage| on state changes. 414 vk::ImageViewHelper mImageViews; 415 416 // |mSampler| contains the relevant Vulkan sampler states reprensenting the OpenGL Texture 417 // sampling states for the Texture. 418 vk::BindingPointer<vk::Sampler> mSampler; 419 420 // Render targets stored as vector of vectors 421 // Level is first dimension, layer is second 422 std::vector<RenderTargetVector> mRenderTargets; 423 424 // The serial is used for cache indexing. 425 Serial mSerial; 426 427 // Overridden in some tests. 428 size_t mStagingBufferInitialSize; 429 430 // The created vkImage usage flag. 431 VkImageUsageFlags mImageUsageFlags; 432 433 // Additional image create flags 434 VkImageCreateFlags mImageCreateFlags; 435 436 angle::ObserverBinding mImageObserverBinding; 437 }; 438 439 } // namespace rx 440 441 #endif // LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_ 442