• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // vk_utils:
7 //    Helper functions for the Vulkan Renderer.
8 //
9 
10 #include "libANGLE/renderer/vulkan/vk_utils.h"
11 
12 #include "libANGLE/Context.h"
13 #include "libANGLE/Display.h"
14 #include "libANGLE/renderer/vulkan/BufferVk.h"
15 #include "libANGLE/renderer/vulkan/ContextVk.h"
16 #include "libANGLE/renderer/vulkan/DisplayVk.h"
17 #include "libANGLE/renderer/vulkan/android/vk_android_utils.h"
18 #include "libANGLE/renderer/vulkan/vk_mem_alloc_wrapper.h"
19 #include "libANGLE/renderer/vulkan/vk_ref_counted_event.h"
20 #include "libANGLE/renderer/vulkan/vk_renderer.h"
21 #include "libANGLE/renderer/vulkan/vk_resource.h"
22 
23 namespace angle
24 {
ToEGL(Result result,EGLint errorCode)25 egl::Error ToEGL(Result result, EGLint errorCode)
26 {
27     if (result != angle::Result::Continue)
28     {
29         egl::Error error = std::move(*egl::Display::GetCurrentThreadErrorScratchSpace());
30         error.setCode(errorCode);
31         return error;
32     }
33     else
34     {
35         return egl::NoError();
36     }
37 }
38 }  // namespace angle
39 
40 namespace rx
41 {
42 namespace
43 {
44 // Pick an arbitrary value to initialize non-zero memory for sanitization.  Note that 0x3F3F3F3F
45 // as float is about 0.75.
46 constexpr int kNonZeroInitValue = 0x3F;
47 
GetStagingBufferUsageFlags(vk::StagingUsage usage)48 VkImageUsageFlags GetStagingBufferUsageFlags(vk::StagingUsage usage)
49 {
50     switch (usage)
51     {
52         case vk::StagingUsage::Read:
53             return VK_BUFFER_USAGE_TRANSFER_DST_BIT;
54         case vk::StagingUsage::Write:
55             return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
56         case vk::StagingUsage::Both:
57             return (VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
58         default:
59             UNREACHABLE();
60             return 0;
61     }
62 }
63 
FindCompatibleMemory(const VkPhysicalDeviceMemoryProperties & memoryProperties,const VkMemoryRequirements & memoryRequirements,VkMemoryPropertyFlags requestedMemoryPropertyFlags,VkMemoryPropertyFlags * memoryPropertyFlagsOut,uint32_t * typeIndexOut)64 bool FindCompatibleMemory(const VkPhysicalDeviceMemoryProperties &memoryProperties,
65                           const VkMemoryRequirements &memoryRequirements,
66                           VkMemoryPropertyFlags requestedMemoryPropertyFlags,
67                           VkMemoryPropertyFlags *memoryPropertyFlagsOut,
68                           uint32_t *typeIndexOut)
69 {
70     for (size_t memoryIndex : angle::BitSet32<32>(memoryRequirements.memoryTypeBits))
71     {
72         ASSERT(memoryIndex < memoryProperties.memoryTypeCount);
73 
74         if ((memoryProperties.memoryTypes[memoryIndex].propertyFlags &
75              requestedMemoryPropertyFlags) == requestedMemoryPropertyFlags)
76         {
77             *memoryPropertyFlagsOut = memoryProperties.memoryTypes[memoryIndex].propertyFlags;
78             *typeIndexOut           = static_cast<uint32_t>(memoryIndex);
79             return true;
80         }
81     }
82 
83     return false;
84 }
85 
FindAndAllocateCompatibleMemory(vk::Context * context,vk::MemoryAllocationType memoryAllocationType,const vk::MemoryProperties & memoryProperties,VkMemoryPropertyFlags requestedMemoryPropertyFlags,VkMemoryPropertyFlags * memoryPropertyFlagsOut,const VkMemoryRequirements & memoryRequirements,const void * extraAllocationInfo,uint32_t * memoryTypeIndexOut,vk::DeviceMemory * deviceMemoryOut)86 VkResult FindAndAllocateCompatibleMemory(vk::Context *context,
87                                          vk::MemoryAllocationType memoryAllocationType,
88                                          const vk::MemoryProperties &memoryProperties,
89                                          VkMemoryPropertyFlags requestedMemoryPropertyFlags,
90                                          VkMemoryPropertyFlags *memoryPropertyFlagsOut,
91                                          const VkMemoryRequirements &memoryRequirements,
92                                          const void *extraAllocationInfo,
93                                          uint32_t *memoryTypeIndexOut,
94                                          vk::DeviceMemory *deviceMemoryOut)
95 {
96     VkDevice device = context->getDevice();
97 
98     VK_RESULT_TRY(memoryProperties.findCompatibleMemoryIndex(
99         context, memoryRequirements, requestedMemoryPropertyFlags, (extraAllocationInfo != nullptr),
100         memoryPropertyFlagsOut, memoryTypeIndexOut));
101 
102     VkMemoryAllocateInfo allocInfo = {};
103     allocInfo.sType                = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
104     allocInfo.pNext                = extraAllocationInfo;
105     allocInfo.memoryTypeIndex      = *memoryTypeIndexOut;
106     allocInfo.allocationSize       = memoryRequirements.size;
107 
108     // Add the new allocation for tracking.
109     vk::Renderer *renderer = context->getRenderer();
110     renderer->getMemoryAllocationTracker()->setPendingMemoryAlloc(
111         memoryAllocationType, allocInfo.allocationSize, *memoryTypeIndexOut);
112 
113     VkResult result = deviceMemoryOut->allocate(device, allocInfo);
114 
115     if (result == VK_SUCCESS)
116     {
117         renderer->onMemoryAlloc(memoryAllocationType, allocInfo.allocationSize, *memoryTypeIndexOut,
118                                 deviceMemoryOut->getHandle());
119     }
120     return result;
121 }
122 
123 template <typename T>
124 VkResult AllocateAndBindBufferOrImageMemory(vk::Context *context,
125                                             vk::MemoryAllocationType memoryAllocationType,
126                                             VkMemoryPropertyFlags requestedMemoryPropertyFlags,
127                                             VkMemoryPropertyFlags *memoryPropertyFlagsOut,
128                                             const VkMemoryRequirements &memoryRequirements,
129                                             const void *extraAllocationInfo,
130                                             const VkBindImagePlaneMemoryInfoKHR *extraBindInfo,
131                                             T *bufferOrImage,
132                                             uint32_t *memoryTypeIndexOut,
133                                             vk::DeviceMemory *deviceMemoryOut);
134 
135 template <>
AllocateAndBindBufferOrImageMemory(vk::Context * context,vk::MemoryAllocationType memoryAllocationType,VkMemoryPropertyFlags requestedMemoryPropertyFlags,VkMemoryPropertyFlags * memoryPropertyFlagsOut,const VkMemoryRequirements & memoryRequirements,const void * extraAllocationInfo,const VkBindImagePlaneMemoryInfoKHR * extraBindInfo,vk::Image * image,uint32_t * memoryTypeIndexOut,vk::DeviceMemory * deviceMemoryOut)136 VkResult AllocateAndBindBufferOrImageMemory(vk::Context *context,
137                                             vk::MemoryAllocationType memoryAllocationType,
138                                             VkMemoryPropertyFlags requestedMemoryPropertyFlags,
139                                             VkMemoryPropertyFlags *memoryPropertyFlagsOut,
140                                             const VkMemoryRequirements &memoryRequirements,
141                                             const void *extraAllocationInfo,
142                                             const VkBindImagePlaneMemoryInfoKHR *extraBindInfo,
143                                             vk::Image *image,
144                                             uint32_t *memoryTypeIndexOut,
145                                             vk::DeviceMemory *deviceMemoryOut)
146 {
147     const vk::MemoryProperties &memoryProperties = context->getRenderer()->getMemoryProperties();
148 
149     VK_RESULT_TRY(FindAndAllocateCompatibleMemory(
150         context, memoryAllocationType, memoryProperties, requestedMemoryPropertyFlags,
151         memoryPropertyFlagsOut, memoryRequirements, extraAllocationInfo, memoryTypeIndexOut,
152         deviceMemoryOut));
153 
154     if (extraBindInfo)
155     {
156         VkBindImageMemoryInfoKHR bindInfo = {};
157         bindInfo.sType                    = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
158         bindInfo.pNext                    = extraBindInfo;
159         bindInfo.image                    = image->getHandle();
160         bindInfo.memory                   = deviceMemoryOut->getHandle();
161         bindInfo.memoryOffset             = 0;
162 
163         VK_RESULT_TRY(image->bindMemory2(context->getDevice(), bindInfo));
164     }
165     else
166     {
167         VK_RESULT_TRY(image->bindMemory(context->getDevice(), *deviceMemoryOut));
168     }
169 
170     return VK_SUCCESS;
171 }
172 
173 template <>
AllocateAndBindBufferOrImageMemory(vk::Context * context,vk::MemoryAllocationType memoryAllocationType,VkMemoryPropertyFlags requestedMemoryPropertyFlags,VkMemoryPropertyFlags * memoryPropertyFlagsOut,const VkMemoryRequirements & memoryRequirements,const void * extraAllocationInfo,const VkBindImagePlaneMemoryInfoKHR * extraBindInfo,vk::Buffer * buffer,uint32_t * memoryTypeIndexOut,vk::DeviceMemory * deviceMemoryOut)174 VkResult AllocateAndBindBufferOrImageMemory(vk::Context *context,
175                                             vk::MemoryAllocationType memoryAllocationType,
176                                             VkMemoryPropertyFlags requestedMemoryPropertyFlags,
177                                             VkMemoryPropertyFlags *memoryPropertyFlagsOut,
178                                             const VkMemoryRequirements &memoryRequirements,
179                                             const void *extraAllocationInfo,
180                                             const VkBindImagePlaneMemoryInfoKHR *extraBindInfo,
181                                             vk::Buffer *buffer,
182                                             uint32_t *memoryTypeIndexOut,
183                                             vk::DeviceMemory *deviceMemoryOut)
184 {
185     ASSERT(extraBindInfo == nullptr);
186 
187     const vk::MemoryProperties &memoryProperties = context->getRenderer()->getMemoryProperties();
188 
189     VK_RESULT_TRY(FindAndAllocateCompatibleMemory(
190         context, memoryAllocationType, memoryProperties, requestedMemoryPropertyFlags,
191         memoryPropertyFlagsOut, memoryRequirements, extraAllocationInfo, memoryTypeIndexOut,
192         deviceMemoryOut));
193 
194     VK_RESULT_TRY(buffer->bindMemory(context->getDevice(), *deviceMemoryOut, 0));
195     return VK_SUCCESS;
196 }
197 
198 template <typename T>
AllocateBufferOrImageMemory(vk::Context * context,vk::MemoryAllocationType memoryAllocationType,VkMemoryPropertyFlags requestedMemoryPropertyFlags,VkMemoryPropertyFlags * memoryPropertyFlagsOut,const void * extraAllocationInfo,T * bufferOrImage,uint32_t * memoryTypeIndexOut,vk::DeviceMemory * deviceMemoryOut,VkDeviceSize * sizeOut)199 VkResult AllocateBufferOrImageMemory(vk::Context *context,
200                                      vk::MemoryAllocationType memoryAllocationType,
201                                      VkMemoryPropertyFlags requestedMemoryPropertyFlags,
202                                      VkMemoryPropertyFlags *memoryPropertyFlagsOut,
203                                      const void *extraAllocationInfo,
204                                      T *bufferOrImage,
205                                      uint32_t *memoryTypeIndexOut,
206                                      vk::DeviceMemory *deviceMemoryOut,
207                                      VkDeviceSize *sizeOut)
208 {
209     // Call driver to determine memory requirements.
210     VkMemoryRequirements memoryRequirements;
211     bufferOrImage->getMemoryRequirements(context->getDevice(), &memoryRequirements);
212 
213     VK_RESULT_TRY(AllocateAndBindBufferOrImageMemory(
214         context, memoryAllocationType, requestedMemoryPropertyFlags, memoryPropertyFlagsOut,
215         memoryRequirements, extraAllocationInfo, nullptr, bufferOrImage, memoryTypeIndexOut,
216         deviceMemoryOut));
217 
218     *sizeOut = memoryRequirements.size;
219 
220     return VK_SUCCESS;
221 }
222 
223 // Unified layer that includes full validation layer stack
224 constexpr char kVkKhronosValidationLayerName[]  = "VK_LAYER_KHRONOS_validation";
225 constexpr char kVkStandardValidationLayerName[] = "VK_LAYER_LUNARG_standard_validation";
226 const char *kVkValidationLayerNames[]           = {
227     "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation",
228     "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation",
229     "VK_LAYER_GOOGLE_unique_objects"};
230 
231 }  // anonymous namespace
232 
VulkanResultString(VkResult result)233 const char *VulkanResultString(VkResult result)
234 {
235     switch (result)
236     {
237         case VK_SUCCESS:
238             return "Command successfully completed";
239         case VK_NOT_READY:
240             return "A fence or query has not yet completed";
241         case VK_TIMEOUT:
242             return "A wait operation has not completed in the specified time";
243         case VK_EVENT_SET:
244             return "An event is signaled";
245         case VK_EVENT_RESET:
246             return "An event is unsignaled";
247         case VK_INCOMPLETE:
248             return "A return array was too small for the result";
249         case VK_SUBOPTIMAL_KHR:
250             return "A swapchain no longer matches the surface properties exactly, but can still be "
251                    "used to present to the surface successfully";
252         case VK_ERROR_OUT_OF_HOST_MEMORY:
253             return "A host memory allocation has failed";
254         case VK_ERROR_OUT_OF_DEVICE_MEMORY:
255             return "A device memory allocation has failed";
256         case VK_ERROR_INITIALIZATION_FAILED:
257             return "Initialization of an object could not be completed for implementation-specific "
258                    "reasons";
259         case VK_ERROR_DEVICE_LOST:
260             return "The logical or physical device has been lost";
261         case VK_ERROR_MEMORY_MAP_FAILED:
262             return "Mapping of a memory object has failed";
263         case VK_ERROR_LAYER_NOT_PRESENT:
264             return "A requested layer is not present or could not be loaded";
265         case VK_ERROR_EXTENSION_NOT_PRESENT:
266             return "A requested extension is not supported";
267         case VK_ERROR_FEATURE_NOT_PRESENT:
268             return "A requested feature is not supported";
269         case VK_ERROR_INCOMPATIBLE_DRIVER:
270             return "The requested version of Vulkan is not supported by the driver or is otherwise "
271                    "incompatible for implementation-specific reasons";
272         case VK_ERROR_TOO_MANY_OBJECTS:
273             return "Too many objects of the type have already been created";
274         case VK_ERROR_FORMAT_NOT_SUPPORTED:
275             return "A requested format is not supported on this device";
276         case VK_ERROR_SURFACE_LOST_KHR:
277             return "A surface is no longer available";
278         case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
279             return "The requested window is already connected to a VkSurfaceKHR, or to some other "
280                    "non-Vulkan API";
281         case VK_ERROR_OUT_OF_DATE_KHR:
282             return "A surface has changed in such a way that it is no longer compatible with the "
283                    "swapchain";
284         case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
285             return "The display used by a swapchain does not use the same presentable image "
286                    "layout, or is incompatible in a way that prevents sharing an image";
287         case VK_ERROR_VALIDATION_FAILED_EXT:
288             return "The validation layers detected invalid API usage";
289         case VK_ERROR_INVALID_SHADER_NV:
290             return "Invalid Vulkan shader was generated";
291         case VK_ERROR_OUT_OF_POOL_MEMORY:
292             return "A pool memory allocation has failed";
293         case VK_ERROR_FRAGMENTED_POOL:
294             return "A pool allocation has failed due to fragmentation of the pool's memory";
295         case VK_ERROR_INVALID_EXTERNAL_HANDLE:
296             return "An external handle is not a valid handle of the specified type";
297         default:
298             return "Unknown vulkan error code";
299     }
300 }
301 
GetAvailableValidationLayers(const std::vector<VkLayerProperties> & layerProps,bool mustHaveLayers,VulkanLayerVector * enabledLayerNames)302 bool GetAvailableValidationLayers(const std::vector<VkLayerProperties> &layerProps,
303                                   bool mustHaveLayers,
304                                   VulkanLayerVector *enabledLayerNames)
305 {
306 
307     ASSERT(enabledLayerNames);
308     for (const auto &layerProp : layerProps)
309     {
310         std::string layerPropLayerName = std::string(layerProp.layerName);
311 
312         // Favor unified Khronos layer, but fallback to standard validation
313         if (layerPropLayerName == kVkKhronosValidationLayerName)
314         {
315             enabledLayerNames->push_back(kVkKhronosValidationLayerName);
316             continue;
317         }
318         else if (layerPropLayerName == kVkStandardValidationLayerName)
319         {
320             enabledLayerNames->push_back(kVkStandardValidationLayerName);
321             continue;
322         }
323 
324         for (const char *validationLayerName : kVkValidationLayerNames)
325         {
326             if (layerPropLayerName == validationLayerName)
327             {
328                 enabledLayerNames->push_back(validationLayerName);
329                 break;
330             }
331         }
332     }
333 
334     if (enabledLayerNames->size() == 0)
335     {
336         // Generate an error if the layers were explicitly requested, warning otherwise.
337         if (mustHaveLayers)
338         {
339             ERR() << "Vulkan validation layers are missing.";
340         }
341         else
342         {
343             WARN() << "Vulkan validation layers are missing.";
344         }
345 
346         return false;
347     }
348 
349     return true;
350 }
351 
352 namespace vk
353 {
354 const char *gLoaderLayersPathEnv   = "VK_LAYER_PATH";
355 const char *gLoaderICDFilenamesEnv = "VK_ICD_FILENAMES";
356 
GetDepthStencilAspectFlags(const angle::Format & format)357 VkImageAspectFlags GetDepthStencilAspectFlags(const angle::Format &format)
358 {
359     return (format.depthBits > 0 ? VK_IMAGE_ASPECT_DEPTH_BIT : 0) |
360            (format.stencilBits > 0 ? VK_IMAGE_ASPECT_STENCIL_BIT : 0);
361 }
362 
GetFormatAspectFlags(const angle::Format & format)363 VkImageAspectFlags GetFormatAspectFlags(const angle::Format &format)
364 {
365     VkImageAspectFlags dsAspect = GetDepthStencilAspectFlags(format);
366     // If the image is not depth stencil, assume color aspect.  Note that detecting color formats
367     // is less trivial than depth/stencil, e.g. as block formats don't indicate any bits for RGBA
368     // channels.
369     return dsAspect != 0 ? dsAspect : VK_IMAGE_ASPECT_COLOR_BIT;
370 }
371 
372 // Context implementation.
Context(Renderer * renderer)373 Context::Context(Renderer *renderer)
374     : mRenderer(renderer), mShareGroupRefCountedEventsGarbageRecycler(nullptr), mPerfCounters{}
375 {}
376 
~Context()377 Context::~Context() {}
378 
getDevice() const379 VkDevice Context::getDevice() const
380 {
381     return mRenderer->getDevice();
382 }
383 
getFeatures() const384 const angle::FeaturesVk &Context::getFeatures() const
385 {
386     return mRenderer->getFeatures();
387 }
388 
389 // MemoryProperties implementation.
MemoryProperties()390 MemoryProperties::MemoryProperties() : mMemoryProperties{} {}
391 
init(VkPhysicalDevice physicalDevice)392 void MemoryProperties::init(VkPhysicalDevice physicalDevice)
393 {
394     ASSERT(mMemoryProperties.memoryTypeCount == 0);
395     vkGetPhysicalDeviceMemoryProperties(physicalDevice, &mMemoryProperties);
396     ASSERT(mMemoryProperties.memoryTypeCount > 0);
397 }
398 
destroy()399 void MemoryProperties::destroy()
400 {
401     mMemoryProperties = {};
402 }
403 
hasLazilyAllocatedMemory() const404 bool MemoryProperties::hasLazilyAllocatedMemory() const
405 {
406     for (uint32_t typeIndex = 0; typeIndex < mMemoryProperties.memoryTypeCount; ++typeIndex)
407     {
408         const VkMemoryType &memoryType = mMemoryProperties.memoryTypes[typeIndex];
409         if ((memoryType.propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) != 0)
410         {
411             return true;
412         }
413     }
414     return false;
415 }
416 
findCompatibleMemoryIndex(Context * context,const VkMemoryRequirements & memoryRequirements,VkMemoryPropertyFlags requestedMemoryPropertyFlags,bool isExternalMemory,VkMemoryPropertyFlags * memoryPropertyFlagsOut,uint32_t * typeIndexOut) const417 VkResult MemoryProperties::findCompatibleMemoryIndex(
418     Context *context,
419     const VkMemoryRequirements &memoryRequirements,
420     VkMemoryPropertyFlags requestedMemoryPropertyFlags,
421     bool isExternalMemory,
422     VkMemoryPropertyFlags *memoryPropertyFlagsOut,
423     uint32_t *typeIndexOut) const
424 {
425     ASSERT(mMemoryProperties.memoryTypeCount > 0 && mMemoryProperties.memoryTypeCount <= 32);
426 
427     // Find a compatible memory pool index. If the index doesn't change, we could cache it.
428     // Not finding a valid memory pool means an out-of-spec driver, or internal error.
429     // TODO(jmadill): Determine if it is possible to cache indexes.
430     // TODO(jmadill): More efficient memory allocation.
431     if (FindCompatibleMemory(mMemoryProperties, memoryRequirements, requestedMemoryPropertyFlags,
432                              memoryPropertyFlagsOut, typeIndexOut))
433     {
434         return VK_SUCCESS;
435     }
436 
437     // We did not find a compatible memory type.  If the caller wanted a host visible memory, just
438     // return the memory index with fallback, guaranteed, memory flags.
439     if (requestedMemoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
440     {
441         // The Vulkan spec says the following -
442         //     There must be at least one memory type with both the
443         //     VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT and VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
444         //     bits set in its propertyFlags
445         constexpr VkMemoryPropertyFlags fallbackMemoryPropertyFlags =
446             VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
447 
448         if (FindCompatibleMemory(mMemoryProperties, memoryRequirements, fallbackMemoryPropertyFlags,
449                                  memoryPropertyFlagsOut, typeIndexOut))
450         {
451             return VK_SUCCESS;
452         }
453     }
454 
455     // We did not find a compatible memory type. When importing external memory, there may be
456     // additional restrictions on memoryType. Find the first available memory type that Vulkan
457     // driver decides being compatible with external memory import.
458     if (isExternalMemory)
459     {
460         if (FindCompatibleMemory(mMemoryProperties, memoryRequirements, 0, memoryPropertyFlagsOut,
461                                  typeIndexOut))
462         {
463             return VK_SUCCESS;
464         }
465     }
466 
467     // TODO(jmadill): Add error message to error.
468     return VK_ERROR_INCOMPATIBLE_DRIVER;
469 }
470 
471 // StagingBuffer implementation.
StagingBuffer()472 StagingBuffer::StagingBuffer() : mSize(0) {}
473 
destroy(Renderer * renderer)474 void StagingBuffer::destroy(Renderer *renderer)
475 {
476     VkDevice device = renderer->getDevice();
477     mBuffer.destroy(device);
478     mAllocation.destroy(renderer->getAllocator());
479     mSize = 0;
480 }
481 
init(Context * context,VkDeviceSize size,StagingUsage usage)482 angle::Result StagingBuffer::init(Context *context, VkDeviceSize size, StagingUsage usage)
483 {
484     VkBufferCreateInfo createInfo    = {};
485     createInfo.sType                 = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
486     createInfo.flags                 = 0;
487     createInfo.size                  = size;
488     createInfo.usage                 = GetStagingBufferUsageFlags(usage);
489     createInfo.sharingMode           = VK_SHARING_MODE_EXCLUSIVE;
490     createInfo.queueFamilyIndexCount = 0;
491     createInfo.pQueueFamilyIndices   = nullptr;
492 
493     VkMemoryPropertyFlags preferredFlags = 0;
494     VkMemoryPropertyFlags requiredFlags =
495         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
496 
497     Renderer *renderer         = context->getRenderer();
498     const Allocator &allocator = renderer->getAllocator();
499 
500     uint32_t memoryTypeIndex = 0;
501     ANGLE_VK_TRY(context,
502                  allocator.createBuffer(createInfo, requiredFlags, preferredFlags,
503                                         renderer->getFeatures().persistentlyMappedBuffers.enabled,
504                                         &memoryTypeIndex, &mBuffer, &mAllocation));
505     mSize = static_cast<size_t>(size);
506 
507     // Wipe memory to an invalid value when the 'allocateNonZeroMemory' feature is enabled. The
508     // invalid values ensures our testing doesn't assume zero-initialized memory.
509     if (renderer->getFeatures().allocateNonZeroMemory.enabled)
510     {
511         ANGLE_TRY(InitMappableAllocation(context, allocator, &mAllocation, size, kNonZeroInitValue,
512                                          requiredFlags));
513     }
514 
515     return angle::Result::Continue;
516 }
517 
release(ContextVk * contextVk)518 void StagingBuffer::release(ContextVk *contextVk)
519 {
520     contextVk->addGarbage(&mBuffer);
521     contextVk->addGarbage(&mAllocation);
522 }
523 
collectGarbage(Renderer * renderer,const QueueSerial & queueSerial)524 void StagingBuffer::collectGarbage(Renderer *renderer, const QueueSerial &queueSerial)
525 {
526     GarbageObjects garbageObjects;
527     garbageObjects.emplace_back(GetGarbage(&mBuffer));
528     garbageObjects.emplace_back(GetGarbage(&mAllocation));
529 
530     ResourceUse use(queueSerial);
531     renderer->collectGarbage(use, std::move(garbageObjects));
532 }
533 
InitMappableAllocation(Context * context,const Allocator & allocator,Allocation * allocation,VkDeviceSize size,int value,VkMemoryPropertyFlags memoryPropertyFlags)534 angle::Result InitMappableAllocation(Context *context,
535                                      const Allocator &allocator,
536                                      Allocation *allocation,
537                                      VkDeviceSize size,
538                                      int value,
539                                      VkMemoryPropertyFlags memoryPropertyFlags)
540 {
541     uint8_t *mapPointer;
542     ANGLE_VK_TRY(context, allocation->map(allocator, &mapPointer));
543     memset(mapPointer, value, static_cast<size_t>(size));
544 
545     if ((memoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
546     {
547         allocation->flush(allocator, 0, size);
548     }
549 
550     allocation->unmap(allocator);
551 
552     return angle::Result::Continue;
553 }
554 
AllocateBufferMemory(Context * context,vk::MemoryAllocationType memoryAllocationType,VkMemoryPropertyFlags requestedMemoryPropertyFlags,VkMemoryPropertyFlags * memoryPropertyFlagsOut,const void * extraAllocationInfo,Buffer * buffer,uint32_t * memoryTypeIndexOut,DeviceMemory * deviceMemoryOut,VkDeviceSize * sizeOut)555 VkResult AllocateBufferMemory(Context *context,
556                               vk::MemoryAllocationType memoryAllocationType,
557                               VkMemoryPropertyFlags requestedMemoryPropertyFlags,
558                               VkMemoryPropertyFlags *memoryPropertyFlagsOut,
559                               const void *extraAllocationInfo,
560                               Buffer *buffer,
561                               uint32_t *memoryTypeIndexOut,
562                               DeviceMemory *deviceMemoryOut,
563                               VkDeviceSize *sizeOut)
564 {
565     return AllocateBufferOrImageMemory(context, memoryAllocationType, requestedMemoryPropertyFlags,
566                                        memoryPropertyFlagsOut, extraAllocationInfo, buffer,
567                                        memoryTypeIndexOut, deviceMemoryOut, sizeOut);
568 }
569 
AllocateImageMemory(Context * context,vk::MemoryAllocationType memoryAllocationType,VkMemoryPropertyFlags memoryPropertyFlags,VkMemoryPropertyFlags * memoryPropertyFlagsOut,const void * extraAllocationInfo,Image * image,uint32_t * memoryTypeIndexOut,DeviceMemory * deviceMemoryOut,VkDeviceSize * sizeOut)570 VkResult AllocateImageMemory(Context *context,
571                              vk::MemoryAllocationType memoryAllocationType,
572                              VkMemoryPropertyFlags memoryPropertyFlags,
573                              VkMemoryPropertyFlags *memoryPropertyFlagsOut,
574                              const void *extraAllocationInfo,
575                              Image *image,
576                              uint32_t *memoryTypeIndexOut,
577                              DeviceMemory *deviceMemoryOut,
578                              VkDeviceSize *sizeOut)
579 {
580     return AllocateBufferOrImageMemory(context, memoryAllocationType, memoryPropertyFlags,
581                                        memoryPropertyFlagsOut, extraAllocationInfo, image,
582                                        memoryTypeIndexOut, deviceMemoryOut, sizeOut);
583 }
584 
AllocateImageMemoryWithRequirements(Context * context,vk::MemoryAllocationType memoryAllocationType,VkMemoryPropertyFlags memoryPropertyFlags,const VkMemoryRequirements & memoryRequirements,const void * extraAllocationInfo,const VkBindImagePlaneMemoryInfoKHR * extraBindInfo,Image * image,uint32_t * memoryTypeIndexOut,DeviceMemory * deviceMemoryOut)585 VkResult AllocateImageMemoryWithRequirements(Context *context,
586                                              vk::MemoryAllocationType memoryAllocationType,
587                                              VkMemoryPropertyFlags memoryPropertyFlags,
588                                              const VkMemoryRequirements &memoryRequirements,
589                                              const void *extraAllocationInfo,
590                                              const VkBindImagePlaneMemoryInfoKHR *extraBindInfo,
591                                              Image *image,
592                                              uint32_t *memoryTypeIndexOut,
593                                              DeviceMemory *deviceMemoryOut)
594 {
595     VkMemoryPropertyFlags memoryPropertyFlagsOut = 0;
596     return AllocateAndBindBufferOrImageMemory(context, memoryAllocationType, memoryPropertyFlags,
597                                               &memoryPropertyFlagsOut, memoryRequirements,
598                                               extraAllocationInfo, extraBindInfo, image,
599                                               memoryTypeIndexOut, deviceMemoryOut);
600 }
601 
AllocateBufferMemoryWithRequirements(Context * context,MemoryAllocationType memoryAllocationType,VkMemoryPropertyFlags memoryPropertyFlags,const VkMemoryRequirements & memoryRequirements,const void * extraAllocationInfo,Buffer * buffer,VkMemoryPropertyFlags * memoryPropertyFlagsOut,uint32_t * memoryTypeIndexOut,DeviceMemory * deviceMemoryOut)602 VkResult AllocateBufferMemoryWithRequirements(Context *context,
603                                               MemoryAllocationType memoryAllocationType,
604                                               VkMemoryPropertyFlags memoryPropertyFlags,
605                                               const VkMemoryRequirements &memoryRequirements,
606                                               const void *extraAllocationInfo,
607                                               Buffer *buffer,
608                                               VkMemoryPropertyFlags *memoryPropertyFlagsOut,
609                                               uint32_t *memoryTypeIndexOut,
610                                               DeviceMemory *deviceMemoryOut)
611 {
612     return AllocateAndBindBufferOrImageMemory(context, memoryAllocationType, memoryPropertyFlags,
613                                               memoryPropertyFlagsOut, memoryRequirements,
614                                               extraAllocationInfo, nullptr, buffer,
615                                               memoryTypeIndexOut, deviceMemoryOut);
616 }
617 
InitShaderModule(Context * context,ShaderModule * shaderModule,const uint32_t * shaderCode,size_t shaderCodeSize)618 angle::Result InitShaderModule(Context *context,
619                                ShaderModule *shaderModule,
620                                const uint32_t *shaderCode,
621                                size_t shaderCodeSize)
622 {
623     VkShaderModuleCreateInfo createInfo = {};
624     createInfo.sType                    = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
625     createInfo.flags                    = 0;
626     createInfo.codeSize                 = shaderCodeSize;
627     createInfo.pCode                    = shaderCode;
628 
629     ANGLE_VK_TRY(context, shaderModule->init(context->getDevice(), createInfo));
630     return angle::Result::Continue;
631 }
632 
Get2DTextureType(uint32_t layerCount,GLint samples)633 gl::TextureType Get2DTextureType(uint32_t layerCount, GLint samples)
634 {
635     if (layerCount > 1)
636     {
637         if (samples > 1)
638         {
639             return gl::TextureType::_2DMultisampleArray;
640         }
641         else
642         {
643             return gl::TextureType::_2DArray;
644         }
645     }
646     else
647     {
648         if (samples > 1)
649         {
650             return gl::TextureType::_2DMultisample;
651         }
652         else
653         {
654             return gl::TextureType::_2D;
655         }
656     }
657 }
658 
GarbageObject()659 GarbageObject::GarbageObject() : mHandleType(HandleType::Invalid), mHandle(VK_NULL_HANDLE) {}
660 
GarbageObject(HandleType handleType,GarbageHandle handle)661 GarbageObject::GarbageObject(HandleType handleType, GarbageHandle handle)
662     : mHandleType(handleType), mHandle(handle)
663 {}
664 
GarbageObject(GarbageObject && other)665 GarbageObject::GarbageObject(GarbageObject &&other) : GarbageObject()
666 {
667     *this = std::move(other);
668 }
669 
operator =(GarbageObject && rhs)670 GarbageObject &GarbageObject::operator=(GarbageObject &&rhs)
671 {
672     std::swap(mHandle, rhs.mHandle);
673     std::swap(mHandleType, rhs.mHandleType);
674     return *this;
675 }
676 
677 // GarbageObject implementation
678 // Using c-style casts here to avoid conditional compile for MSVC 32-bit
679 //  which fails to compile with reinterpret_cast, requiring static_cast.
destroy(Renderer * renderer)680 void GarbageObject::destroy(Renderer *renderer)
681 {
682     ANGLE_TRACE_EVENT0("gpu.angle", "GarbageObject::destroy");
683     VkDevice device = renderer->getDevice();
684     switch (mHandleType)
685     {
686         case HandleType::Semaphore:
687             vkDestroySemaphore(device, (VkSemaphore)mHandle, nullptr);
688             break;
689         case HandleType::CommandBuffer:
690             // Command buffers are pool allocated.
691             UNREACHABLE();
692             break;
693         case HandleType::Event:
694             vkDestroyEvent(device, (VkEvent)mHandle, nullptr);
695             break;
696         case HandleType::Fence:
697             vkDestroyFence(device, (VkFence)mHandle, nullptr);
698             break;
699         case HandleType::DeviceMemory:
700             vkFreeMemory(device, (VkDeviceMemory)mHandle, nullptr);
701             break;
702         case HandleType::Buffer:
703             vkDestroyBuffer(device, (VkBuffer)mHandle, nullptr);
704             break;
705         case HandleType::BufferView:
706             vkDestroyBufferView(device, (VkBufferView)mHandle, nullptr);
707             break;
708         case HandleType::Image:
709             vkDestroyImage(device, (VkImage)mHandle, nullptr);
710             break;
711         case HandleType::ImageView:
712             vkDestroyImageView(device, (VkImageView)mHandle, nullptr);
713             break;
714         case HandleType::ShaderModule:
715             vkDestroyShaderModule(device, (VkShaderModule)mHandle, nullptr);
716             break;
717         case HandleType::PipelineLayout:
718             vkDestroyPipelineLayout(device, (VkPipelineLayout)mHandle, nullptr);
719             break;
720         case HandleType::RenderPass:
721             vkDestroyRenderPass(device, (VkRenderPass)mHandle, nullptr);
722             break;
723         case HandleType::Pipeline:
724             vkDestroyPipeline(device, (VkPipeline)mHandle, nullptr);
725             break;
726         case HandleType::DescriptorSetLayout:
727             vkDestroyDescriptorSetLayout(device, (VkDescriptorSetLayout)mHandle, nullptr);
728             break;
729         case HandleType::Sampler:
730             vkDestroySampler(device, (VkSampler)mHandle, nullptr);
731             break;
732         case HandleType::DescriptorPool:
733             vkDestroyDescriptorPool(device, (VkDescriptorPool)mHandle, nullptr);
734             break;
735         case HandleType::Framebuffer:
736             vkDestroyFramebuffer(device, (VkFramebuffer)mHandle, nullptr);
737             break;
738         case HandleType::CommandPool:
739             vkDestroyCommandPool(device, (VkCommandPool)mHandle, nullptr);
740             break;
741         case HandleType::QueryPool:
742             vkDestroyQueryPool(device, (VkQueryPool)mHandle, nullptr);
743             break;
744         case HandleType::Allocation:
745             vma::FreeMemory(renderer->getAllocator().getHandle(), (VmaAllocation)mHandle);
746             break;
747         default:
748             UNREACHABLE();
749             break;
750     }
751 
752     renderer->onDeallocateHandle(mHandleType);
753 }
754 
MakeDebugUtilsLabel(GLenum source,const char * marker,VkDebugUtilsLabelEXT * label)755 void MakeDebugUtilsLabel(GLenum source, const char *marker, VkDebugUtilsLabelEXT *label)
756 {
757     static constexpr angle::ColorF kLabelColors[6] = {
758         angle::ColorF(1.0f, 0.5f, 0.5f, 1.0f),  // DEBUG_SOURCE_API
759         angle::ColorF(0.5f, 1.0f, 0.5f, 1.0f),  // DEBUG_SOURCE_WINDOW_SYSTEM
760         angle::ColorF(0.5f, 0.5f, 1.0f, 1.0f),  // DEBUG_SOURCE_SHADER_COMPILER
761         angle::ColorF(0.7f, 0.7f, 0.7f, 1.0f),  // DEBUG_SOURCE_THIRD_PARTY
762         angle::ColorF(0.5f, 0.8f, 0.9f, 1.0f),  // DEBUG_SOURCE_APPLICATION
763         angle::ColorF(0.9f, 0.8f, 0.5f, 1.0f),  // DEBUG_SOURCE_OTHER
764     };
765 
766     int colorIndex = source - GL_DEBUG_SOURCE_API;
767     ASSERT(colorIndex >= 0 && static_cast<size_t>(colorIndex) < ArraySize(kLabelColors));
768 
769     label->sType      = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
770     label->pNext      = nullptr;
771     label->pLabelName = marker;
772     kLabelColors[colorIndex].writeData(label->color);
773 }
774 
SetDebugUtilsObjectName(ContextVk * contextVk,VkObjectType objectType,uint64_t handle,const std::string & label)775 angle::Result SetDebugUtilsObjectName(ContextVk *contextVk,
776                                       VkObjectType objectType,
777                                       uint64_t handle,
778                                       const std::string &label)
779 {
780     Renderer *renderer = contextVk->getRenderer();
781 
782     VkDebugUtilsObjectNameInfoEXT objectNameInfo = {};
783     objectNameInfo.sType        = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
784     objectNameInfo.objectType   = objectType;
785     objectNameInfo.objectHandle = handle;
786     objectNameInfo.pObjectName  = label.c_str();
787 
788     if (vkSetDebugUtilsObjectNameEXT)
789     {
790         ANGLE_VK_TRY(contextVk,
791                      vkSetDebugUtilsObjectNameEXT(renderer->getDevice(), &objectNameInfo));
792     }
793     return angle::Result::Continue;
794 }
795 
796 // ClearValuesArray implementation.
ClearValuesArray()797 ClearValuesArray::ClearValuesArray() : mValues{}, mEnabled{} {}
798 
799 ClearValuesArray::~ClearValuesArray() = default;
800 
801 ClearValuesArray::ClearValuesArray(const ClearValuesArray &other) = default;
802 
803 ClearValuesArray &ClearValuesArray::operator=(const ClearValuesArray &rhs) = default;
804 
store(uint32_t index,VkImageAspectFlags aspectFlags,const VkClearValue & clearValue)805 void ClearValuesArray::store(uint32_t index,
806                              VkImageAspectFlags aspectFlags,
807                              const VkClearValue &clearValue)
808 {
809     ASSERT(aspectFlags != 0);
810 
811     // We do this double if to handle the packed depth-stencil case.
812     if ((aspectFlags & VK_IMAGE_ASPECT_STENCIL_BIT) != 0)
813     {
814         // Ensure for packed DS we're writing to the depth index.
815         ASSERT(index == kUnpackedDepthIndex ||
816                (index == kUnpackedStencilIndex && aspectFlags == VK_IMAGE_ASPECT_STENCIL_BIT));
817 
818         storeNoDepthStencil(kUnpackedStencilIndex, clearValue);
819     }
820 
821     if (aspectFlags != VK_IMAGE_ASPECT_STENCIL_BIT)
822     {
823         storeNoDepthStencil(index, clearValue);
824     }
825 }
826 
storeNoDepthStencil(uint32_t index,const VkClearValue & clearValue)827 void ClearValuesArray::storeNoDepthStencil(uint32_t index, const VkClearValue &clearValue)
828 {
829     mValues[index] = clearValue;
830     mEnabled.set(index);
831 }
832 
getColorMask() const833 gl::DrawBufferMask ClearValuesArray::getColorMask() const
834 {
835     return gl::DrawBufferMask(mEnabled.bits() & kUnpackedColorBuffersMask);
836 }
837 
838 // ResourceSerialFactory implementation.
ResourceSerialFactory()839 ResourceSerialFactory::ResourceSerialFactory() : mCurrentUniqueSerial(1) {}
840 
~ResourceSerialFactory()841 ResourceSerialFactory::~ResourceSerialFactory() {}
842 
issueSerial()843 uint32_t ResourceSerialFactory::issueSerial()
844 {
845     uint32_t newSerial = ++mCurrentUniqueSerial;
846     // make sure serial does not wrap
847     ASSERT(newSerial > 0);
848     return newSerial;
849 }
850 
851 #define ANGLE_DEFINE_GEN_VK_SERIAL(Type)                         \
852     Type##Serial ResourceSerialFactory::generate##Type##Serial() \
853     {                                                            \
854         return Type##Serial(issueSerial());                      \
855     }
856 
ANGLE_VK_SERIAL_OP(ANGLE_DEFINE_GEN_VK_SERIAL)857 ANGLE_VK_SERIAL_OP(ANGLE_DEFINE_GEN_VK_SERIAL)
858 
859 void ClampViewport(VkViewport *viewport)
860 {
861     // 0-sized viewports are invalid in Vulkan.
862     ASSERT(viewport);
863     if (viewport->width == 0.0f)
864     {
865         viewport->width = 1.0f;
866     }
867     if (viewport->height == 0.0f)
868     {
869         viewport->height = 1.0f;
870     }
871 }
872 
ApplyPipelineCreationFeedback(Context * context,const VkPipelineCreationFeedback & feedback)873 void ApplyPipelineCreationFeedback(Context *context, const VkPipelineCreationFeedback &feedback)
874 {
875     const bool cacheHit =
876         (feedback.flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT) != 0;
877 
878     angle::VulkanPerfCounters &perfCounters = context->getPerfCounters();
879 
880     if (cacheHit)
881     {
882         ++perfCounters.pipelineCreationCacheHits;
883         perfCounters.pipelineCreationTotalCacheHitsDurationNs += feedback.duration;
884     }
885     else
886     {
887         ++perfCounters.pipelineCreationCacheMisses;
888         perfCounters.pipelineCreationTotalCacheMissesDurationNs += feedback.duration;
889     }
890 }
891 
hash() const892 size_t MemoryAllocInfoMapKey::hash() const
893 {
894     return angle::ComputeGenericHash(*this);
895 }
896 }  // namespace vk
897 
898 #if !defined(ANGLE_SHARED_LIBVULKAN)
899 // VK_EXT_debug_utils
900 PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT   = nullptr;
901 PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT = nullptr;
902 PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT       = nullptr;
903 PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT           = nullptr;
904 PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT     = nullptr;
905 PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT       = nullptr;
906 
907 // VK_KHR_get_physical_device_properties2
908 PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR             = nullptr;
909 PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR                 = nullptr;
910 PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR = nullptr;
911 
912 // VK_KHR_external_semaphore_fd
913 PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR = nullptr;
914 
915 // VK_EXT_host_query_reset
916 PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT = nullptr;
917 
918 // VK_EXT_transform_feedback
919 PFN_vkCmdBindTransformFeedbackBuffersEXT vkCmdBindTransformFeedbackBuffersEXT = nullptr;
920 PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT             = nullptr;
921 PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT                 = nullptr;
922 PFN_vkCmdBeginQueryIndexedEXT vkCmdBeginQueryIndexedEXT                       = nullptr;
923 PFN_vkCmdEndQueryIndexedEXT vkCmdEndQueryIndexedEXT                           = nullptr;
924 PFN_vkCmdDrawIndirectByteCountEXT vkCmdDrawIndirectByteCountEXT               = nullptr;
925 
926 // VK_KHR_get_memory_requirements2
927 PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR = nullptr;
928 PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR   = nullptr;
929 
930 // VK_KHR_bind_memory2
931 PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR = nullptr;
932 PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR   = nullptr;
933 
934 // VK_KHR_external_fence_capabilities
935 PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR vkGetPhysicalDeviceExternalFencePropertiesKHR =
936     nullptr;
937 
938 // VK_KHR_external_fence_fd
939 PFN_vkGetFenceFdKHR vkGetFenceFdKHR       = nullptr;
940 PFN_vkImportFenceFdKHR vkImportFenceFdKHR = nullptr;
941 
942 // VK_KHR_external_semaphore_capabilities
943 PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR
944     vkGetPhysicalDeviceExternalSemaphorePropertiesKHR = nullptr;
945 
946 // VK_KHR_sampler_ycbcr_conversion
947 PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR   = nullptr;
948 PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR = nullptr;
949 
950 // VK_KHR_create_renderpass2
951 PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR = nullptr;
952 
953 #    if defined(ANGLE_PLATFORM_FUCHSIA)
954 // VK_FUCHSIA_imagepipe_surface
955 PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA = nullptr;
956 #    endif
957 
958 #    if defined(ANGLE_PLATFORM_ANDROID)
959 PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID =
960     nullptr;
961 PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID = nullptr;
962 #    endif
963 
964 #    if defined(ANGLE_PLATFORM_GGP)
965 PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP = nullptr;
966 #    endif
967 
968 #    define GET_INSTANCE_FUNC(vkName)                                                          \
969         do                                                                                     \
970         {                                                                                      \
971             vkName = reinterpret_cast<PFN_##vkName>(vkGetInstanceProcAddr(instance, #vkName)); \
972             ASSERT(vkName);                                                                    \
973         } while (0)
974 
975 #    define GET_DEVICE_FUNC(vkName)                                                        \
976         do                                                                                 \
977         {                                                                                  \
978             vkName = reinterpret_cast<PFN_##vkName>(vkGetDeviceProcAddr(device, #vkName)); \
979             ASSERT(vkName);                                                                \
980         } while (0)
981 
982 // VK_KHR_shared_presentable_image
983 PFN_vkGetSwapchainStatusKHR vkGetSwapchainStatusKHR = nullptr;
984 
985 // VK_EXT_extended_dynamic_state
986 PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT             = nullptr;
987 PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT                           = nullptr;
988 PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT = nullptr;
989 PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT               = nullptr;
990 PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT             = nullptr;
991 PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT           = nullptr;
992 PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT                         = nullptr;
993 PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT         = nullptr;
994 PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT           = nullptr;
995 PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT                         = nullptr;
996 PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT         = nullptr;
997 PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT         = nullptr;
998 
999 // VK_EXT_extended_dynamic_state2
1000 PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT                 = nullptr;
1001 PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT                                 = nullptr;
1002 PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT           = nullptr;
1003 PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT   = nullptr;
1004 PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT = nullptr;
1005 
1006 // VK_EXT_vertex_input_dynamic_state
1007 PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT = nullptr;
1008 
1009 // VK_KHR_dynamic_rendering
1010 PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR = nullptr;
1011 PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR     = nullptr;
1012 
1013 // VK_KHR_dynamic_rendering_local_read
1014 PFN_vkCmdSetRenderingAttachmentLocationsKHR vkCmdSetRenderingAttachmentLocationsKHR       = nullptr;
1015 PFN_vkCmdSetRenderingInputAttachmentIndicesKHR vkCmdSetRenderingInputAttachmentIndicesKHR = nullptr;
1016 
1017 // VK_KHR_fragment_shading_rate
1018 PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR vkGetPhysicalDeviceFragmentShadingRatesKHR = nullptr;
1019 PFN_vkCmdSetFragmentShadingRateKHR vkCmdSetFragmentShadingRateKHR                         = nullptr;
1020 
1021 // VK_GOOGLE_display_timing
1022 PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE = nullptr;
1023 
1024 // VK_EXT_host_image_copy
1025 PFN_vkCopyImageToImageEXT vkCopyImageToImageEXT                     = nullptr;
1026 PFN_vkCopyImageToMemoryEXT vkCopyImageToMemoryEXT                   = nullptr;
1027 PFN_vkCopyMemoryToImageEXT vkCopyMemoryToImageEXT                   = nullptr;
1028 PFN_vkGetImageSubresourceLayout2EXT vkGetImageSubresourceLayout2EXT = nullptr;
1029 PFN_vkTransitionImageLayoutEXT vkTransitionImageLayoutEXT           = nullptr;
1030 
InitDebugUtilsEXTFunctions(VkInstance instance)1031 void InitDebugUtilsEXTFunctions(VkInstance instance)
1032 {
1033     GET_INSTANCE_FUNC(vkCreateDebugUtilsMessengerEXT);
1034     GET_INSTANCE_FUNC(vkDestroyDebugUtilsMessengerEXT);
1035     GET_INSTANCE_FUNC(vkCmdBeginDebugUtilsLabelEXT);
1036     GET_INSTANCE_FUNC(vkCmdEndDebugUtilsLabelEXT);
1037     GET_INSTANCE_FUNC(vkCmdInsertDebugUtilsLabelEXT);
1038     GET_INSTANCE_FUNC(vkSetDebugUtilsObjectNameEXT);
1039 }
1040 
InitTransformFeedbackEXTFunctions(VkDevice device)1041 void InitTransformFeedbackEXTFunctions(VkDevice device)
1042 {
1043     GET_DEVICE_FUNC(vkCmdBindTransformFeedbackBuffersEXT);
1044     GET_DEVICE_FUNC(vkCmdBeginTransformFeedbackEXT);
1045     GET_DEVICE_FUNC(vkCmdEndTransformFeedbackEXT);
1046     GET_DEVICE_FUNC(vkCmdBeginQueryIndexedEXT);
1047     GET_DEVICE_FUNC(vkCmdEndQueryIndexedEXT);
1048     GET_DEVICE_FUNC(vkCmdDrawIndirectByteCountEXT);
1049 }
1050 
1051 // VK_KHR_create_renderpass2
InitRenderPass2KHRFunctions(VkDevice device)1052 void InitRenderPass2KHRFunctions(VkDevice device)
1053 {
1054     GET_DEVICE_FUNC(vkCreateRenderPass2KHR);
1055 }
1056 
1057 #    if defined(ANGLE_PLATFORM_FUCHSIA)
InitImagePipeSurfaceFUCHSIAFunctions(VkInstance instance)1058 void InitImagePipeSurfaceFUCHSIAFunctions(VkInstance instance)
1059 {
1060     GET_INSTANCE_FUNC(vkCreateImagePipeSurfaceFUCHSIA);
1061 }
1062 #    endif
1063 
1064 #    if defined(ANGLE_PLATFORM_ANDROID)
InitExternalMemoryHardwareBufferANDROIDFunctions(VkInstance instance)1065 void InitExternalMemoryHardwareBufferANDROIDFunctions(VkInstance instance)
1066 {
1067     GET_INSTANCE_FUNC(vkGetAndroidHardwareBufferPropertiesANDROID);
1068     GET_INSTANCE_FUNC(vkGetMemoryAndroidHardwareBufferANDROID);
1069 }
1070 #    endif
1071 
1072 #    if defined(ANGLE_PLATFORM_GGP)
InitGGPStreamDescriptorSurfaceFunctions(VkInstance instance)1073 void InitGGPStreamDescriptorSurfaceFunctions(VkInstance instance)
1074 {
1075     GET_INSTANCE_FUNC(vkCreateStreamDescriptorSurfaceGGP);
1076 }
1077 #    endif  // defined(ANGLE_PLATFORM_GGP)
1078 
InitExternalSemaphoreFdFunctions(VkInstance instance)1079 void InitExternalSemaphoreFdFunctions(VkInstance instance)
1080 {
1081     GET_INSTANCE_FUNC(vkImportSemaphoreFdKHR);
1082 }
1083 
InitHostQueryResetFunctions(VkDevice device)1084 void InitHostQueryResetFunctions(VkDevice device)
1085 {
1086     GET_DEVICE_FUNC(vkResetQueryPoolEXT);
1087 }
1088 
1089 // VK_KHR_external_fence_fd
InitExternalFenceFdFunctions(VkInstance instance)1090 void InitExternalFenceFdFunctions(VkInstance instance)
1091 {
1092     GET_INSTANCE_FUNC(vkGetFenceFdKHR);
1093     GET_INSTANCE_FUNC(vkImportFenceFdKHR);
1094 }
1095 
1096 // VK_KHR_shared_presentable_image
InitGetSwapchainStatusKHRFunctions(VkDevice device)1097 void InitGetSwapchainStatusKHRFunctions(VkDevice device)
1098 {
1099     GET_DEVICE_FUNC(vkGetSwapchainStatusKHR);
1100 }
1101 
1102 // VK_EXT_extended_dynamic_state
InitExtendedDynamicStateEXTFunctions(VkDevice device)1103 void InitExtendedDynamicStateEXTFunctions(VkDevice device)
1104 {
1105     GET_DEVICE_FUNC(vkCmdBindVertexBuffers2EXT);
1106     GET_DEVICE_FUNC(vkCmdSetCullModeEXT);
1107     GET_DEVICE_FUNC(vkCmdSetDepthBoundsTestEnableEXT);
1108     GET_DEVICE_FUNC(vkCmdSetDepthCompareOpEXT);
1109     GET_DEVICE_FUNC(vkCmdSetDepthTestEnableEXT);
1110     GET_DEVICE_FUNC(vkCmdSetDepthWriteEnableEXT);
1111     GET_DEVICE_FUNC(vkCmdSetFrontFaceEXT);
1112     GET_DEVICE_FUNC(vkCmdSetPrimitiveTopologyEXT);
1113     GET_DEVICE_FUNC(vkCmdSetScissorWithCountEXT);
1114     GET_DEVICE_FUNC(vkCmdSetStencilOpEXT);
1115     GET_DEVICE_FUNC(vkCmdSetStencilTestEnableEXT);
1116     GET_DEVICE_FUNC(vkCmdSetViewportWithCountEXT);
1117 }
1118 
1119 // VK_EXT_extended_dynamic_state2
InitExtendedDynamicState2EXTFunctions(VkDevice device)1120 void InitExtendedDynamicState2EXTFunctions(VkDevice device)
1121 {
1122     GET_DEVICE_FUNC(vkCmdSetDepthBiasEnableEXT);
1123     GET_DEVICE_FUNC(vkCmdSetLogicOpEXT);
1124     GET_DEVICE_FUNC(vkCmdSetPatchControlPointsEXT);
1125     GET_DEVICE_FUNC(vkCmdSetPrimitiveRestartEnableEXT);
1126     GET_DEVICE_FUNC(vkCmdSetRasterizerDiscardEnableEXT);
1127 }
1128 
1129 // VK_EXT_vertex_input_dynamic_state
InitVertexInputDynamicStateEXTFunctions(VkDevice device)1130 void InitVertexInputDynamicStateEXTFunctions(VkDevice device)
1131 {
1132     GET_DEVICE_FUNC(vkCmdSetVertexInputEXT);
1133 }
1134 
1135 // VK_KHR_dynamic_rendering
InitDynamicRenderingFunctions(VkDevice device)1136 void InitDynamicRenderingFunctions(VkDevice device)
1137 {
1138     GET_DEVICE_FUNC(vkCmdBeginRenderingKHR);
1139     GET_DEVICE_FUNC(vkCmdEndRenderingKHR);
1140 }
1141 
1142 // VK_KHR_dynamic_rendering_local_read
InitDynamicRenderingLocalReadFunctions(VkDevice device)1143 void InitDynamicRenderingLocalReadFunctions(VkDevice device)
1144 {
1145     GET_DEVICE_FUNC(vkCmdSetRenderingAttachmentLocationsKHR);
1146     GET_DEVICE_FUNC(vkCmdSetRenderingInputAttachmentIndicesKHR);
1147 }
1148 
1149 // VK_KHR_fragment_shading_rate
InitFragmentShadingRateKHRInstanceFunction(VkInstance instance)1150 void InitFragmentShadingRateKHRInstanceFunction(VkInstance instance)
1151 {
1152     GET_INSTANCE_FUNC(vkGetPhysicalDeviceFragmentShadingRatesKHR);
1153 }
1154 
InitFragmentShadingRateKHRDeviceFunction(VkDevice device)1155 void InitFragmentShadingRateKHRDeviceFunction(VkDevice device)
1156 {
1157     GET_DEVICE_FUNC(vkCmdSetFragmentShadingRateKHR);
1158 }
1159 
1160 // VK_GOOGLE_display_timing
InitGetPastPresentationTimingGoogleFunction(VkDevice device)1161 void InitGetPastPresentationTimingGoogleFunction(VkDevice device)
1162 {
1163     GET_DEVICE_FUNC(vkGetPastPresentationTimingGOOGLE);
1164 }
1165 
1166 // VK_EXT_host_image_copy
InitHostImageCopyFunctions(VkDevice device)1167 void InitHostImageCopyFunctions(VkDevice device)
1168 {
1169     GET_DEVICE_FUNC(vkCopyImageToImageEXT);
1170     GET_DEVICE_FUNC(vkCopyImageToMemoryEXT);
1171     GET_DEVICE_FUNC(vkCopyMemoryToImageEXT);
1172     GET_DEVICE_FUNC(vkGetImageSubresourceLayout2EXT);
1173     GET_DEVICE_FUNC(vkTransitionImageLayoutEXT);
1174 }
1175 
1176 #    undef GET_INSTANCE_FUNC
1177 #    undef GET_DEVICE_FUNC
1178 
1179 #endif  // !defined(ANGLE_SHARED_LIBVULKAN)
1180 
1181 #define ASSIGN_FROM_CORE(vkName, EXT)              \
1182     do                                             \
1183     {                                              \
1184         /* The core entry point must be present */ \
1185         ASSERT(vkName != nullptr);                 \
1186         vkName##EXT = vkName;                      \
1187     } while (0)
1188 
InitGetPhysicalDeviceProperties2KHRFunctionsFromCore()1189 void InitGetPhysicalDeviceProperties2KHRFunctionsFromCore()
1190 {
1191     ASSIGN_FROM_CORE(vkGetPhysicalDeviceProperties2, KHR);
1192     ASSIGN_FROM_CORE(vkGetPhysicalDeviceFeatures2, KHR);
1193     ASSIGN_FROM_CORE(vkGetPhysicalDeviceMemoryProperties2, KHR);
1194 }
1195 
InitExternalFenceCapabilitiesFunctionsFromCore()1196 void InitExternalFenceCapabilitiesFunctionsFromCore()
1197 {
1198     ASSIGN_FROM_CORE(vkGetPhysicalDeviceExternalFenceProperties, KHR);
1199 }
1200 
InitExternalSemaphoreCapabilitiesFunctionsFromCore()1201 void InitExternalSemaphoreCapabilitiesFunctionsFromCore()
1202 {
1203     ASSIGN_FROM_CORE(vkGetPhysicalDeviceExternalSemaphoreProperties, KHR);
1204 }
1205 
InitSamplerYcbcrKHRFunctionsFromCore()1206 void InitSamplerYcbcrKHRFunctionsFromCore()
1207 {
1208     ASSIGN_FROM_CORE(vkCreateSamplerYcbcrConversion, KHR);
1209     ASSIGN_FROM_CORE(vkDestroySamplerYcbcrConversion, KHR);
1210 }
1211 
InitGetMemoryRequirements2KHRFunctionsFromCore()1212 void InitGetMemoryRequirements2KHRFunctionsFromCore()
1213 {
1214     ASSIGN_FROM_CORE(vkGetBufferMemoryRequirements2, KHR);
1215     ASSIGN_FROM_CORE(vkGetImageMemoryRequirements2, KHR);
1216 }
1217 
InitBindMemory2KHRFunctionsFromCore()1218 void InitBindMemory2KHRFunctionsFromCore()
1219 {
1220     ASSIGN_FROM_CORE(vkBindBufferMemory2, KHR);
1221     ASSIGN_FROM_CORE(vkBindImageMemory2, KHR);
1222 }
1223 
1224 #undef ASSIGN_FROM_CORE
1225 
CalculateGenerateMipmapFilter(ContextVk * contextVk,angle::FormatID formatID)1226 GLenum CalculateGenerateMipmapFilter(ContextVk *contextVk, angle::FormatID formatID)
1227 {
1228     const bool formatSupportsLinearFiltering = contextVk->getRenderer()->hasImageFormatFeatureBits(
1229         formatID, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT);
1230     const bool hintFastest = contextVk->getState().getGenerateMipmapHint() == GL_FASTEST;
1231 
1232     return formatSupportsLinearFiltering && !hintFastest ? GL_LINEAR : GL_NEAREST;
1233 }
1234 
1235 // Return the log of samples.  Assumes |sampleCount| is a power of 2.  The result can be used to
1236 // index an array based on sample count.  See for example TextureVk::PerSampleCountArray.
PackSampleCount(GLint sampleCount)1237 size_t PackSampleCount(GLint sampleCount)
1238 {
1239     if (sampleCount == 0)
1240     {
1241         sampleCount = 1;
1242     }
1243 
1244     // We currently only support up to 16xMSAA.
1245     ASSERT(sampleCount <= VK_SAMPLE_COUNT_16_BIT);
1246     ASSERT(gl::isPow2(sampleCount));
1247     return gl::ScanForward(static_cast<uint32_t>(sampleCount));
1248 }
1249 
1250 namespace gl_vk
1251 {
1252 
GetFilter(const GLenum filter)1253 VkFilter GetFilter(const GLenum filter)
1254 {
1255     switch (filter)
1256     {
1257         case GL_LINEAR_MIPMAP_LINEAR:
1258         case GL_LINEAR_MIPMAP_NEAREST:
1259         case GL_LINEAR:
1260             return VK_FILTER_LINEAR;
1261         case GL_NEAREST_MIPMAP_LINEAR:
1262         case GL_NEAREST_MIPMAP_NEAREST:
1263         case GL_NEAREST:
1264             return VK_FILTER_NEAREST;
1265         default:
1266             UNIMPLEMENTED();
1267             return VK_FILTER_MAX_ENUM;
1268     }
1269 }
1270 
GetSamplerMipmapMode(const GLenum filter)1271 VkSamplerMipmapMode GetSamplerMipmapMode(const GLenum filter)
1272 {
1273     switch (filter)
1274     {
1275         case GL_LINEAR_MIPMAP_LINEAR:
1276         case GL_NEAREST_MIPMAP_LINEAR:
1277             return VK_SAMPLER_MIPMAP_MODE_LINEAR;
1278         case GL_LINEAR:
1279         case GL_NEAREST:
1280         case GL_NEAREST_MIPMAP_NEAREST:
1281         case GL_LINEAR_MIPMAP_NEAREST:
1282             return VK_SAMPLER_MIPMAP_MODE_NEAREST;
1283         default:
1284             UNIMPLEMENTED();
1285             return VK_SAMPLER_MIPMAP_MODE_MAX_ENUM;
1286     }
1287 }
1288 
GetSamplerAddressMode(const GLenum wrap)1289 VkSamplerAddressMode GetSamplerAddressMode(const GLenum wrap)
1290 {
1291     switch (wrap)
1292     {
1293         case GL_REPEAT:
1294             return VK_SAMPLER_ADDRESS_MODE_REPEAT;
1295         case GL_MIRRORED_REPEAT:
1296             return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
1297         case GL_CLAMP_TO_BORDER:
1298             return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
1299         case GL_CLAMP_TO_EDGE:
1300             return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
1301         case GL_MIRROR_CLAMP_TO_EDGE_EXT:
1302             return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
1303         default:
1304             UNIMPLEMENTED();
1305             return VK_SAMPLER_ADDRESS_MODE_MAX_ENUM;
1306     }
1307 }
1308 
GetRect(const gl::Rectangle & source)1309 VkRect2D GetRect(const gl::Rectangle &source)
1310 {
1311     return {{source.x, source.y},
1312             {static_cast<uint32_t>(source.width), static_cast<uint32_t>(source.height)}};
1313 }
1314 
GetPrimitiveTopology(gl::PrimitiveMode mode)1315 VkPrimitiveTopology GetPrimitiveTopology(gl::PrimitiveMode mode)
1316 {
1317     switch (mode)
1318     {
1319         case gl::PrimitiveMode::Triangles:
1320             return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1321         case gl::PrimitiveMode::Points:
1322             return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
1323         case gl::PrimitiveMode::Lines:
1324             return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
1325         case gl::PrimitiveMode::LineStrip:
1326             return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
1327         case gl::PrimitiveMode::TriangleFan:
1328             return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
1329         case gl::PrimitiveMode::TriangleStrip:
1330             return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1331         case gl::PrimitiveMode::LineLoop:
1332             return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
1333         case gl::PrimitiveMode::LinesAdjacency:
1334             return VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY;
1335         case gl::PrimitiveMode::LineStripAdjacency:
1336             return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY;
1337         case gl::PrimitiveMode::TrianglesAdjacency:
1338             return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY;
1339         case gl::PrimitiveMode::TriangleStripAdjacency:
1340             return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY;
1341         case gl::PrimitiveMode::Patches:
1342             return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
1343         default:
1344             UNREACHABLE();
1345             return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
1346     }
1347 }
1348 
GetPolygonMode(const gl::PolygonMode polygonMode)1349 VkPolygonMode GetPolygonMode(const gl::PolygonMode polygonMode)
1350 {
1351     switch (polygonMode)
1352     {
1353         case gl::PolygonMode::Point:
1354             return VK_POLYGON_MODE_POINT;
1355         case gl::PolygonMode::Line:
1356             return VK_POLYGON_MODE_LINE;
1357         case gl::PolygonMode::Fill:
1358             return VK_POLYGON_MODE_FILL;
1359         default:
1360             UNREACHABLE();
1361             return VK_POLYGON_MODE_FILL;
1362     }
1363 }
1364 
GetCullMode(const gl::RasterizerState & rasterState)1365 VkCullModeFlagBits GetCullMode(const gl::RasterizerState &rasterState)
1366 {
1367     if (!rasterState.cullFace)
1368     {
1369         return VK_CULL_MODE_NONE;
1370     }
1371 
1372     switch (rasterState.cullMode)
1373     {
1374         case gl::CullFaceMode::Front:
1375             return VK_CULL_MODE_FRONT_BIT;
1376         case gl::CullFaceMode::Back:
1377             return VK_CULL_MODE_BACK_BIT;
1378         case gl::CullFaceMode::FrontAndBack:
1379             return VK_CULL_MODE_FRONT_AND_BACK;
1380         default:
1381             UNREACHABLE();
1382             return VK_CULL_MODE_NONE;
1383     }
1384 }
1385 
GetFrontFace(GLenum frontFace,bool invertCullFace)1386 VkFrontFace GetFrontFace(GLenum frontFace, bool invertCullFace)
1387 {
1388     // Invert CW and CCW to have the same behavior as OpenGL.
1389     switch (frontFace)
1390     {
1391         case GL_CW:
1392             return invertCullFace ? VK_FRONT_FACE_CLOCKWISE : VK_FRONT_FACE_COUNTER_CLOCKWISE;
1393         case GL_CCW:
1394             return invertCullFace ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE;
1395         default:
1396             UNREACHABLE();
1397             return VK_FRONT_FACE_CLOCKWISE;
1398     }
1399 }
1400 
GetSamples(GLint sampleCount,bool limitSampleCountTo2)1401 VkSampleCountFlagBits GetSamples(GLint sampleCount, bool limitSampleCountTo2)
1402 {
1403     if (limitSampleCountTo2)
1404     {
1405         // Limiting samples to 2 allows multisampling to work while reducing
1406         // how much graphics memory is required.  This makes ANGLE nonconformant
1407         // (GLES 3.0+ requires 4 samples minimum) but gives low memory systems a
1408         // better chance of running applications.
1409         sampleCount = std::min(sampleCount, 2);
1410     }
1411 
1412     switch (sampleCount)
1413     {
1414         case 0:
1415             UNREACHABLE();
1416             return VK_SAMPLE_COUNT_1_BIT;
1417         case 1:
1418             return VK_SAMPLE_COUNT_1_BIT;
1419         case 2:
1420             return VK_SAMPLE_COUNT_2_BIT;
1421         case 4:
1422             return VK_SAMPLE_COUNT_4_BIT;
1423         case 8:
1424             return VK_SAMPLE_COUNT_8_BIT;
1425         case 16:
1426             return VK_SAMPLE_COUNT_16_BIT;
1427         case 32:
1428             return VK_SAMPLE_COUNT_32_BIT;
1429         default:
1430             UNREACHABLE();
1431             return VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM;
1432     }
1433 }
1434 
GetSwizzle(const GLenum swizzle)1435 VkComponentSwizzle GetSwizzle(const GLenum swizzle)
1436 {
1437     switch (swizzle)
1438     {
1439         case GL_ALPHA:
1440             return VK_COMPONENT_SWIZZLE_A;
1441         case GL_RED:
1442             return VK_COMPONENT_SWIZZLE_R;
1443         case GL_GREEN:
1444             return VK_COMPONENT_SWIZZLE_G;
1445         case GL_BLUE:
1446             return VK_COMPONENT_SWIZZLE_B;
1447         case GL_ZERO:
1448             return VK_COMPONENT_SWIZZLE_ZERO;
1449         case GL_ONE:
1450             return VK_COMPONENT_SWIZZLE_ONE;
1451         default:
1452             UNREACHABLE();
1453             return VK_COMPONENT_SWIZZLE_IDENTITY;
1454     }
1455 }
1456 
GetCompareOp(const GLenum compareFunc)1457 VkCompareOp GetCompareOp(const GLenum compareFunc)
1458 {
1459     switch (compareFunc)
1460     {
1461         case GL_NEVER:
1462             return VK_COMPARE_OP_NEVER;
1463         case GL_LESS:
1464             return VK_COMPARE_OP_LESS;
1465         case GL_EQUAL:
1466             return VK_COMPARE_OP_EQUAL;
1467         case GL_LEQUAL:
1468             return VK_COMPARE_OP_LESS_OR_EQUAL;
1469         case GL_GREATER:
1470             return VK_COMPARE_OP_GREATER;
1471         case GL_NOTEQUAL:
1472             return VK_COMPARE_OP_NOT_EQUAL;
1473         case GL_GEQUAL:
1474             return VK_COMPARE_OP_GREATER_OR_EQUAL;
1475         case GL_ALWAYS:
1476             return VK_COMPARE_OP_ALWAYS;
1477         default:
1478             UNREACHABLE();
1479             return VK_COMPARE_OP_ALWAYS;
1480     }
1481 }
1482 
GetStencilOp(GLenum compareOp)1483 VkStencilOp GetStencilOp(GLenum compareOp)
1484 {
1485     switch (compareOp)
1486     {
1487         case GL_KEEP:
1488             return VK_STENCIL_OP_KEEP;
1489         case GL_ZERO:
1490             return VK_STENCIL_OP_ZERO;
1491         case GL_REPLACE:
1492             return VK_STENCIL_OP_REPLACE;
1493         case GL_INCR:
1494             return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
1495         case GL_DECR:
1496             return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
1497         case GL_INCR_WRAP:
1498             return VK_STENCIL_OP_INCREMENT_AND_WRAP;
1499         case GL_DECR_WRAP:
1500             return VK_STENCIL_OP_DECREMENT_AND_WRAP;
1501         case GL_INVERT:
1502             return VK_STENCIL_OP_INVERT;
1503         default:
1504             UNREACHABLE();
1505             return VK_STENCIL_OP_KEEP;
1506     }
1507 }
1508 
GetLogicOp(const GLenum logicOp)1509 VkLogicOp GetLogicOp(const GLenum logicOp)
1510 {
1511     // GL's logic op values are 0x1500 + op, where op is the same value as Vulkan's VkLogicOp.
1512     return static_cast<VkLogicOp>(logicOp - GL_CLEAR);
1513 }
1514 
GetOffset(const gl::Offset & glOffset,VkOffset3D * vkOffset)1515 void GetOffset(const gl::Offset &glOffset, VkOffset3D *vkOffset)
1516 {
1517     vkOffset->x = glOffset.x;
1518     vkOffset->y = glOffset.y;
1519     vkOffset->z = glOffset.z;
1520 }
1521 
GetExtent(const gl::Extents & glExtent,VkExtent3D * vkExtent)1522 void GetExtent(const gl::Extents &glExtent, VkExtent3D *vkExtent)
1523 {
1524     vkExtent->width  = glExtent.width;
1525     vkExtent->height = glExtent.height;
1526     vkExtent->depth  = glExtent.depth;
1527 }
1528 
GetImageType(gl::TextureType textureType)1529 VkImageType GetImageType(gl::TextureType textureType)
1530 {
1531     switch (textureType)
1532     {
1533         case gl::TextureType::_2D:
1534         case gl::TextureType::_2DArray:
1535         case gl::TextureType::_2DMultisample:
1536         case gl::TextureType::_2DMultisampleArray:
1537         case gl::TextureType::CubeMap:
1538         case gl::TextureType::CubeMapArray:
1539         case gl::TextureType::External:
1540             return VK_IMAGE_TYPE_2D;
1541         case gl::TextureType::_3D:
1542             return VK_IMAGE_TYPE_3D;
1543         default:
1544             // We will need to implement all the texture types for ES3+.
1545             UNIMPLEMENTED();
1546             return VK_IMAGE_TYPE_MAX_ENUM;
1547     }
1548 }
1549 
GetImageViewType(gl::TextureType textureType)1550 VkImageViewType GetImageViewType(gl::TextureType textureType)
1551 {
1552     switch (textureType)
1553     {
1554         case gl::TextureType::_2D:
1555         case gl::TextureType::_2DMultisample:
1556         case gl::TextureType::External:
1557             return VK_IMAGE_VIEW_TYPE_2D;
1558         case gl::TextureType::_2DArray:
1559         case gl::TextureType::_2DMultisampleArray:
1560             return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
1561         case gl::TextureType::_3D:
1562             return VK_IMAGE_VIEW_TYPE_3D;
1563         case gl::TextureType::CubeMap:
1564             return VK_IMAGE_VIEW_TYPE_CUBE;
1565         case gl::TextureType::CubeMapArray:
1566             return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
1567         default:
1568             // We will need to implement all the texture types for ES3+.
1569             UNIMPLEMENTED();
1570             return VK_IMAGE_VIEW_TYPE_MAX_ENUM;
1571     }
1572 }
1573 
GetColorComponentFlags(bool red,bool green,bool blue,bool alpha)1574 VkColorComponentFlags GetColorComponentFlags(bool red, bool green, bool blue, bool alpha)
1575 {
1576     return (red ? VK_COLOR_COMPONENT_R_BIT : 0) | (green ? VK_COLOR_COMPONENT_G_BIT : 0) |
1577            (blue ? VK_COLOR_COMPONENT_B_BIT : 0) | (alpha ? VK_COLOR_COMPONENT_A_BIT : 0);
1578 }
1579 
GetShaderStageFlags(gl::ShaderBitSet activeShaders)1580 VkShaderStageFlags GetShaderStageFlags(gl::ShaderBitSet activeShaders)
1581 {
1582     VkShaderStageFlags flags = 0;
1583     for (const gl::ShaderType shaderType : activeShaders)
1584     {
1585         flags |= kShaderStageMap[shaderType];
1586     }
1587     return flags;
1588 }
1589 
GetViewport(const gl::Rectangle & viewport,float nearPlane,float farPlane,bool invertViewport,bool clipSpaceOriginUpperLeft,GLint renderAreaHeight,VkViewport * viewportOut)1590 void GetViewport(const gl::Rectangle &viewport,
1591                  float nearPlane,
1592                  float farPlane,
1593                  bool invertViewport,
1594                  bool clipSpaceOriginUpperLeft,
1595                  GLint renderAreaHeight,
1596                  VkViewport *viewportOut)
1597 {
1598     viewportOut->x        = static_cast<float>(viewport.x);
1599     viewportOut->y        = static_cast<float>(viewport.y);
1600     viewportOut->width    = static_cast<float>(viewport.width);
1601     viewportOut->height   = static_cast<float>(viewport.height);
1602     viewportOut->minDepth = gl::clamp01(nearPlane);
1603     viewportOut->maxDepth = gl::clamp01(farPlane);
1604 
1605     // Say an application intends to draw a primitive (shown as 'o' below), it can choose to use
1606     // different clip space origin. When clip space origin (shown as 'C' below) is switched from
1607     // lower-left to upper-left, primitives will be rendered with its y-coordinate flipped.
1608 
1609     // Rendered content will differ based on whether it is a default framebuffer or a user defined
1610     // framebuffer. We modify the viewport's 'y' and 'h' accordingly.
1611 
1612     // clip space origin is lower-left
1613     // Expected draw in GLES        default framebuffer    user defined framebuffer
1614     // (0,H)                        (0,0)                  (0,0)
1615     // +                            +-----------+  (W,0)   +-----------+ (W,0)
1616     // |                            |                      |  C----+
1617     // |                            |                      |  |    | (h)
1618     // |  +----+                    |  +----+              |  | O  |
1619     // |  | O  |                    |  | O  | (-h)         |  +----+
1620     // |  |    |                    |  |    |              |
1621     // |  C----+                    |  C----+              |
1622     // +-----------+ (W,0)          +                      +
1623     // (0,0)                        (0,H)                  (0,H)
1624     //                              y' = H - h             y' = y
1625 
1626     // clip space origin is upper-left
1627     // Expected draw in GLES        default framebuffer     user defined framebuffer
1628     // (0,H)                        (0,0)                  (0,0)
1629     // +                            +-----------+  (W,0)   +-----------+ (W,0)
1630     // |                            |                      |  +----+
1631     // |                            |                      |  | O  | (-h)
1632     // |  C----+                    |  C----+              |  |    |
1633     // |  |    |                    |  |    | (h)          |  C----+
1634     // |  | O  |                    |  | O  |              |
1635     // |  +----+                    |  +----+              |
1636     // +-----------+  (W,0)         +                      +
1637     // (0,0)                        (0,H)                  (0,H)
1638     //                              y' = H - (y + h)       y' = y + H
1639 
1640     if (clipSpaceOriginUpperLeft)
1641     {
1642         if (invertViewport)
1643         {
1644             viewportOut->y = static_cast<float>(renderAreaHeight - (viewport.height + viewport.y));
1645         }
1646         else
1647         {
1648             viewportOut->y      = static_cast<float>(viewport.height + viewport.y);
1649             viewportOut->height = -viewportOut->height;
1650         }
1651     }
1652     else
1653     {
1654         if (invertViewport)
1655         {
1656             viewportOut->y      = static_cast<float>(renderAreaHeight - viewport.y);
1657             viewportOut->height = -viewportOut->height;
1658         }
1659     }
1660 }
1661 
GetExtentsAndLayerCount(gl::TextureType textureType,const gl::Extents & extents,VkExtent3D * extentsOut,uint32_t * layerCountOut)1662 void GetExtentsAndLayerCount(gl::TextureType textureType,
1663                              const gl::Extents &extents,
1664                              VkExtent3D *extentsOut,
1665                              uint32_t *layerCountOut)
1666 {
1667     extentsOut->width  = extents.width;
1668     extentsOut->height = extents.height;
1669 
1670     switch (textureType)
1671     {
1672         case gl::TextureType::CubeMap:
1673             extentsOut->depth = 1;
1674             *layerCountOut    = gl::kCubeFaceCount;
1675             break;
1676 
1677         case gl::TextureType::_2DArray:
1678         case gl::TextureType::_2DMultisampleArray:
1679         case gl::TextureType::CubeMapArray:
1680             extentsOut->depth = 1;
1681             *layerCountOut    = extents.depth;
1682             break;
1683 
1684         default:
1685             extentsOut->depth = extents.depth;
1686             *layerCountOut    = 1;
1687             break;
1688     }
1689 }
1690 
GetLevelIndex(gl::LevelIndex levelGL,gl::LevelIndex baseLevel)1691 vk::LevelIndex GetLevelIndex(gl::LevelIndex levelGL, gl::LevelIndex baseLevel)
1692 {
1693     ASSERT(baseLevel <= levelGL);
1694     return vk::LevelIndex(levelGL.get() - baseLevel.get());
1695 }
1696 
GetTilingMode(gl::TilingMode tilingMode)1697 VkImageTiling GetTilingMode(gl::TilingMode tilingMode)
1698 {
1699     switch (tilingMode)
1700     {
1701         case gl::TilingMode::Optimal:
1702             return VK_IMAGE_TILING_OPTIMAL;
1703         case gl::TilingMode::Linear:
1704             return VK_IMAGE_TILING_LINEAR;
1705         default:
1706             UNREACHABLE();
1707             return VK_IMAGE_TILING_OPTIMAL;
1708     }
1709 }
1710 
1711 }  // namespace gl_vk
1712 
1713 namespace vk_gl
1714 {
AddSampleCounts(VkSampleCountFlags sampleCounts,gl::SupportedSampleSet * setOut)1715 void AddSampleCounts(VkSampleCountFlags sampleCounts, gl::SupportedSampleSet *setOut)
1716 {
1717     // The possible bits are VK_SAMPLE_COUNT_n_BIT = n, with n = 1 << b.  At the time of this
1718     // writing, b is in [0, 6], however, we test all 32 bits in case the enum is extended.
1719     for (size_t bit : angle::BitSet32<32>(sampleCounts & kSupportedSampleCounts))
1720     {
1721         setOut->insert(static_cast<GLuint>(1 << bit));
1722     }
1723 }
1724 
GetMaxSampleCount(VkSampleCountFlags sampleCounts)1725 GLuint GetMaxSampleCount(VkSampleCountFlags sampleCounts)
1726 {
1727     GLuint maxCount = 0;
1728     for (size_t bit : angle::BitSet32<32>(sampleCounts & kSupportedSampleCounts))
1729     {
1730         maxCount = static_cast<GLuint>(1 << bit);
1731     }
1732     return maxCount;
1733 }
1734 
GetSampleCount(VkSampleCountFlags supportedCounts,GLuint requestedCount)1735 GLuint GetSampleCount(VkSampleCountFlags supportedCounts, GLuint requestedCount)
1736 {
1737     for (size_t bit : angle::BitSet32<32>(supportedCounts & kSupportedSampleCounts))
1738     {
1739         GLuint sampleCount = static_cast<GLuint>(1 << bit);
1740         if (sampleCount >= requestedCount)
1741         {
1742             return sampleCount;
1743         }
1744     }
1745 
1746     UNREACHABLE();
1747     return 0;
1748 }
1749 
GetLevelIndex(vk::LevelIndex levelVk,gl::LevelIndex baseLevel)1750 gl::LevelIndex GetLevelIndex(vk::LevelIndex levelVk, gl::LevelIndex baseLevel)
1751 {
1752     return gl::LevelIndex(levelVk.get() + baseLevel.get());
1753 }
1754 }  // namespace vk_gl
1755 }  // namespace rx
1756