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