1 /*
2  * Copyright (c) 2015-2019 The Khronos Group Inc.
3  * Copyright (c) 2015-2019 Valve Corporation
4  * Copyright (c) 2015-2019 LunarG, Inc.
5  * Copyright (c) 2015-2019 Google, Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Author: Chia-I Wu <olvaffe@gmail.com>
14  * Author: Chris Forbes <chrisf@ijw.co.nz>
15  * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
16  * Author: Mark Lobodzinski <mark@lunarg.com>
17  * Author: Mike Stroyan <mike@LunarG.com>
18  * Author: Tobin Ehlis <tobine@google.com>
19  * Author: Tony Barbour <tony@LunarG.com>
20  * Author: Cody Northrop <cnorthrop@google.com>
21  * Author: Dave Houlton <daveh@lunarg.com>
22  * Author: Jeremy Kniager <jeremyk@lunarg.com>
23  * Author: Shannon McPherson <shannon@lunarg.com>
24  * Author: John Zulauf <jzulauf@lunarg.com>
25  */
26 
27 #ifndef VKLAYERTEST_H
28 #define VKLAYERTEST_H
29 
30 #ifdef ANDROID
31 #include "vulkan_wrapper.h"
32 #else
33 #define NOMINMAX
34 #include <vulkan/vulkan.h>
35 #endif
36 
37 #include "layers/vk_device_profile_api_layer.h"
38 
39 #if defined(ANDROID)
40 #include <android/log.h>
41 #if defined(VALIDATION_APK)
42 #include <android_native_app_glue.h>
43 #endif
44 #endif
45 
46 #include "icd-spv.h"
47 #include "test_common.h"
48 #include "vk_layer_config.h"
49 #include "vk_format_utils.h"
50 #include "vkrenderframework.h"
51 #include "vk_typemap_helper.h"
52 #include "convert_to_renderpass2.h"
53 
54 #include <algorithm>
55 #include <cmath>
56 #include <functional>
57 #include <limits>
58 #include <memory>
59 #include <unordered_set>
60 
61 //--------------------------------------------------------------------------------------
62 // Mesh and VertexFormat Data
63 //--------------------------------------------------------------------------------------
64 
65 static const char kSkipPrefix[] = "             TEST SKIPPED:";
66 
67 enum BsoFailSelect {
68     BsoFailNone,
69     BsoFailLineWidth,
70     BsoFailDepthBias,
71     BsoFailViewport,
72     BsoFailScissor,
73     BsoFailBlend,
74     BsoFailDepthBounds,
75     BsoFailStencilReadMask,
76     BsoFailStencilWriteMask,
77     BsoFailStencilReference,
78     BsoFailCmdClearAttachments,
79     BsoFailIndexBuffer,
80     BsoFailIndexBufferBadSize,
81     BsoFailIndexBufferBadOffset,
82     BsoFailIndexBufferBadMapSize,
83     BsoFailIndexBufferBadMapOffset,
84     BsoFailLineStipple,
85 };
86 
87 static const char bindStateMinimalShaderText[] = "#version 450\nvoid main() {}\n";
88 
89 static const char bindStateVertShaderText[] =
90     "#version 450\n"
91     "void main() {\n"
92     "   gl_Position = vec4(1);\n"
93     "}\n";
94 
95 static const char bindStateVertPointSizeShaderText[] =
96     "#version 450\n"
97     "out gl_PerVertex {\n"
98     "    vec4 gl_Position;\n"
99     "    float gl_PointSize;\n"
100     "};\n"
101     "void main() {\n"
102     "    gl_Position = vec4(1);\n"
103     "    gl_PointSize = 1.0;\n"
104     "}\n";
105 
106 static char const bindStateGeomShaderText[] =
107     "#version 450\n"
108     "layout(triangles) in;\n"
109     "layout(triangle_strip, max_vertices=3) out;\n"
110     "void main() {\n"
111     "   gl_Position = vec4(1);\n"
112     "   EmitVertex();\n"
113     "}\n";
114 
115 static char const bindStateGeomPointSizeShaderText[] =
116     "#version 450\n"
117     "layout (points) in;\n"
118     "layout (points) out;\n"
119     "layout (max_vertices = 1) out;\n"
120     "void main() {\n"
121     "   gl_Position = vec4(1);\n"
122     "   gl_PointSize = 1.0;\n"
123     "   EmitVertex();\n"
124     "}\n";
125 
126 static const char bindStateTscShaderText[] =
127     "#version 450\n"
128     "layout(vertices=3) out;\n"
129     "void main() {\n"
130     "   gl_TessLevelOuter[0] = gl_TessLevelOuter[1] = gl_TessLevelOuter[2] = 1;\n"
131     "   gl_TessLevelInner[0] = 1;\n"
132     "}\n";
133 
134 static const char bindStateTeshaderText[] =
135     "#version 450\n"
136     "layout(triangles, equal_spacing, cw) in;\n"
137     "void main() { gl_Position = vec4(1); }\n";
138 
139 static const char bindStateFragShaderText[] =
140     "#version 450\n"
141     "layout(location = 0) out vec4 uFragColor;\n"
142     "void main(){\n"
143     "   uFragColor = vec4(0,1,0,1);\n"
144     "}\n";
145 
146 static const char bindStateFragSamplerShaderText[] =
147     "#version 450\n"
148     "layout(set=0, binding=0) uniform sampler2D s;\n"
149     "layout(location=0) out vec4 x;\n"
150     "void main(){\n"
151     "   x = texture(s, vec2(1));\n"
152     "}\n";
153 
154 static const char bindStateFragUniformShaderText[] =
155     "#version 450\n"
156     "layout(set=0) layout(binding=0) uniform foo { int x; int y; } bar;\n"
157     "layout(location=0) out vec4 x;\n"
158     "void main(){\n"
159     "   x = vec4(bar.y);\n"
160     "}\n";
161 
162 // Static arrays helper
163 template <class ElementT, size_t array_size>
size(ElementT (&)[array_size])164 size_t size(ElementT (&)[array_size]) {
165     return array_size;
166 }
167 
168 // Format search helper
169 VkFormat FindSupportedDepthStencilFormat(VkPhysicalDevice phy);
170 
171 // Returns true if *any* requested features are available.
172 // Assumption is that the framework can successfully create an image as
173 // long as at least one of the feature bits is present (excepting VTX_BUF).
174 bool ImageFormatIsSupported(VkPhysicalDevice phy, VkFormat format, VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL,
175                             VkFormatFeatureFlags features = ~VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT);
176 
177 // Returns true if format and *all* requested features are available.
178 bool ImageFormatAndFeaturesSupported(VkPhysicalDevice phy, VkFormat format, VkImageTiling tiling, VkFormatFeatureFlags features);
179 
180 // Returns true if format and *all* requested features are available.
181 bool ImageFormatAndFeaturesSupported(const VkInstance inst, const VkPhysicalDevice phy, const VkImageCreateInfo info,
182                                      const VkFormatFeatureFlags features);
183 
184 // Validation report callback prototype
185 VKAPI_ATTR VkBool32 VKAPI_CALL myDbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location,
186                                          int32_t msgCode, const char *pLayerPrefix, const char *pMsg, void *pUserData);
187 
188 // Simple sane SamplerCreateInfo boilerplate
189 VkSamplerCreateInfo SafeSaneSamplerCreateInfo();
190 
191 VkImageViewCreateInfo SafeSaneImageViewCreateInfo(VkImage image, VkFormat format, VkImageAspectFlags aspect_mask);
192 
193 VkImageViewCreateInfo SafeSaneImageViewCreateInfo(const VkImageObj &image, VkFormat format, VkImageAspectFlags aspect_mask);
194 
195 // Helper for checking createRenderPass2 support and adding related extensions.
196 bool CheckCreateRenderPass2Support(VkRenderFramework *renderFramework, std::vector<const char *> &device_extension_names);
197 
198 // Helper for checking descriptor_indexing support and adding related extensions.
199 bool CheckDescriptorIndexingSupportAndInitFramework(VkRenderFramework *renderFramework,
200                                                     std::vector<const char *> &instance_extension_names,
201                                                     std::vector<const char *> &device_extension_names,
202                                                     VkValidationFeaturesEXT *features, void *userData);
203 
204 // Dependent "false" type for the static assert, as GCC will evaluate
205 // non-dependent static_asserts even for non-instantiated templates
206 template <typename T>
207 struct AlwaysFalse : std::false_type {};
208 
209 // Helpers to get nearest greater or smaller value (of float) -- useful for testing the boundary cases of Vulkan limits
210 template <typename T>
NearestGreater(const T from)211 T NearestGreater(const T from) {
212     using Lim = std::numeric_limits<T>;
213     const auto positive_direction = Lim::has_infinity ? Lim::infinity() : Lim::max();
214 
215     return std::nextafter(from, positive_direction);
216 }
217 
218 template <typename T>
NearestSmaller(const T from)219 T NearestSmaller(const T from) {
220     using Lim = std::numeric_limits<T>;
221     const auto negative_direction = Lim::has_infinity ? -Lim::infinity() : Lim::lowest();
222 
223     return std::nextafter(from, negative_direction);
224 }
225 
226 // ErrorMonitor Usage:
227 //
228 // Call SetDesiredFailureMsg with a string to be compared against all
229 // encountered log messages, or a validation error enum identifying
230 // desired error message. Passing NULL or VALIDATION_ERROR_MAX_ENUM
231 // will match all log messages. logMsg will return true for skipCall
232 // only if msg is matched or NULL.
233 //
234 // Call VerifyFound to determine if all desired failure messages
235 // were encountered. Call VerifyNotFound to determine if any unexpected
236 // failure was encountered.
237 class ErrorMonitor {
238    public:
239     ErrorMonitor();
240 
241     ~ErrorMonitor();
242 
243     // Set monitor to pristine state
244     void Reset();
245 
246     // ErrorMonitor will look for an error message containing the specified string(s)
247     void SetDesiredFailureMsg(const VkFlags msgFlags, const std::string msg);
248     void SetDesiredFailureMsg(const VkFlags msgFlags, const char *const msgString);
249 
250     // ErrorMonitor will look for an error message containing the specified string(s)
251     template <typename Iter>
SetDesiredFailureMsg(const VkFlags msgFlags,Iter iter,const Iter end)252     void SetDesiredFailureMsg(const VkFlags msgFlags, Iter iter, const Iter end) {
253         for (; iter != end; ++iter) {
254             SetDesiredFailureMsg(msgFlags, *iter);
255         }
256     }
257 
258     // Set an error that the error monitor will ignore. Do not use this function if you are creating a new test.
259     // TODO: This is stopgap to block new unexpected errors from being introduced. The long-term goal is to remove the use of this
260     // function and its definition.
261     void SetUnexpectedError(const char *const msg);
262 
263     VkBool32 CheckForDesiredMsg(const char *const msgString);
264     vector<string> GetOtherFailureMsgs() const;
265     VkDebugReportFlagsEXT GetMessageFlags() const;
266     bool AnyDesiredMsgFound() const;
267     bool AllDesiredMsgsFound() const;
268     void SetError(const char *const errorString);
269     void SetBailout(bool *bailout);
270     void DumpFailureMsgs() const;
271 
272     // Helpers
273 
274     // ExpectSuccess now takes an optional argument allowing a custom combination of debug flags
275     void ExpectSuccess(VkDebugReportFlagsEXT const message_flag_mask = VK_DEBUG_REPORT_ERROR_BIT_EXT);
276 
277     void VerifyFound();
278     void VerifyNotFound();
279 
280    private:
281     // TODO: This is stopgap to block new unexpected errors from being introduced. The long-term goal is to remove the use of this
282     // function and its definition.
283     bool IgnoreMessage(std::string const &msg) const;
284 
285     VkFlags message_flags_;
286     std::unordered_multiset<std::string> desired_message_strings_;
287     std::unordered_multiset<std::string> failure_message_strings_;
288     std::vector<std::string> ignore_message_strings_;
289     vector<string> other_messages_;
290     test_platform_thread_mutex mutex_;
291     bool *bailout_;
292     bool message_found_;
293 };
294 
295 class VkLayerTest : public VkRenderFramework {
296    public:
297     void VKTriangleTest(BsoFailSelect failCase);
298 
299     void GenericDrawPreparation(VkCommandBufferObj *commandBuffer, VkPipelineObj &pipelineobj, VkDescriptorSetObj &descriptorSet,
300                                 BsoFailSelect failCase);
301 
302     void Init(VkPhysicalDeviceFeatures *features = nullptr, VkPhysicalDeviceFeatures2 *features2 = nullptr,
303               const VkCommandPoolCreateFlags flags = 0, void *instance_pnext = nullptr);
304     bool AddSurfaceInstanceExtension();
305     bool AddSwapchainDeviceExtension();
306     ErrorMonitor *Monitor();
307     VkCommandBufferObj *CommandBuffer();
308 
309    protected:
310     ErrorMonitor *m_errorMonitor;
311     uint32_t m_instance_api_version = 0;
312     uint32_t m_target_api_version = 0;
313     bool m_enableWSI;
314 
315     uint32_t SetTargetApiVersion(uint32_t target_api_version);
316     uint32_t DeviceValidationVersion();
317     bool LoadDeviceProfileLayer(
318         PFN_vkSetPhysicalDeviceFormatPropertiesEXT &fpvkSetPhysicalDeviceFormatPropertiesEXT,
319         PFN_vkGetOriginalPhysicalDeviceFormatPropertiesEXT &fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT);
320 
321     VkLayerTest();
322     ~VkLayerTest();
323 };
324 
325 class VkPositiveLayerTest : public VkLayerTest {
326    public:
327    protected:
328 };
329 
330 class VkWsiEnabledLayerTest : public VkLayerTest {
331    public:
332    protected:
VkWsiEnabledLayerTest()333     VkWsiEnabledLayerTest() { m_enableWSI = true; }
334 };
335 
336 class VkBufferTest {
337    public:
338     enum eTestEnFlags {
339         eDoubleDelete,
340         eInvalidDeviceOffset,
341         eInvalidMemoryOffset,
342         eBindNullBuffer,
343         eBindFakeBuffer,
344         eFreeInvalidHandle,
345         eNone,
346     };
347 
348     enum eTestConditions { eOffsetAlignment = 1 };
349 
350     static bool GetTestConditionValid(VkDeviceObj *aVulkanDevice, eTestEnFlags aTestFlag, VkBufferUsageFlags aBufferUsage = 0);
351     // A constructor which performs validation tests within construction.
352     VkBufferTest(VkDeviceObj *aVulkanDevice, VkBufferUsageFlags aBufferUsage, eTestEnFlags aTestFlag = eNone);
353     ~VkBufferTest();
354     bool GetBufferCurrent();
355     const VkBuffer &GetBuffer();
356     void TestDoubleDestroy();
357 
358    protected:
359     bool AllocateCurrent;
360     bool BoundCurrent;
361     bool CreateCurrent;
362     bool InvalidDeleteEn;
363 
364     VkBuffer VulkanBuffer;
365     VkDevice VulkanDevice;
366     VkDeviceMemory VulkanMemory;
367 };
368 
369 struct CreatePipelineHelper;
370 class VkVerticesObj {
371    public:
372     VkVerticesObj(VkDeviceObj *aVulkanDevice, unsigned aAttributeCount, unsigned aBindingCount, unsigned aByteStride,
373                   VkDeviceSize aVertexCount, const float *aVerticies);
374     ~VkVerticesObj();
375     bool AddVertexInputToPipe(VkPipelineObj &aPipelineObj);
376     bool AddVertexInputToPipeHelpr(CreatePipelineHelper *pipelineHelper);
377     void BindVertexBuffers(VkCommandBuffer aCommandBuffer, unsigned aOffsetCount = 0, VkDeviceSize *aOffsetList = nullptr);
378 
379    protected:
380     static uint32_t BindIdGenerator;
381 
382     bool BoundCurrent;
383     unsigned AttributeCount;
384     unsigned BindingCount;
385     uint32_t BindId;
386 
387     VkPipelineVertexInputStateCreateInfo PipelineVertexInputStateCreateInfo;
388     VkVertexInputAttributeDescription *VertexInputAttributeDescription;
389     VkVertexInputBindingDescription *VertexInputBindingDescription;
390     VkConstantBufferObj VulkanMemoryBuffer;
391 };
392 
393 struct OneOffDescriptorSet {
394     VkDeviceObj *device_;
395     VkDescriptorPool pool_;
396     VkDescriptorSetLayoutObj layout_;
397     VkDescriptorSet set_;
398     typedef std::vector<VkDescriptorSetLayoutBinding> Bindings;
399     std::vector<VkDescriptorBufferInfo> buffer_infos;
400     std::vector<VkDescriptorImageInfo> image_infos;
401     std::vector<VkWriteDescriptorSet> descriptor_writes;
402 
403     OneOffDescriptorSet(VkDeviceObj *device, const Bindings &bindings, VkDescriptorSetLayoutCreateFlags layout_flags = 0,
404                         void *layout_pnext = NULL, VkDescriptorPoolCreateFlags poolFlags = 0, void *allocate_pnext = NULL);
405     ~OneOffDescriptorSet();
406     bool Initialized();
407     void WriteDescriptorBufferInfo(int blinding, VkBuffer buffer, VkDeviceSize size,
408                                    VkDescriptorType descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
409     void WriteDescriptorBufferView(int blinding, VkBufferView &buffer_view,
410                                    VkDescriptorType descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
411     void WriteDescriptorImageInfo(int blinding, VkImageView image_view, VkSampler sampler,
412                                   VkDescriptorType descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
413     void UpdateDescriptorSets();
414 };
415 
416 template <typename T>
IsValidVkStruct(const T & s)417 bool IsValidVkStruct(const T &s) {
418     return LvlTypeMap<T>::kSType == s.sType;
419 }
420 
421 // Helper class for tersely creating create pipeline tests
422 //
423 // Designed with minimal error checking to ensure easy error state creation
424 // See OneshotTest for typical usage
425 struct CreatePipelineHelper {
426    public:
427     std::vector<VkDescriptorSetLayoutBinding> dsl_bindings_;
428     std::unique_ptr<OneOffDescriptorSet> descriptor_set_;
429     std::vector<VkPipelineShaderStageCreateInfo> shader_stages_;
430     VkPipelineVertexInputStateCreateInfo vi_ci_ = {};
431     VkPipelineInputAssemblyStateCreateInfo ia_ci_ = {};
432     VkPipelineTessellationStateCreateInfo tess_ci_ = {};
433     VkViewport viewport_ = {};
434     VkRect2D scissor_ = {};
435     VkPipelineViewportStateCreateInfo vp_state_ci_ = {};
436     VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci_ = {};
437     VkPipelineLayoutCreateInfo pipeline_layout_ci_ = {};
438     VkPipelineLayoutObj pipeline_layout_;
439     VkPipelineDynamicStateCreateInfo dyn_state_ci_ = {};
440     VkPipelineRasterizationStateCreateInfo rs_state_ci_ = {};
441     VkPipelineRasterizationLineStateCreateInfoEXT line_state_ci_ = {};
442     VkPipelineColorBlendAttachmentState cb_attachments_ = {};
443     VkPipelineColorBlendStateCreateInfo cb_ci_ = {};
444     VkGraphicsPipelineCreateInfo gp_ci_ = {};
445     VkPipelineCacheCreateInfo pc_ci_ = {};
446     VkPipeline pipeline_ = VK_NULL_HANDLE;
447     VkPipelineCache pipeline_cache_ = VK_NULL_HANDLE;
448     std::unique_ptr<VkShaderObj> vs_;
449     std::unique_ptr<VkShaderObj> fs_;
450     VkLayerTest &layer_test_;
451     CreatePipelineHelper(VkLayerTest &test);
452     ~CreatePipelineHelper();
453 
454     void InitDescriptorSetInfo();
455     void InitInputAndVertexInfo();
456     void InitMultisampleInfo();
457     void InitPipelineLayoutInfo();
458     void InitViewportInfo();
459     void InitDynamicStateInfo();
460     void InitShaderInfo();
461     void InitRasterizationInfo();
462     void InitLineRasterizationInfo();
463     void InitBlendStateInfo();
464     void InitGraphicsPipelineInfo();
465     void InitPipelineCacheInfo();
466 
467     // Not called by default during init_info
468     void InitTesselationState();
469 
470     // TDB -- add control for optional and/or additional initialization
471     void InitInfo();
472     void InitState();
473     void LateBindPipelineInfo();
474     VkResult CreateGraphicsPipeline(bool implicit_destroy = true, bool do_late_bind = true);
475 
476     // Helper function to create a simple test case (positive or negative)
477     //
478     // info_override can be any callable that takes a CreatePipelineHeper &
479     // flags, error can be any args accepted by "SetDesiredFailure".
480     template <typename Test, typename OverrideFunc, typename Error>
481     static void OneshotTest(Test &test, const OverrideFunc &info_override, const VkFlags flags, const std::vector<Error> &errors,
482                             bool positive_test = false) {
483         CreatePipelineHelper helper(test);
484         helper.InitInfo();
485         info_override(helper);
486         helper.InitState();
487 
488         for (const auto &error : errors) test.Monitor()->SetDesiredFailureMsg(flags, error);
489         helper.CreateGraphicsPipeline();
490 
491         if (positive_test) {
492             test.Monitor()->VerifyNotFound();
493         } else {
494             test.Monitor()->VerifyFound();
495         }
496     }
497 
498     template <typename Test, typename OverrideFunc, typename Error>
499     static void OneshotTest(Test &test, const OverrideFunc &info_override, const VkFlags flags, Error error,
500                             bool positive_test = false) {
501         OneshotTest(test, info_override, flags, std::vector<Error>(1, error), positive_test);
502     }
503 };
504 
505 struct CreateComputePipelineHelper {
506    public:
507     std::vector<VkDescriptorSetLayoutBinding> dsl_bindings_;
508     std::unique_ptr<OneOffDescriptorSet> descriptor_set_;
509     VkPipelineLayoutCreateInfo pipeline_layout_ci_ = {};
510     VkPipelineLayoutObj pipeline_layout_;
511     VkComputePipelineCreateInfo cp_ci_ = {};
512     VkPipelineCacheCreateInfo pc_ci_ = {};
513     VkPipeline pipeline_ = VK_NULL_HANDLE;
514     VkPipelineCache pipeline_cache_ = VK_NULL_HANDLE;
515     std::unique_ptr<VkShaderObj> cs_;
516     VkLayerTest &layer_test_;
517     CreateComputePipelineHelper(VkLayerTest &test);
518     ~CreateComputePipelineHelper();
519 
520     void InitDescriptorSetInfo();
521     void InitPipelineLayoutInfo();
522     void InitShaderInfo();
523     void InitComputePipelineInfo();
524     void InitPipelineCacheInfo();
525 
526     // TDB -- add control for optional and/or additional initialization
527     void InitInfo();
528     void InitState();
529     void LateBindPipelineInfo();
530     VkResult CreateComputePipeline(bool implicit_destroy = true, bool do_late_bind = true);
531 
532     // Helper function to create a simple test case (positive or negative)
533     //
534     // info_override can be any callable that takes a CreatePipelineHeper &
535     // flags, error can be any args accepted by "SetDesiredFailure".
536     template <typename Test, typename OverrideFunc, typename Error>
537     static void OneshotTest(Test &test, const OverrideFunc &info_override, const VkFlags flags, const std::vector<Error> &errors,
538                             bool positive_test = false) {
539         CreateComputePipelineHelper helper(test);
540         helper.InitInfo();
541         info_override(helper);
542         helper.InitState();
543 
544         for (const auto &error : errors) test.Monitor()->SetDesiredFailureMsg(flags, error);
545         helper.CreateComputePipeline();
546 
547         if (positive_test) {
548             test.Monitor()->VerifyNotFound();
549         } else {
550             test.Monitor()->VerifyFound();
551         }
552     }
553 
554     template <typename Test, typename OverrideFunc, typename Error>
555     static void OneshotTest(Test &test, const OverrideFunc &info_override, const VkFlags flags, Error error,
556                             bool positive_test = false) {
557         OneshotTest(test, info_override, flags, std::vector<Error>(1, error), positive_test);
558     }
559 };
560 
561 // Helper class for tersely creating create ray tracing pipeline tests
562 //
563 // Designed with minimal error checking to ensure easy error state creation
564 // See OneshotTest for typical usage
565 struct CreateNVRayTracingPipelineHelper {
566    public:
567     std::vector<VkDescriptorSetLayoutBinding> dsl_bindings_;
568     std::unique_ptr<OneOffDescriptorSet> descriptor_set_;
569     std::vector<VkPipelineShaderStageCreateInfo> shader_stages_;
570     VkPipelineLayoutCreateInfo pipeline_layout_ci_ = {};
571     VkPipelineLayoutObj pipeline_layout_;
572     VkRayTracingPipelineCreateInfoNV rp_ci_ = {};
573     VkPipelineCacheCreateInfo pc_ci_ = {};
574     VkPipeline pipeline_ = VK_NULL_HANDLE;
575     VkPipelineCache pipeline_cache_ = VK_NULL_HANDLE;
576     std::vector<VkRayTracingShaderGroupCreateInfoNV> groups_;
577     std::unique_ptr<VkShaderObj> rgs_;
578     std::unique_ptr<VkShaderObj> chs_;
579     std::unique_ptr<VkShaderObj> mis_;
580     VkLayerTest &layer_test_;
581     CreateNVRayTracingPipelineHelper(VkLayerTest &test);
582     ~CreateNVRayTracingPipelineHelper();
583 
584     static bool InitInstanceExtensions(VkLayerTest &test, std::vector<const char *> &instance_extension_names);
585     static bool InitDeviceExtensions(VkLayerTest &test, std::vector<const char *> &device_extension_names);
586     void InitShaderGroups();
587     void InitDescriptorSetInfo();
588     void InitPipelineLayoutInfo();
589     void InitShaderInfo();
590     void InitNVRayTracingPipelineInfo();
591     void InitPipelineCacheInfo();
592     void InitInfo();
593     void InitState();
594     void LateBindPipelineInfo();
595     VkResult CreateNVRayTracingPipeline(bool implicit_destroy = true, bool do_late_bind = true);
596 
597     // Helper function to create a simple test case (positive or negative)
598     //
599     // info_override can be any callable that takes a CreateNVRayTracingPipelineHelper &
600     // flags, error can be any args accepted by "SetDesiredFailure".
601     template <typename Test, typename OverrideFunc, typename Error>
602     static void OneshotTest(Test &test, const OverrideFunc &info_override, const std::vector<Error> &errors,
603                             const VkFlags flags = VK_DEBUG_REPORT_ERROR_BIT_EXT) {
604         CreateNVRayTracingPipelineHelper helper(test);
605         helper.InitInfo();
606         info_override(helper);
607         helper.InitState();
608 
609         for (const auto &error : errors) test.Monitor()->SetDesiredFailureMsg(flags, error);
610         helper.CreateNVRayTracingPipeline();
611         test.Monitor()->VerifyFound();
612     }
613 
614     template <typename Test, typename OverrideFunc, typename Error>
615     static void OneshotTest(Test &test, const OverrideFunc &info_override, Error error,
616                             const VkFlags flags = VK_DEBUG_REPORT_ERROR_BIT_EXT) {
617         OneshotTest(test, info_override, std::vector<Error>(1, error), flags);
618     }
619 
620     template <typename Test, typename OverrideFunc>
621     static void OneshotPositiveTest(Test &test, const OverrideFunc &info_override,
622                                     const VkDebugReportFlagsEXT message_flag_mask = VK_DEBUG_REPORT_ERROR_BIT_EXT) {
623         CreateNVRayTracingPipelineHelper helper(test);
624         helper.InitInfo();
625         info_override(helper);
626         helper.InitState();
627 
628         test.Monitor()->ExpectSuccess(message_flag_mask);
629         ASSERT_VK_SUCCESS(helper.CreateNVRayTracingPipeline());
630         test.Monitor()->VerifyNotFound();
631     }
632 };
633 
634 namespace chain_util {
635 template <typename T>
636 T Init(const void *pnext_in = nullptr) {
637     T pnext_obj = {};
638     pnext_obj.sType = LvlTypeMap<T>::kSType;
639     pnext_obj.pNext = pnext_in;
640     return pnext_obj;
641 }
642 
643 class ExtensionChain {
644     const void *head_ = nullptr;
645     typedef std::function<bool(const char *)> AddIfFunction;
646     AddIfFunction add_if_;
647     typedef std::vector<const char *> List;
648     List *list_;
649 
650    public:
651     template <typename F>
ExtensionChain(F & add_if,List * list)652     ExtensionChain(F &add_if, List *list) : add_if_(add_if), list_(list) {}
653 
654     template <typename T>
Add(const char * name,T & obj)655     void Add(const char *name, T &obj) {
656         if (add_if_(name)) {
657             if (list_) {
658                 list_->push_back(name);
659             }
660             obj.pNext = head_;
661             head_ = &obj;
662         }
663     }
664 
665     const void *Head() const;
666 };
667 }  // namespace chain_util
668 
669 // PushDescriptorProperties helper
670 VkPhysicalDevicePushDescriptorPropertiesKHR GetPushDescriptorProperties(VkInstance instance, VkPhysicalDevice gpu);
671 
672 // Subgroup properties helper
673 VkPhysicalDeviceSubgroupProperties GetSubgroupProperties(VkInstance instance, VkPhysicalDevice gpu);
674 
675 class BarrierQueueFamilyTestHelper {
676    public:
677     struct QueueFamilyObjs {
678         uint32_t index;
679         // We would use std::unique_ptr, but this triggers a compiler error on older compilers
680         VkQueueObj *queue = nullptr;
681         VkCommandPoolObj *command_pool = nullptr;
682         VkCommandBufferObj *command_buffer = nullptr;
683         VkCommandBufferObj *command_buffer2 = nullptr;
684         ~QueueFamilyObjs();
685         void Init(VkDeviceObj *device, uint32_t qf_index, VkQueue qf_queue, VkCommandPoolCreateFlags cp_flags);
686     };
687 
688     struct Context {
689         VkLayerTest *layer_test;
690         uint32_t default_index;
691         std::unordered_map<uint32_t, QueueFamilyObjs> queue_families;
692         Context(VkLayerTest *test, const std::vector<uint32_t> &queue_family_indices);
693         void Reset();
694     };
695 
696     BarrierQueueFamilyTestHelper(Context *context);
697     // Init with queue families non-null for CONCURRENT sharing mode (which requires them)
698     void Init(std::vector<uint32_t> *families, bool image_memory = true, bool buffer_memory = true);
699 
700     QueueFamilyObjs *GetQueueFamilyInfo(Context *context, uint32_t qfi);
701 
702     enum Modifier {
703         NONE,
704         DOUBLE_RECORD,
705         DOUBLE_COMMAND_BUFFER,
706     };
707 
708     void operator()(std::string img_err, std::string buf_err = "", uint32_t src = VK_QUEUE_FAMILY_IGNORED,
709                     uint32_t dst = VK_QUEUE_FAMILY_IGNORED, bool positive = false,
710                     uint32_t queue_family_index = kInvalidQueueFamily, Modifier mod = Modifier::NONE);
711 
712     static const uint32_t kInvalidQueueFamily = UINT32_MAX;
713     Context *context_;
714     VkImageObj image_;
715     VkImageMemoryBarrier image_barrier_;
716     VkBufferObj buffer_;
717     VkBufferMemoryBarrier buffer_barrier_;
718 };
719 
720 struct DebugUtilsLabelCheckData {
721     std::function<void(const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, DebugUtilsLabelCheckData *)> callback;
722     size_t count;
723 };
724 
725 bool operator==(const VkDebugUtilsLabelEXT &rhs, const VkDebugUtilsLabelEXT &lhs);
726 
727 VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
728                                                   VkDebugUtilsMessageTypeFlagsEXT messageTypes,
729                                                   const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData);
730 
731 #if GTEST_IS_THREADSAFE
732 struct thread_data_struct {
733     VkCommandBuffer commandBuffer;
734     VkDevice device;
735     VkEvent event;
736     bool bailout;
737 };
738 
739 extern "C" void *AddToCommandBuffer(void *arg);
740 #endif  // GTEST_IS_THREADSAFE
741 
742 extern "C" void *ReleaseNullFence(void *arg);
743 
744 void TestRenderPassCreate(ErrorMonitor *error_monitor, const VkDevice device, const VkRenderPassCreateInfo *create_info,
745                           bool rp2_supported, const char *rp1_vuid, const char *rp2_vuid);
746 void PositiveTestRenderPassCreate(ErrorMonitor *error_monitor, const VkDevice device, const VkRenderPassCreateInfo *create_info,
747                                   bool rp2_supported);
748 void TestRenderPass2KHRCreate(ErrorMonitor *error_monitor, const VkDevice device, const VkRenderPassCreateInfo2KHR *create_info,
749                               const char *rp2_vuid);
750 void TestRenderPassBegin(ErrorMonitor *error_monitor, const VkDevice device, const VkCommandBuffer command_buffer,
751                          const VkRenderPassBeginInfo *begin_info, bool rp2Supported, const char *rp1_vuid, const char *rp2_vuid);
752 
753 // Helpers for the tests below
754 void ValidOwnershipTransferOp(ErrorMonitor *monitor, VkCommandBufferObj *cb, VkPipelineStageFlags src_stages,
755                               VkPipelineStageFlags dst_stages, const VkBufferMemoryBarrier *buf_barrier,
756                               const VkImageMemoryBarrier *img_barrier);
757 
758 void ValidOwnershipTransfer(ErrorMonitor *monitor, VkCommandBufferObj *cb_from, VkCommandBufferObj *cb_to,
759                             VkPipelineStageFlags src_stages, VkPipelineStageFlags dst_stages,
760                             const VkBufferMemoryBarrier *buf_barrier, const VkImageMemoryBarrier *img_barrier);
761 
762 VkResult GPDIFPHelper(VkPhysicalDevice dev, const VkImageCreateInfo *ci, VkImageFormatProperties *limits = nullptr);
763 
764 VkFormat FindFormatLinearWithoutMips(VkPhysicalDevice gpu, VkImageCreateInfo image_ci);
765 
766 bool FindFormatWithoutSamples(VkPhysicalDevice gpu, VkImageCreateInfo &image_ci);
767 
768 bool FindUnsupportedImage(VkPhysicalDevice gpu, VkImageCreateInfo &image_ci);
769 
770 VkFormat FindFormatWithoutFeatures(VkPhysicalDevice gpu, VkImageTiling tiling,
771                                    VkFormatFeatureFlags undesired_features = UINT32_MAX);
772 
773 void NegHeightViewportTests(VkDeviceObj *m_device, VkCommandBufferObj *m_commandBuffer, ErrorMonitor *m_errorMonitor);
774 
775 void CreateSamplerTest(VkLayerTest &test, const VkSamplerCreateInfo *pCreateInfo, std::string code = "");
776 
777 void CreateBufferTest(VkLayerTest &test, const VkBufferCreateInfo *pCreateInfo, std::string code = "");
778 
779 void CreateImageTest(VkLayerTest &test, const VkImageCreateInfo *pCreateInfo, std::string code = "");
780 
781 void CreateBufferViewTest(VkLayerTest &test, const VkBufferViewCreateInfo *pCreateInfo, const std::vector<std::string> &codes);
782 
783 void CreateImageViewTest(VkLayerTest &test, const VkImageViewCreateInfo *pCreateInfo, std::string code = "");
784 
785 void print_android(const char *c);
786 #endif  // VKLAYERTEST_H
787