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 retainSampler(vk::ResourceUseList * resourceUseList)188 void retainSampler(vk::ResourceUseList *resourceUseList) { mSampler.retain(resourceUseList); } 189 190 void releaseOwnershipOfImage(const gl::Context *context); 191 192 const vk::ImageView &getReadImageViewAndRecordUse(ContextVk *contextVk) const; 193 // A special view for cube maps as a 2D array, used with shaders that do texelFetch() and for 194 // seamful cube map emulation. 195 const vk::ImageView &getFetchImageViewAndRecordUse(ContextVk *contextVk) const; 196 angle::Result getStorageImageView(ContextVk *contextVk, 197 bool allLayers, 198 size_t level, 199 size_t singleLayer, 200 const vk::ImageView **imageViewOut); 201 getSampler()202 const vk::Sampler &getSampler() const 203 { 204 ASSERT(mSampler.valid()); 205 return mSampler.get(); 206 } 207 208 // Normally, initialize the image with enabled mipmap level counts. 209 angle::Result ensureImageInitialized(ContextVk *contextVk, ImageMipLevels mipLevels); 210 getSerial()211 Serial getSerial() const { return mSerial; } 212 overrideStagingBufferSizeForTesting(size_t initialSizeForTesting)213 void overrideStagingBufferSizeForTesting(size_t initialSizeForTesting) 214 { 215 mStagingBufferInitialSize = initialSizeForTesting; 216 } 217 218 GLenum getColorReadFormat(const gl::Context *context) override; 219 GLenum getColorReadType(const gl::Context *context) override; 220 221 angle::Result getTexImage(const gl::Context *context, 222 const gl::PixelPackState &packState, 223 gl::Buffer *packBuffer, 224 gl::TextureTarget target, 225 GLint level, 226 GLenum format, 227 GLenum type, 228 void *pixels) override; 229 isBoundAsImageTexture(gl::ContextID contextID)230 ANGLE_INLINE bool isBoundAsImageTexture(gl::ContextID contextID) const 231 { 232 return mState.isBoundAsImageTexture(contextID); 233 } 234 235 private: 236 // Transform an image index from the frontend into one that can be used on the backing 237 // ImageHelper, taking into account mipmap or cube face offsets 238 gl::ImageIndex getNativeImageIndex(const gl::ImageIndex &inputImageIndex) const; 239 uint32_t getNativeImageLevel(uint32_t frontendLevel) const; 240 uint32_t getNativeImageLayer(uint32_t frontendLayer) const; 241 242 void releaseAndDeleteImage(ContextVk *contextVk); 243 angle::Result ensureImageAllocated(ContextVk *contextVk, const vk::Format &format); 244 void setImageHelper(ContextVk *contextVk, 245 vk::ImageHelper *imageHelper, 246 gl::TextureType imageType, 247 const vk::Format &format, 248 uint32_t imageLevelOffset, 249 uint32_t imageLayerOffset, 250 uint32_t imageBaseLevel, 251 bool selfOwned); 252 void updateImageHelper(ContextVk *contextVk, const vk::Format &internalFormat); 253 254 angle::Result redefineImage(const gl::Context *context, 255 const gl::ImageIndex &index, 256 const vk::Format &format, 257 const gl::Extents &size); 258 259 angle::Result setImageImpl(const gl::Context *context, 260 const gl::ImageIndex &index, 261 const gl::InternalFormat &formatInfo, 262 const gl::Extents &size, 263 GLenum type, 264 const gl::PixelUnpackState &unpack, 265 gl::Buffer *unpackBuffer, 266 const uint8_t *pixels); 267 angle::Result setSubImageImpl(const gl::Context *context, 268 const gl::ImageIndex &index, 269 const gl::Box &area, 270 const gl::InternalFormat &formatInfo, 271 GLenum type, 272 const gl::PixelUnpackState &unpack, 273 gl::Buffer *unpackBuffer, 274 const uint8_t *pixels, 275 const vk::Format &vkFormat); 276 277 angle::Result copyImageDataToBufferAndGetData(ContextVk *contextVk, 278 size_t sourceLevel, 279 uint32_t layerCount, 280 const gl::Box &sourceArea, 281 uint8_t **outDataPtr); 282 283 angle::Result copyBufferDataToImage(ContextVk *contextVk, 284 vk::BufferHelper *srcBuffer, 285 const gl::ImageIndex index, 286 uint32_t rowLength, 287 uint32_t imageHeight, 288 const gl::Box &sourceArea, 289 size_t offset); 290 291 angle::Result generateMipmapsWithCPU(const gl::Context *context); 292 293 angle::Result generateMipmapLevelsWithCPU(ContextVk *contextVk, 294 const angle::Format &sourceFormat, 295 GLuint layer, 296 GLuint firstMipLevel, 297 GLuint maxMipLevel, 298 const size_t sourceWidth, 299 const size_t sourceHeight, 300 const size_t sourceDepth, 301 const size_t sourceRowPitch, 302 const size_t sourceDepthPitch, 303 uint8_t *sourceData); 304 305 angle::Result copySubImageImpl(const gl::Context *context, 306 const gl::ImageIndex &index, 307 const gl::Offset &destOffset, 308 const gl::Rectangle &sourceArea, 309 const gl::InternalFormat &internalFormat, 310 gl::Framebuffer *source); 311 312 angle::Result copySubTextureImpl(ContextVk *contextVk, 313 const gl::ImageIndex &index, 314 const gl::Offset &destOffset, 315 const gl::InternalFormat &destFormat, 316 size_t sourceLevel, 317 const gl::Rectangle &sourceArea, 318 bool unpackFlipY, 319 bool unpackPremultiplyAlpha, 320 bool unpackUnmultiplyAlpha, 321 TextureVk *source); 322 323 angle::Result copySubImageImplWithTransfer(ContextVk *contextVk, 324 const gl::ImageIndex &index, 325 const gl::Offset &destOffset, 326 const vk::Format &destFormat, 327 size_t sourceLevel, 328 size_t sourceLayer, 329 const gl::Rectangle &sourceArea, 330 vk::ImageHelper *srcImage); 331 332 angle::Result copySubImageImplWithDraw(ContextVk *contextVk, 333 const gl::ImageIndex &index, 334 const gl::Offset &destOffset, 335 const vk::Format &destFormat, 336 size_t sourceLevel, 337 const gl::Rectangle &sourceArea, 338 bool isSrcFlipY, 339 bool unpackFlipY, 340 bool unpackPremultiplyAlpha, 341 bool unpackUnmultiplyAlpha, 342 vk::ImageHelper *srcImage, 343 const vk::ImageView *srcView); 344 345 angle::Result initImage(ContextVk *contextVk, 346 const vk::Format &format, 347 const bool sized, 348 const gl::Extents &extents, 349 const uint32_t levelCount); 350 void releaseImage(ContextVk *contextVk); 351 void releaseStagingBuffer(ContextVk *contextVk); 352 uint32_t getMipLevelCount(ImageMipLevels mipLevels) const; 353 uint32_t getMaxLevelCount() const; 354 // Used when the image is being redefined (for example to add mips or change base level) to copy 355 // each subresource of the image and stage it for another subresource. When all subresources 356 // are taken care of, the image is recreated. 357 angle::Result copyAndStageImageSubresource(ContextVk *contextVk, 358 const gl::ImageDesc &desc, 359 bool ignoreLayerCount, 360 uint32_t currentLayer, 361 uint32_t sourceLevel, 362 uint32_t stagingDstMipLevel); 363 angle::Result initImageViews(ContextVk *contextVk, 364 const vk::Format &format, 365 const bool sized, 366 uint32_t levelCount, 367 uint32_t layerCount); 368 angle::Result initRenderTargets(ContextVk *contextVk, GLuint layerCount, GLuint levelIndex); 369 angle::Result getLevelLayerImageView(ContextVk *contextVk, 370 size_t level, 371 size_t layer, 372 const vk::ImageView **imageViewOut); 373 374 angle::Result ensureImageInitializedImpl(ContextVk *contextVk, 375 const gl::Extents &baseLevelExtents, 376 uint32_t levelCount, 377 const vk::Format &format); 378 379 const gl::InternalFormat &getImplementationSizedFormat(const gl::Context *context) const; 380 const vk::Format &getBaseLevelFormat(RendererVk *renderer) const; 381 // Re-create the image. 382 angle::Result changeLevels(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::SamplerHelper 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 angle::ObserverBinding mStagingBufferObserverBinding; 434 }; 435 436 } // namespace rx 437 438 #endif // LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_ 439