1 // 2 // Copyright 2018 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 // UtilsVk.h: 7 // Defines the UtilsVk class, a helper for various internal draw/dispatch utilities such as 8 // buffer clear and copy, image clear and copy, texture mip map generation, etc. 9 // 10 // - Convert index buffer: 11 // * Used by VertexArrayVk::convertIndexBufferGPU() to convert a ubyte element array to ushort 12 // - Convert vertex buffer: 13 // * Used by VertexArrayVk::convertVertexBufferGPU() to convert vertex attributes from 14 // unsupported formats to their fallbacks. 15 // - Image clear: Used by FramebufferVk::clearWithDraw(). 16 // - Image copy: Used by TextureVk::copySubImageImplWithDraw(). 17 // - Image copy bits: Used by ImageHelper::CopyImageSubData() to perform bitwise copies between 18 // RGB formats where at least one of src and dst use RGBA as fallback. 19 // - Color blit/resolve: Used by FramebufferVk::blit() to implement blit or multisample resolve 20 // on color images. 21 // - Depth/Stencil blit/resolve: Used by FramebufferVk::blit() to implement blit or multisample 22 // resolve on depth/stencil images. 23 // - Generate mipmap: Used by TextureVk::generateMipmapsWithCompute(). 24 // - Overlay Draw: Used by OverlayVk to draw a UI for debugging. 25 // - Mipmap generation: Used by TextureVk to generate mipmaps more efficiently in compute. 26 // 27 28 #ifndef LIBANGLE_RENDERER_VULKAN_UTILSVK_H_ 29 #define LIBANGLE_RENDERER_VULKAN_UTILSVK_H_ 30 31 #include "libANGLE/renderer/vulkan/vk_cache_utils.h" 32 #include "libANGLE/renderer/vulkan/vk_helpers.h" 33 #include "libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h" 34 35 namespace rx 36 { 37 class UtilsVk : angle::NonCopyable 38 { 39 public: 40 UtilsVk(); 41 ~UtilsVk(); 42 43 void destroy(RendererVk *renderer); 44 45 struct ConvertIndexParameters 46 { 47 uint32_t srcOffset = 0; 48 uint32_t dstOffset = 0; 49 uint32_t maxIndex = 0; 50 }; 51 52 struct ConvertIndexIndirectParameters 53 { 54 uint32_t srcIndirectBufOffset = 0; 55 uint32_t srcIndexBufOffset = 0; 56 uint32_t dstIndexBufOffset = 0; 57 uint32_t maxIndex = 0; 58 uint32_t dstIndirectBufOffset = 0; 59 }; 60 61 struct ConvertLineLoopIndexIndirectParameters 62 { 63 uint32_t indirectBufferOffset = 0; 64 uint32_t dstIndirectBufferOffset = 0; 65 uint32_t srcIndexBufferOffset = 0; 66 uint32_t dstIndexBufferOffset = 0; 67 uint32_t indicesBitsWidth = 0; 68 }; 69 70 struct ConvertLineLoopArrayIndirectParameters 71 { 72 uint32_t indirectBufferOffset = 0; 73 uint32_t dstIndirectBufferOffset = 0; 74 uint32_t dstIndexBufferOffset = 0; 75 }; 76 77 struct ConvertVertexParameters 78 { 79 size_t vertexCount; 80 const angle::Format *srcFormat; 81 const angle::Format *dstFormat; 82 size_t srcStride; 83 size_t srcOffset; 84 size_t dstOffset; 85 }; 86 87 struct ClearFramebufferParameters 88 { 89 // Satisfy chromium-style with a constructor that does what = {} was already doing in a 90 // safer way. 91 ClearFramebufferParameters(); 92 93 gl::Rectangle clearArea; 94 95 bool clearColor; 96 bool clearDepth; 97 bool clearStencil; 98 99 uint8_t stencilMask; 100 VkColorComponentFlags colorMaskFlags; 101 uint32_t colorAttachmentIndexGL; 102 const angle::Format *colorFormat; 103 104 VkClearColorValue colorClearValue; 105 VkClearDepthStencilValue depthStencilClearValue; 106 }; 107 108 struct BlitResolveParameters 109 { 110 // |srcOffset| and |dstIndexBufferOffset| define the original blit/resolve offsets, possibly 111 // flipped. 112 int srcOffset[2]; 113 int dstOffset[2]; 114 // Amount to add to x and y axis for certain rotations 115 int rotatedOffsetFactor[2]; 116 // |stretch| is SourceDimension / DestDimension used to transfer dst coordinates to source. 117 float stretch[2]; 118 // |srcExtents| is used to normalize source coordinates for sampling. 119 int srcExtents[2]; 120 // |blitArea| is the area in destination where blit happens. It's expected that scissor 121 // and source clipping effects have already been applied to it. 122 gl::Rectangle blitArea; 123 int srcLayer; 124 // Whether linear or point sampling should be used. 125 bool linear; 126 bool flipX; 127 bool flipY; 128 SurfaceRotation rotation; 129 }; 130 131 struct ClearImageParameters 132 { 133 gl::Rectangle clearArea; 134 135 vk::LevelIndex dstMip; 136 int dstLayer; 137 138 VkColorComponentFlags colorMaskFlags; 139 VkClearColorValue colorClearValue; 140 }; 141 142 struct CopyImageParameters 143 { 144 int srcOffset[2]; 145 int srcExtents[2]; 146 int dstOffset[2]; 147 int srcMip; 148 int srcLayer; 149 int srcHeight; 150 gl::LevelIndex dstMip; 151 int dstLayer; 152 bool srcPremultiplyAlpha; 153 bool srcUnmultiplyAlpha; 154 bool srcFlipY; 155 bool dstFlipY; 156 SurfaceRotation srcRotation; 157 GLenum srcColorEncoding; 158 GLenum dstColorEncoding; 159 }; 160 161 struct CopyImageBitsParameters 162 { 163 int srcOffset[3]; 164 gl::LevelIndex srcLevel; 165 int dstOffset[3]; 166 gl::LevelIndex dstLevel; 167 uint32_t copyExtents[3]; 168 }; 169 170 struct OverlayDrawParameters 171 { 172 uint32_t textWidgetCount; 173 uint32_t graphWidgetCount; 174 bool rotateXY; 175 }; 176 177 struct GenerateMipmapParameters 178 { 179 uint32_t srcLevel; 180 uint32_t dstLevelCount; 181 }; 182 183 struct UnresolveParameters 184 { 185 gl::DrawBufferMask unresolveColorMask; 186 bool unresolveDepth; 187 bool unresolveStencil; 188 }; 189 190 // Based on the maximum number of levels in GenerateMipmap.comp. 191 static constexpr uint32_t kGenerateMipmapMaxLevels = 6; 192 static uint32_t GetGenerateMipmapMaxLevels(ContextVk *contextVk); 193 194 angle::Result convertIndexBuffer(ContextVk *contextVk, 195 vk::BufferHelper *dst, 196 vk::BufferHelper *src, 197 const ConvertIndexParameters ¶ms); 198 angle::Result convertIndexIndirectBuffer(ContextVk *contextVk, 199 vk::BufferHelper *srcIndirectBuf, 200 vk::BufferHelper *srcIndexBuf, 201 vk::BufferHelper *dstIndirectBuf, 202 vk::BufferHelper *dstIndexBuf, 203 const ConvertIndexIndirectParameters ¶ms); 204 205 angle::Result convertLineLoopIndexIndirectBuffer( 206 ContextVk *contextVk, 207 vk::BufferHelper *srcIndirectBuffer, 208 vk::BufferHelper *dstIndirectBuffer, 209 vk::BufferHelper *dstIndexBuffer, 210 vk::BufferHelper *srcIndexBuffer, 211 const ConvertLineLoopIndexIndirectParameters ¶ms); 212 213 angle::Result convertLineLoopArrayIndirectBuffer( 214 ContextVk *contextVk, 215 vk::BufferHelper *srcIndirectBuffer, 216 vk::BufferHelper *dstIndirectBuffer, 217 vk::BufferHelper *dstIndexBuffer, 218 const ConvertLineLoopArrayIndirectParameters ¶ms); 219 220 angle::Result convertVertexBuffer(ContextVk *contextVk, 221 vk::BufferHelper *dst, 222 vk::BufferHelper *src, 223 const ConvertVertexParameters ¶ms); 224 225 angle::Result clearFramebuffer(ContextVk *contextVk, 226 FramebufferVk *framebuffer, 227 const ClearFramebufferParameters ¶ms); 228 229 // Resolve images if multisampled. Blit otherwise. 230 angle::Result colorBlitResolve(ContextVk *contextVk, 231 FramebufferVk *framebuffer, 232 vk::ImageHelper *src, 233 const vk::ImageView *srcView, 234 const BlitResolveParameters ¶ms); 235 angle::Result depthStencilBlitResolve(ContextVk *contextVk, 236 FramebufferVk *framebuffer, 237 vk::ImageHelper *src, 238 const vk::ImageView *srcDepthView, 239 const vk::ImageView *srcStencilView, 240 const BlitResolveParameters ¶ms); 241 angle::Result stencilBlitResolveNoShaderExport(ContextVk *contextVk, 242 FramebufferVk *framebuffer, 243 vk::ImageHelper *src, 244 const vk::ImageView *srcStencilView, 245 const BlitResolveParameters ¶ms); 246 247 angle::Result clearImage(ContextVk *contextVk, 248 vk::ImageHelper *dst, 249 const ClearImageParameters ¶ms); 250 251 angle::Result copyImage(ContextVk *contextVk, 252 vk::ImageHelper *dst, 253 const vk::ImageView *dstView, 254 vk::ImageHelper *src, 255 const vk::ImageView *srcView, 256 const CopyImageParameters ¶ms); 257 258 angle::Result copyImageBits(ContextVk *contextVk, 259 vk::ImageHelper *dst, 260 vk::ImageHelper *src, 261 const CopyImageBitsParameters ¶ms); 262 263 using GenerateMipmapDestLevelViews = 264 std::array<const vk::ImageView *, kGenerateMipmapMaxLevels>; 265 angle::Result generateMipmap(ContextVk *contextVk, 266 vk::ImageHelper *src, 267 const vk::ImageView *srcLevelZeroView, 268 vk::ImageHelper *dst, 269 const GenerateMipmapDestLevelViews &dstLevelViews, 270 const vk::Sampler &sampler, 271 const GenerateMipmapParameters ¶ms); 272 273 angle::Result unresolve(ContextVk *contextVk, 274 const FramebufferVk *framebuffer, 275 const UnresolveParameters ¶ms); 276 277 // Overlay utilities. 278 angle::Result drawOverlay(ContextVk *contextVk, 279 vk::BufferHelper *textWidgetsBuffer, 280 vk::BufferHelper *graphWidgetsBuffer, 281 vk::ImageHelper *font, 282 const vk::ImageView *fontView, 283 vk::ImageHelper *dst, 284 const vk::ImageView *dstView, 285 const OverlayDrawParameters ¶ms); 286 287 private: 288 ANGLE_ENABLE_STRUCT_PADDING_WARNINGS 289 290 struct ConvertIndexShaderParams 291 { 292 uint32_t srcOffset = 0; 293 uint32_t dstOffsetDiv4 = 0; 294 uint32_t maxIndex = 0; 295 uint32_t _padding = 0; 296 }; 297 298 struct ConvertIndexIndirectShaderParams 299 { 300 uint32_t srcIndirectOffsetDiv4 = 0; 301 uint32_t srcOffset = 0; 302 uint32_t dstOffsetDiv4 = 0; 303 uint32_t maxIndex = 0; 304 uint32_t dstIndirectOffsetDiv4 = 0; 305 }; 306 307 struct ConvertIndexIndirectLineLoopShaderParams 308 { 309 uint32_t cmdOffsetDiv4 = 0; 310 uint32_t dstCmdOffsetDiv4 = 0; 311 uint32_t srcOffset = 0; 312 uint32_t dstOffsetDiv4 = 0; 313 uint32_t isRestartEnabled = 0; 314 }; 315 316 struct ConvertIndirectLineLoopShaderParams 317 { 318 uint32_t cmdOffsetDiv4 = 0; 319 uint32_t dstCmdOffsetDiv4 = 0; 320 uint32_t dstOffsetDiv4 = 0; 321 }; 322 323 struct ConvertVertexShaderParams 324 { 325 ConvertVertexShaderParams(); 326 327 // Structure matching PushConstants in ConvertVertex.comp 328 uint32_t outputCount = 0; 329 uint32_t componentCount = 0; 330 uint32_t srcOffset = 0; 331 uint32_t dstOffset = 0; 332 uint32_t Ns = 0; 333 uint32_t Bs = 0; 334 uint32_t Ss = 0; 335 uint32_t Es = 0; 336 uint32_t Nd = 0; 337 uint32_t Bd = 0; 338 uint32_t Sd = 0; 339 uint32_t Ed = 0; 340 uint32_t srcEmulatedAlpha = 0; 341 uint32_t isSrcHDR = 0; 342 uint32_t isSrcA2BGR10 = 0; 343 uint32_t _padding = 0; 344 }; 345 346 struct ImageClearShaderParams 347 { 348 // Structure matching PushConstants in ImageClear.frag 349 VkClearColorValue clearValue = {}; 350 float clearDepth = 0.0f; 351 }; 352 353 struct ImageCopyShaderParams 354 { 355 ImageCopyShaderParams(); 356 357 // Structure matching PushConstants in ImageCopy.frag 358 int32_t srcOffset[2] = {}; 359 int32_t dstOffset[2] = {}; 360 int32_t srcMip = 0; 361 int32_t srcLayer = 0; 362 uint32_t flipX = 0; 363 uint32_t flipY = 0; 364 uint32_t premultiplyAlpha = 0; 365 uint32_t unmultiplyAlpha = 0; 366 uint32_t dstHasLuminance = 0; 367 uint32_t dstIsAlpha = 0; 368 uint32_t srcIsSRGB = 0; 369 uint32_t dstIsSRGB = 0; 370 uint32_t dstDefaultChannelsMask = 0; 371 uint32_t rotateXY = 0; 372 }; 373 374 union BlitResolveOffset 375 { 376 int32_t resolve[2]; 377 float blit[2]; 378 }; 379 380 struct BlitResolveShaderParams 381 { 382 // Structure matching PushConstants in BlitResolve.frag 383 BlitResolveOffset offset = {}; 384 float stretch[2] = {}; 385 float invSrcExtent[2] = {}; 386 int32_t srcLayer = 0; 387 int32_t samples = 0; 388 float invSamples = 0; 389 uint32_t outputMask = 0; 390 uint32_t flipX = 0; 391 uint32_t flipY = 0; 392 uint32_t rotateXY = 0; 393 }; 394 395 struct BlitResolveStencilNoExportShaderParams 396 { 397 // Structure matching PushConstants in BlitResolveStencilNoExport.comp 398 BlitResolveOffset offset = {}; 399 float stretch[2] = {}; 400 float invSrcExtent[2] = {}; 401 int32_t srcLayer = 0; 402 int32_t srcWidth = 0; 403 int32_t blitArea[4] = {}; 404 int32_t dstPitch = 0; 405 uint32_t flipX = 0; 406 uint32_t flipY = 0; 407 uint32_t rotateXY = 0; 408 }; 409 410 struct OverlayDrawShaderParams 411 { 412 // Structure matching PushConstants in OverlayDraw.vert and OverlayDraw.frag 413 uint32_t viewportSize[2] = {}; 414 uint32_t isText = 0; 415 uint32_t rotateXY = 0; 416 }; 417 418 struct GenerateMipmapShaderParams 419 { 420 // Structure matching PushConstants in GenerateMipmap.comp 421 float invSrcExtent[2] = {}; 422 uint32_t levelCount = 0; 423 }; 424 425 ANGLE_DISABLE_STRUCT_PADDING_WARNINGS 426 427 // Functions implemented by the class: 428 enum class Function 429 { 430 // Functions implemented in graphics 431 ImageClear = 0, 432 ImageCopy = 1, 433 BlitResolve = 2, 434 OverlayDraw = 3, 435 // Note: unresolve is special as it has a different layout per attachment count. Depth and 436 // stencil each require a binding, so are counted separately. 437 Unresolve1Attachment = 4, 438 Unresolve2Attachments = 5, 439 Unresolve3Attachments = 6, 440 Unresolve4Attachments = 7, 441 Unresolve5Attachments = 8, 442 Unresolve6Attachments = 9, 443 Unresolve7Attachments = 10, 444 Unresolve8Attachments = 11, 445 Unresolve9Attachments = 12, 446 Unresolve10Attachments = 13, 447 448 // Functions implemented in compute 449 ComputeStartIndex = 14, // Special value to separate draw and dispatch functions. 450 ConvertIndexBuffer = 14, 451 ConvertVertexBuffer = 15, 452 BlitResolveStencilNoExport = 16, 453 ConvertIndexIndirectBuffer = 17, 454 ConvertIndexIndirectLineLoopBuffer = 18, 455 ConvertIndirectLineLoopBuffer = 19, 456 GenerateMipmap = 20, 457 458 InvalidEnum = 21, 459 EnumCount = 21, 460 }; 461 462 // Common functions that create the pipeline for the specified function, binds it and prepares 463 // the draw/dispatch call. 464 angle::Result setupComputeProgram(ContextVk *contextVk, 465 Function function, 466 vk::RefCounted<vk::ShaderAndSerial> *csShader, 467 vk::ShaderProgramHelper *program, 468 const VkDescriptorSet descriptorSet, 469 const void *pushConstants, 470 size_t pushConstantsSize, 471 vk::OutsideRenderPassCommandBuffer *commandBuffer); 472 angle::Result setupGraphicsProgram(ContextVk *contextVk, 473 Function function, 474 vk::RefCounted<vk::ShaderAndSerial> *vsShader, 475 vk::RefCounted<vk::ShaderAndSerial> *fsShader, 476 vk::ShaderProgramHelper *program, 477 const vk::GraphicsPipelineDesc *pipelineDesc, 478 const VkDescriptorSet descriptorSet, 479 const void *pushConstants, 480 size_t pushConstantsSize, 481 vk::RenderPassCommandBuffer *commandBuffer); 482 483 // Initializes descriptor set layout, pipeline layout and descriptor pool corresponding to given 484 // function, if not already initialized. Uses setSizes to create the layout. For example, if 485 // this array has two entries {STORAGE_TEXEL_BUFFER, 1} and {UNIFORM_TEXEL_BUFFER, 3}, then the 486 // created set layout would be binding 0 for storage texel buffer and bindings 1 through 3 for 487 // uniform texel buffer. All resources are put in set 0. 488 angle::Result ensureResourcesInitialized(ContextVk *contextVk, 489 Function function, 490 VkDescriptorPoolSize *setSizes, 491 size_t setSizesCount, 492 size_t pushConstantsSize); 493 494 // Initializers corresponding to functions, calling into ensureResourcesInitialized with the 495 // appropriate parameters. 496 angle::Result ensureConvertIndexResourcesInitialized(ContextVk *contextVk); 497 angle::Result ensureConvertIndexIndirectResourcesInitialized(ContextVk *contextVk); 498 angle::Result ensureConvertIndexIndirectLineLoopResourcesInitialized(ContextVk *contextVk); 499 angle::Result ensureConvertIndirectLineLoopResourcesInitialized(ContextVk *contextVk); 500 angle::Result ensureConvertVertexResourcesInitialized(ContextVk *contextVk); 501 angle::Result ensureImageClearResourcesInitialized(ContextVk *contextVk); 502 angle::Result ensureImageCopyResourcesInitialized(ContextVk *contextVk); 503 angle::Result ensureBlitResolveResourcesInitialized(ContextVk *contextVk); 504 angle::Result ensureBlitResolveStencilNoExportResourcesInitialized(ContextVk *contextVk); 505 angle::Result ensureOverlayDrawResourcesInitialized(ContextVk *contextVk); 506 angle::Result ensureGenerateMipmapResourcesInitialized(ContextVk *contextVk); 507 angle::Result ensureUnresolveResourcesInitialized(ContextVk *contextVk, 508 Function function, 509 uint32_t attachmentIndex); 510 511 angle::Result ensureSamplersInitialized(ContextVk *context); 512 513 angle::Result startRenderPass(ContextVk *contextVk, 514 vk::ImageHelper *image, 515 const vk::ImageView *imageView, 516 const vk::RenderPassDesc &renderPassDesc, 517 const gl::Rectangle &renderArea, 518 vk::RenderPassCommandBuffer **commandBufferOut); 519 520 // Set up descriptor set and call dispatch. 521 angle::Result convertVertexBufferImpl(ContextVk *contextVk, 522 vk::BufferHelper *dst, 523 vk::BufferHelper *src, 524 uint32_t flags, 525 vk::OutsideRenderPassCommandBuffer *commandBuffer, 526 const ConvertVertexShaderParams &shaderParams); 527 528 // Blits or resolves either color or depth/stencil, based on which view is given. 529 angle::Result blitResolveImpl(ContextVk *contextVk, 530 FramebufferVk *framebuffer, 531 vk::ImageHelper *src, 532 const vk::ImageView *srcColorView, 533 const vk::ImageView *srcDepthView, 534 const vk::ImageView *srcStencilView, 535 const BlitResolveParameters ¶ms); 536 537 // Allocates a single descriptor set. 538 angle::Result allocateDescriptorSet(ContextVk *contextVk, 539 Function function, 540 vk::RefCountedDescriptorPoolBinding *bindingOut, 541 VkDescriptorSet *descriptorSetOut); 542 543 angle::PackedEnumMap<Function, vk::DescriptorSetLayoutPointerArray> mDescriptorSetLayouts; 544 angle::PackedEnumMap<Function, vk::BindingPointer<vk::PipelineLayout>> mPipelineLayouts; 545 angle::PackedEnumMap<Function, vk::DynamicDescriptorPool> mDescriptorPools; 546 547 vk::ShaderProgramHelper mConvertIndexPrograms[vk::InternalShader::ConvertIndex_comp::kArrayLen]; 548 vk::ShaderProgramHelper mConvertIndexIndirectLineLoopPrograms 549 [vk::InternalShader::ConvertIndexIndirectLineLoop_comp::kArrayLen]; 550 vk::ShaderProgramHelper mConvertIndirectLineLoopPrograms 551 [vk::InternalShader::ConvertIndirectLineLoop_comp::kArrayLen]; 552 vk::ShaderProgramHelper 553 mConvertVertexPrograms[vk::InternalShader::ConvertVertex_comp::kArrayLen]; 554 vk::ShaderProgramHelper mImageClearProgramVSOnly; 555 vk::ShaderProgramHelper mImageClearPrograms[vk::InternalShader::ImageClear_frag::kArrayLen]; 556 vk::ShaderProgramHelper mImageCopyPrograms[vk::InternalShader::ImageCopy_frag::kArrayLen]; 557 vk::ShaderProgramHelper mBlitResolvePrograms[vk::InternalShader::BlitResolve_frag::kArrayLen]; 558 vk::ShaderProgramHelper mBlitResolveStencilNoExportPrograms 559 [vk::InternalShader::BlitResolveStencilNoExport_comp::kArrayLen]; 560 vk::ShaderProgramHelper mOverlayDrawProgram; 561 vk::ShaderProgramHelper 562 mGenerateMipmapPrograms[vk::InternalShader::GenerateMipmap_comp::kArrayLen]; 563 564 // Unresolve shaders are special as they are generated on the fly due to the large number of 565 // combinations. 566 std::unordered_map<uint32_t, vk::RefCounted<vk::ShaderAndSerial>> mUnresolveFragShaders; 567 std::unordered_map<uint32_t, vk::ShaderProgramHelper> mUnresolvePrograms; 568 569 vk::Sampler mPointSampler; 570 vk::Sampler mLinearSampler; 571 }; 572 573 } // namespace rx 574 575 #endif // LIBANGLE_RENDERER_VULKAN_UTILSVK_H_ 576