• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &params);
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 &params);
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 &params);
212 
213     angle::Result convertLineLoopArrayIndirectBuffer(
214         ContextVk *contextVk,
215         vk::BufferHelper *srcIndirectBuffer,
216         vk::BufferHelper *dstIndirectBuffer,
217         vk::BufferHelper *dstIndexBuffer,
218         const ConvertLineLoopArrayIndirectParameters &params);
219 
220     angle::Result convertVertexBuffer(ContextVk *contextVk,
221                                       vk::BufferHelper *dst,
222                                       vk::BufferHelper *src,
223                                       const ConvertVertexParameters &params);
224 
225     angle::Result clearFramebuffer(ContextVk *contextVk,
226                                    FramebufferVk *framebuffer,
227                                    const ClearFramebufferParameters &params);
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 &params);
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 &params);
241     angle::Result stencilBlitResolveNoShaderExport(ContextVk *contextVk,
242                                                    FramebufferVk *framebuffer,
243                                                    vk::ImageHelper *src,
244                                                    const vk::ImageView *srcStencilView,
245                                                    const BlitResolveParameters &params);
246 
247     angle::Result clearImage(ContextVk *contextVk,
248                              vk::ImageHelper *dst,
249                              const ClearImageParameters &params);
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 &params);
257 
258     angle::Result copyImageBits(ContextVk *contextVk,
259                                 vk::ImageHelper *dst,
260                                 vk::ImageHelper *src,
261                                 const CopyImageBitsParameters &params);
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 &params);
272 
273     angle::Result unresolve(ContextVk *contextVk,
274                             const FramebufferVk *framebuffer,
275                             const UnresolveParameters &params);
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 &params);
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 &params);
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