xref: /aosp_15_r20/external/vulkan-validation-layers/tests/layer_validation_tests.cpp (revision b7893ccf7851cd6a48cc5a1e965257d8a5cdcc70)
1*b7893ccfSSadaf Ebrahimi /*
2*b7893ccfSSadaf Ebrahimi  * Copyright (c) 2015-2019 The Khronos Group Inc.
3*b7893ccfSSadaf Ebrahimi  * Copyright (c) 2015-2019 Valve Corporation
4*b7893ccfSSadaf Ebrahimi  * Copyright (c) 2015-2019 LunarG, Inc.
5*b7893ccfSSadaf Ebrahimi  * Copyright (c) 2015-2019 Google, Inc.
6*b7893ccfSSadaf Ebrahimi  *
7*b7893ccfSSadaf Ebrahimi  * Licensed under the Apache License, Version 2.0 (the "License");
8*b7893ccfSSadaf Ebrahimi  * you may not use this file except in compliance with the License.
9*b7893ccfSSadaf Ebrahimi  * You may obtain a copy of the License at
10*b7893ccfSSadaf Ebrahimi  *
11*b7893ccfSSadaf Ebrahimi  *     http://www.apache.org/licenses/LICENSE-2.0
12*b7893ccfSSadaf Ebrahimi  *
13*b7893ccfSSadaf Ebrahimi  * Author: Chia-I Wu <[email protected]>
14*b7893ccfSSadaf Ebrahimi  * Author: Chris Forbes <[email protected]>
15*b7893ccfSSadaf Ebrahimi  * Author: Courtney Goeltzenleuchter <[email protected]>
16*b7893ccfSSadaf Ebrahimi  * Author: Mark Lobodzinski <[email protected]>
17*b7893ccfSSadaf Ebrahimi  * Author: Mike Stroyan <[email protected]>
18*b7893ccfSSadaf Ebrahimi  * Author: Tobin Ehlis <[email protected]>
19*b7893ccfSSadaf Ebrahimi  * Author: Tony Barbour <[email protected]>
20*b7893ccfSSadaf Ebrahimi  * Author: Cody Northrop <[email protected]>
21*b7893ccfSSadaf Ebrahimi  * Author: Dave Houlton <[email protected]>
22*b7893ccfSSadaf Ebrahimi  * Author: Jeremy Kniager <[email protected]>
23*b7893ccfSSadaf Ebrahimi  * Author: Shannon McPherson <[email protected]>
24*b7893ccfSSadaf Ebrahimi  * Author: John Zulauf <[email protected]>
25*b7893ccfSSadaf Ebrahimi  */
26*b7893ccfSSadaf Ebrahimi #include "cast_utils.h"
27*b7893ccfSSadaf Ebrahimi #include "layer_validation_tests.h"
28*b7893ccfSSadaf Ebrahimi 
FindSupportedDepthStencilFormat(VkPhysicalDevice phy)29*b7893ccfSSadaf Ebrahimi VkFormat FindSupportedDepthStencilFormat(VkPhysicalDevice phy) {
30*b7893ccfSSadaf Ebrahimi     const VkFormat ds_formats[] = {VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT};
31*b7893ccfSSadaf Ebrahimi     for (uint32_t i = 0; i < size(ds_formats); ++i) {
32*b7893ccfSSadaf Ebrahimi         VkFormatProperties format_props;
33*b7893ccfSSadaf Ebrahimi         vkGetPhysicalDeviceFormatProperties(phy, ds_formats[i], &format_props);
34*b7893ccfSSadaf Ebrahimi 
35*b7893ccfSSadaf Ebrahimi         if (format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
36*b7893ccfSSadaf Ebrahimi             return ds_formats[i];
37*b7893ccfSSadaf Ebrahimi         }
38*b7893ccfSSadaf Ebrahimi     }
39*b7893ccfSSadaf Ebrahimi     return VK_FORMAT_UNDEFINED;
40*b7893ccfSSadaf Ebrahimi }
41*b7893ccfSSadaf Ebrahimi 
ImageFormatIsSupported(VkPhysicalDevice phy,VkFormat format,VkImageTiling tiling,VkFormatFeatureFlags features)42*b7893ccfSSadaf Ebrahimi bool ImageFormatIsSupported(VkPhysicalDevice phy, VkFormat format, VkImageTiling tiling, VkFormatFeatureFlags features) {
43*b7893ccfSSadaf Ebrahimi     VkFormatProperties format_props;
44*b7893ccfSSadaf Ebrahimi     vkGetPhysicalDeviceFormatProperties(phy, format, &format_props);
45*b7893ccfSSadaf Ebrahimi     VkFormatFeatureFlags phy_features =
46*b7893ccfSSadaf Ebrahimi         (VK_IMAGE_TILING_OPTIMAL == tiling ? format_props.optimalTilingFeatures : format_props.linearTilingFeatures);
47*b7893ccfSSadaf Ebrahimi     return (0 != (phy_features & features));
48*b7893ccfSSadaf Ebrahimi }
49*b7893ccfSSadaf Ebrahimi 
ImageFormatAndFeaturesSupported(VkPhysicalDevice phy,VkFormat format,VkImageTiling tiling,VkFormatFeatureFlags features)50*b7893ccfSSadaf Ebrahimi bool ImageFormatAndFeaturesSupported(VkPhysicalDevice phy, VkFormat format, VkImageTiling tiling, VkFormatFeatureFlags features) {
51*b7893ccfSSadaf Ebrahimi     VkFormatProperties format_props;
52*b7893ccfSSadaf Ebrahimi     vkGetPhysicalDeviceFormatProperties(phy, format, &format_props);
53*b7893ccfSSadaf Ebrahimi     VkFormatFeatureFlags phy_features =
54*b7893ccfSSadaf Ebrahimi         (VK_IMAGE_TILING_OPTIMAL == tiling ? format_props.optimalTilingFeatures : format_props.linearTilingFeatures);
55*b7893ccfSSadaf Ebrahimi     return (features == (phy_features & features));
56*b7893ccfSSadaf Ebrahimi }
57*b7893ccfSSadaf Ebrahimi 
ImageFormatAndFeaturesSupported(const VkInstance inst,const VkPhysicalDevice phy,const VkImageCreateInfo info,const VkFormatFeatureFlags features)58*b7893ccfSSadaf Ebrahimi bool ImageFormatAndFeaturesSupported(const VkInstance inst, const VkPhysicalDevice phy, const VkImageCreateInfo info,
59*b7893ccfSSadaf Ebrahimi                                      const VkFormatFeatureFlags features) {
60*b7893ccfSSadaf Ebrahimi     // Verify physical device support of format features
61*b7893ccfSSadaf Ebrahimi     if (!ImageFormatAndFeaturesSupported(phy, info.format, info.tiling, features)) {
62*b7893ccfSSadaf Ebrahimi         return false;
63*b7893ccfSSadaf Ebrahimi     }
64*b7893ccfSSadaf Ebrahimi 
65*b7893ccfSSadaf Ebrahimi     // Verify that PhysDevImageFormatProp() also claims support for the specific usage
66*b7893ccfSSadaf Ebrahimi     VkImageFormatProperties props;
67*b7893ccfSSadaf Ebrahimi     VkResult err =
68*b7893ccfSSadaf Ebrahimi         vkGetPhysicalDeviceImageFormatProperties(phy, info.format, info.imageType, info.tiling, info.usage, info.flags, &props);
69*b7893ccfSSadaf Ebrahimi     if (VK_SUCCESS != err) {
70*b7893ccfSSadaf Ebrahimi         return false;
71*b7893ccfSSadaf Ebrahimi     }
72*b7893ccfSSadaf Ebrahimi 
73*b7893ccfSSadaf Ebrahimi #if 0  // Convinced this chunk doesn't currently add any additional info, but leaving in place because it may be
74*b7893ccfSSadaf Ebrahimi        // necessary with future extensions
75*b7893ccfSSadaf Ebrahimi 
76*b7893ccfSSadaf Ebrahimi     // Verify again using version 2, if supported, which *can* return more property data than the original...
77*b7893ccfSSadaf Ebrahimi     // (It's not clear that this is any more definitive than using the original version - but no harm)
78*b7893ccfSSadaf Ebrahimi     PFN_vkGetPhysicalDeviceImageFormatProperties2KHR p_GetPDIFP2KHR =
79*b7893ccfSSadaf Ebrahimi         (PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)vkGetInstanceProcAddr(inst,
80*b7893ccfSSadaf Ebrahimi                                                                                 "vkGetPhysicalDeviceImageFormatProperties2KHR");
81*b7893ccfSSadaf Ebrahimi     if (NULL != p_GetPDIFP2KHR) {
82*b7893ccfSSadaf Ebrahimi         VkPhysicalDeviceImageFormatInfo2KHR fmt_info{};
83*b7893ccfSSadaf Ebrahimi         fmt_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR;
84*b7893ccfSSadaf Ebrahimi         fmt_info.pNext = nullptr;
85*b7893ccfSSadaf Ebrahimi         fmt_info.format = info.format;
86*b7893ccfSSadaf Ebrahimi         fmt_info.type = info.imageType;
87*b7893ccfSSadaf Ebrahimi         fmt_info.tiling = info.tiling;
88*b7893ccfSSadaf Ebrahimi         fmt_info.usage = info.usage;
89*b7893ccfSSadaf Ebrahimi         fmt_info.flags = info.flags;
90*b7893ccfSSadaf Ebrahimi 
91*b7893ccfSSadaf Ebrahimi         VkImageFormatProperties2KHR fmt_props = {};
92*b7893ccfSSadaf Ebrahimi         fmt_props.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR;
93*b7893ccfSSadaf Ebrahimi         err = p_GetPDIFP2KHR(phy, &fmt_info, &fmt_props);
94*b7893ccfSSadaf Ebrahimi         if (VK_SUCCESS != err) {
95*b7893ccfSSadaf Ebrahimi             return false;
96*b7893ccfSSadaf Ebrahimi         }
97*b7893ccfSSadaf Ebrahimi     }
98*b7893ccfSSadaf Ebrahimi #endif
99*b7893ccfSSadaf Ebrahimi 
100*b7893ccfSSadaf Ebrahimi     return true;
101*b7893ccfSSadaf Ebrahimi }
102*b7893ccfSSadaf Ebrahimi 
myDbgFunc(VkFlags msgFlags,VkDebugReportObjectTypeEXT objType,uint64_t srcObject,size_t location,int32_t msgCode,const char * pLayerPrefix,const char * pMsg,void * pUserData)103*b7893ccfSSadaf Ebrahimi VKAPI_ATTR VkBool32 VKAPI_CALL myDbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location,
104*b7893ccfSSadaf Ebrahimi                                          int32_t msgCode, const char *pLayerPrefix, const char *pMsg, void *pUserData) {
105*b7893ccfSSadaf Ebrahimi     ErrorMonitor *errMonitor = (ErrorMonitor *)pUserData;
106*b7893ccfSSadaf Ebrahimi     if (msgFlags & errMonitor->GetMessageFlags()) {
107*b7893ccfSSadaf Ebrahimi         return errMonitor->CheckForDesiredMsg(pMsg);
108*b7893ccfSSadaf Ebrahimi     }
109*b7893ccfSSadaf Ebrahimi     return VK_FALSE;
110*b7893ccfSSadaf Ebrahimi }
111*b7893ccfSSadaf Ebrahimi 
GetPushDescriptorProperties(VkInstance instance,VkPhysicalDevice gpu)112*b7893ccfSSadaf Ebrahimi VkPhysicalDevicePushDescriptorPropertiesKHR GetPushDescriptorProperties(VkInstance instance, VkPhysicalDevice gpu) {
113*b7893ccfSSadaf Ebrahimi     // Find address of extension call and make the call -- assumes needed extensions are enabled.
114*b7893ccfSSadaf Ebrahimi     PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR =
115*b7893ccfSSadaf Ebrahimi         (PFN_vkGetPhysicalDeviceProperties2KHR)vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2KHR");
116*b7893ccfSSadaf Ebrahimi     assert(vkGetPhysicalDeviceProperties2KHR != nullptr);
117*b7893ccfSSadaf Ebrahimi 
118*b7893ccfSSadaf Ebrahimi     // Get the push descriptor limits
119*b7893ccfSSadaf Ebrahimi     auto push_descriptor_prop = lvl_init_struct<VkPhysicalDevicePushDescriptorPropertiesKHR>();
120*b7893ccfSSadaf Ebrahimi     auto prop2 = lvl_init_struct<VkPhysicalDeviceProperties2KHR>(&push_descriptor_prop);
121*b7893ccfSSadaf Ebrahimi     vkGetPhysicalDeviceProperties2KHR(gpu, &prop2);
122*b7893ccfSSadaf Ebrahimi     return push_descriptor_prop;
123*b7893ccfSSadaf Ebrahimi }
124*b7893ccfSSadaf Ebrahimi 
GetSubgroupProperties(VkInstance instance,VkPhysicalDevice gpu)125*b7893ccfSSadaf Ebrahimi VkPhysicalDeviceSubgroupProperties GetSubgroupProperties(VkInstance instance, VkPhysicalDevice gpu) {
126*b7893ccfSSadaf Ebrahimi     auto subgroup_prop = lvl_init_struct<VkPhysicalDeviceSubgroupProperties>();
127*b7893ccfSSadaf Ebrahimi 
128*b7893ccfSSadaf Ebrahimi     auto prop2 = lvl_init_struct<VkPhysicalDeviceProperties2>(&subgroup_prop);
129*b7893ccfSSadaf Ebrahimi     vkGetPhysicalDeviceProperties2(gpu, &prop2);
130*b7893ccfSSadaf Ebrahimi     return subgroup_prop;
131*b7893ccfSSadaf Ebrahimi }
132*b7893ccfSSadaf Ebrahimi 
operator ==(const VkDebugUtilsLabelEXT & rhs,const VkDebugUtilsLabelEXT & lhs)133*b7893ccfSSadaf Ebrahimi bool operator==(const VkDebugUtilsLabelEXT &rhs, const VkDebugUtilsLabelEXT &lhs) {
134*b7893ccfSSadaf Ebrahimi     bool is_equal = (rhs.color[0] == lhs.color[0]) && (rhs.color[1] == lhs.color[1]) && (rhs.color[2] == lhs.color[2]) &&
135*b7893ccfSSadaf Ebrahimi                     (rhs.color[3] == lhs.color[3]);
136*b7893ccfSSadaf Ebrahimi     if (is_equal) {
137*b7893ccfSSadaf Ebrahimi         if (rhs.pLabelName && lhs.pLabelName) {
138*b7893ccfSSadaf Ebrahimi             is_equal = (0 == strcmp(rhs.pLabelName, lhs.pLabelName));
139*b7893ccfSSadaf Ebrahimi         } else {
140*b7893ccfSSadaf Ebrahimi             is_equal = (rhs.pLabelName == nullptr) && (lhs.pLabelName == nullptr);
141*b7893ccfSSadaf Ebrahimi         }
142*b7893ccfSSadaf Ebrahimi     }
143*b7893ccfSSadaf Ebrahimi     return is_equal;
144*b7893ccfSSadaf Ebrahimi }
145*b7893ccfSSadaf Ebrahimi 
DebugUtilsCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,VkDebugUtilsMessageTypeFlagsEXT messageTypes,const VkDebugUtilsMessengerCallbackDataEXT * pCallbackData,void * pUserData)146*b7893ccfSSadaf Ebrahimi VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
147*b7893ccfSSadaf Ebrahimi                                                   VkDebugUtilsMessageTypeFlagsEXT messageTypes,
148*b7893ccfSSadaf Ebrahimi                                                   const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData) {
149*b7893ccfSSadaf Ebrahimi     auto *data = reinterpret_cast<DebugUtilsLabelCheckData *>(pUserData);
150*b7893ccfSSadaf Ebrahimi     data->callback(pCallbackData, data);
151*b7893ccfSSadaf Ebrahimi     return VK_FALSE;
152*b7893ccfSSadaf Ebrahimi }
153*b7893ccfSSadaf Ebrahimi 
154*b7893ccfSSadaf Ebrahimi #if GTEST_IS_THREADSAFE
AddToCommandBuffer(void * arg)155*b7893ccfSSadaf Ebrahimi extern "C" void *AddToCommandBuffer(void *arg) {
156*b7893ccfSSadaf Ebrahimi     struct thread_data_struct *data = (struct thread_data_struct *)arg;
157*b7893ccfSSadaf Ebrahimi 
158*b7893ccfSSadaf Ebrahimi     for (int i = 0; i < 80000; i++) {
159*b7893ccfSSadaf Ebrahimi         vkCmdSetEvent(data->commandBuffer, data->event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
160*b7893ccfSSadaf Ebrahimi         if (data->bailout) {
161*b7893ccfSSadaf Ebrahimi             break;
162*b7893ccfSSadaf Ebrahimi         }
163*b7893ccfSSadaf Ebrahimi     }
164*b7893ccfSSadaf Ebrahimi     return NULL;
165*b7893ccfSSadaf Ebrahimi }
166*b7893ccfSSadaf Ebrahimi #endif  // GTEST_IS_THREADSAFE
167*b7893ccfSSadaf Ebrahimi 
ReleaseNullFence(void * arg)168*b7893ccfSSadaf Ebrahimi extern "C" void *ReleaseNullFence(void *arg) {
169*b7893ccfSSadaf Ebrahimi     struct thread_data_struct *data = (struct thread_data_struct *)arg;
170*b7893ccfSSadaf Ebrahimi 
171*b7893ccfSSadaf Ebrahimi     for (int i = 0; i < 40000; i++) {
172*b7893ccfSSadaf Ebrahimi         vkDestroyFence(data->device, VK_NULL_HANDLE, NULL);
173*b7893ccfSSadaf Ebrahimi         if (data->bailout) {
174*b7893ccfSSadaf Ebrahimi             break;
175*b7893ccfSSadaf Ebrahimi         }
176*b7893ccfSSadaf Ebrahimi     }
177*b7893ccfSSadaf Ebrahimi     return NULL;
178*b7893ccfSSadaf Ebrahimi }
179*b7893ccfSSadaf Ebrahimi 
TestRenderPassCreate(ErrorMonitor * error_monitor,const VkDevice device,const VkRenderPassCreateInfo * create_info,bool rp2_supported,const char * rp1_vuid,const char * rp2_vuid)180*b7893ccfSSadaf Ebrahimi void TestRenderPassCreate(ErrorMonitor *error_monitor, const VkDevice device, const VkRenderPassCreateInfo *create_info,
181*b7893ccfSSadaf Ebrahimi                           bool rp2_supported, const char *rp1_vuid, const char *rp2_vuid) {
182*b7893ccfSSadaf Ebrahimi     VkRenderPass render_pass = VK_NULL_HANDLE;
183*b7893ccfSSadaf Ebrahimi     VkResult err;
184*b7893ccfSSadaf Ebrahimi 
185*b7893ccfSSadaf Ebrahimi     if (rp1_vuid) {
186*b7893ccfSSadaf Ebrahimi         error_monitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, rp1_vuid);
187*b7893ccfSSadaf Ebrahimi         err = vkCreateRenderPass(device, create_info, nullptr, &render_pass);
188*b7893ccfSSadaf Ebrahimi         if (err == VK_SUCCESS) vkDestroyRenderPass(device, render_pass, nullptr);
189*b7893ccfSSadaf Ebrahimi         error_monitor->VerifyFound();
190*b7893ccfSSadaf Ebrahimi     }
191*b7893ccfSSadaf Ebrahimi 
192*b7893ccfSSadaf Ebrahimi     if (rp2_supported && rp2_vuid) {
193*b7893ccfSSadaf Ebrahimi         PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR =
194*b7893ccfSSadaf Ebrahimi             (PFN_vkCreateRenderPass2KHR)vkGetDeviceProcAddr(device, "vkCreateRenderPass2KHR");
195*b7893ccfSSadaf Ebrahimi         safe_VkRenderPassCreateInfo2KHR create_info2;
196*b7893ccfSSadaf Ebrahimi         ConvertVkRenderPassCreateInfoToV2KHR(create_info, &create_info2);
197*b7893ccfSSadaf Ebrahimi 
198*b7893ccfSSadaf Ebrahimi         error_monitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, rp2_vuid);
199*b7893ccfSSadaf Ebrahimi         err = vkCreateRenderPass2KHR(device, create_info2.ptr(), nullptr, &render_pass);
200*b7893ccfSSadaf Ebrahimi         if (err == VK_SUCCESS) vkDestroyRenderPass(device, render_pass, nullptr);
201*b7893ccfSSadaf Ebrahimi         error_monitor->VerifyFound();
202*b7893ccfSSadaf Ebrahimi     }
203*b7893ccfSSadaf Ebrahimi }
204*b7893ccfSSadaf Ebrahimi 
PositiveTestRenderPassCreate(ErrorMonitor * error_monitor,const VkDevice device,const VkRenderPassCreateInfo * create_info,bool rp2_supported)205*b7893ccfSSadaf Ebrahimi void PositiveTestRenderPassCreate(ErrorMonitor *error_monitor, const VkDevice device, const VkRenderPassCreateInfo *create_info,
206*b7893ccfSSadaf Ebrahimi                                   bool rp2_supported) {
207*b7893ccfSSadaf Ebrahimi     VkRenderPass render_pass = VK_NULL_HANDLE;
208*b7893ccfSSadaf Ebrahimi     VkResult err;
209*b7893ccfSSadaf Ebrahimi 
210*b7893ccfSSadaf Ebrahimi     error_monitor->ExpectSuccess();
211*b7893ccfSSadaf Ebrahimi     err = vkCreateRenderPass(device, create_info, nullptr, &render_pass);
212*b7893ccfSSadaf Ebrahimi     if (err == VK_SUCCESS) vkDestroyRenderPass(device, render_pass, nullptr);
213*b7893ccfSSadaf Ebrahimi     error_monitor->VerifyNotFound();
214*b7893ccfSSadaf Ebrahimi 
215*b7893ccfSSadaf Ebrahimi     if (rp2_supported) {
216*b7893ccfSSadaf Ebrahimi         PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR =
217*b7893ccfSSadaf Ebrahimi             (PFN_vkCreateRenderPass2KHR)vkGetDeviceProcAddr(device, "vkCreateRenderPass2KHR");
218*b7893ccfSSadaf Ebrahimi         safe_VkRenderPassCreateInfo2KHR create_info2;
219*b7893ccfSSadaf Ebrahimi         ConvertVkRenderPassCreateInfoToV2KHR(create_info, &create_info2);
220*b7893ccfSSadaf Ebrahimi 
221*b7893ccfSSadaf Ebrahimi         error_monitor->ExpectSuccess();
222*b7893ccfSSadaf Ebrahimi         err = vkCreateRenderPass2KHR(device, create_info2.ptr(), nullptr, &render_pass);
223*b7893ccfSSadaf Ebrahimi         if (err == VK_SUCCESS) vkDestroyRenderPass(device, render_pass, nullptr);
224*b7893ccfSSadaf Ebrahimi         error_monitor->VerifyNotFound();
225*b7893ccfSSadaf Ebrahimi     }
226*b7893ccfSSadaf Ebrahimi }
227*b7893ccfSSadaf Ebrahimi 
TestRenderPass2KHRCreate(ErrorMonitor * error_monitor,const VkDevice device,const VkRenderPassCreateInfo2KHR * create_info,const char * rp2_vuid)228*b7893ccfSSadaf Ebrahimi void TestRenderPass2KHRCreate(ErrorMonitor *error_monitor, const VkDevice device, const VkRenderPassCreateInfo2KHR *create_info,
229*b7893ccfSSadaf Ebrahimi                               const char *rp2_vuid) {
230*b7893ccfSSadaf Ebrahimi     VkRenderPass render_pass = VK_NULL_HANDLE;
231*b7893ccfSSadaf Ebrahimi     VkResult err;
232*b7893ccfSSadaf Ebrahimi     PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR =
233*b7893ccfSSadaf Ebrahimi         (PFN_vkCreateRenderPass2KHR)vkGetDeviceProcAddr(device, "vkCreateRenderPass2KHR");
234*b7893ccfSSadaf Ebrahimi 
235*b7893ccfSSadaf Ebrahimi     error_monitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, rp2_vuid);
236*b7893ccfSSadaf Ebrahimi     err = vkCreateRenderPass2KHR(device, create_info, nullptr, &render_pass);
237*b7893ccfSSadaf Ebrahimi     if (err == VK_SUCCESS) vkDestroyRenderPass(device, render_pass, nullptr);
238*b7893ccfSSadaf Ebrahimi     error_monitor->VerifyFound();
239*b7893ccfSSadaf Ebrahimi }
240*b7893ccfSSadaf Ebrahimi 
TestRenderPassBegin(ErrorMonitor * error_monitor,const VkDevice device,const VkCommandBuffer command_buffer,const VkRenderPassBeginInfo * begin_info,bool rp2Supported,const char * rp1_vuid,const char * rp2_vuid)241*b7893ccfSSadaf Ebrahimi void TestRenderPassBegin(ErrorMonitor *error_monitor, const VkDevice device, const VkCommandBuffer command_buffer,
242*b7893ccfSSadaf Ebrahimi                          const VkRenderPassBeginInfo *begin_info, bool rp2Supported, const char *rp1_vuid, const char *rp2_vuid) {
243*b7893ccfSSadaf Ebrahimi     VkCommandBufferBeginInfo cmd_begin_info = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr,
244*b7893ccfSSadaf Ebrahimi                                                VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
245*b7893ccfSSadaf Ebrahimi 
246*b7893ccfSSadaf Ebrahimi     if (rp1_vuid) {
247*b7893ccfSSadaf Ebrahimi         vkBeginCommandBuffer(command_buffer, &cmd_begin_info);
248*b7893ccfSSadaf Ebrahimi         error_monitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, rp1_vuid);
249*b7893ccfSSadaf Ebrahimi         vkCmdBeginRenderPass(command_buffer, begin_info, VK_SUBPASS_CONTENTS_INLINE);
250*b7893ccfSSadaf Ebrahimi         error_monitor->VerifyFound();
251*b7893ccfSSadaf Ebrahimi         vkResetCommandBuffer(command_buffer, 0);
252*b7893ccfSSadaf Ebrahimi     }
253*b7893ccfSSadaf Ebrahimi     if (rp2Supported && rp2_vuid) {
254*b7893ccfSSadaf Ebrahimi         PFN_vkCmdBeginRenderPass2KHR vkCmdBeginRenderPass2KHR =
255*b7893ccfSSadaf Ebrahimi             (PFN_vkCmdBeginRenderPass2KHR)vkGetDeviceProcAddr(device, "vkCmdBeginRenderPass2KHR");
256*b7893ccfSSadaf Ebrahimi         VkSubpassBeginInfoKHR subpass_begin_info = {VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR, nullptr, VK_SUBPASS_CONTENTS_INLINE};
257*b7893ccfSSadaf Ebrahimi         vkBeginCommandBuffer(command_buffer, &cmd_begin_info);
258*b7893ccfSSadaf Ebrahimi         error_monitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, rp2_vuid);
259*b7893ccfSSadaf Ebrahimi         vkCmdBeginRenderPass2KHR(command_buffer, begin_info, &subpass_begin_info);
260*b7893ccfSSadaf Ebrahimi         error_monitor->VerifyFound();
261*b7893ccfSSadaf Ebrahimi         vkResetCommandBuffer(command_buffer, 0);
262*b7893ccfSSadaf Ebrahimi     }
263*b7893ccfSSadaf Ebrahimi }
264*b7893ccfSSadaf Ebrahimi 
ValidOwnershipTransferOp(ErrorMonitor * monitor,VkCommandBufferObj * cb,VkPipelineStageFlags src_stages,VkPipelineStageFlags dst_stages,const VkBufferMemoryBarrier * buf_barrier,const VkImageMemoryBarrier * img_barrier)265*b7893ccfSSadaf Ebrahimi void ValidOwnershipTransferOp(ErrorMonitor *monitor, VkCommandBufferObj *cb, VkPipelineStageFlags src_stages,
266*b7893ccfSSadaf Ebrahimi                               VkPipelineStageFlags dst_stages, const VkBufferMemoryBarrier *buf_barrier,
267*b7893ccfSSadaf Ebrahimi                               const VkImageMemoryBarrier *img_barrier) {
268*b7893ccfSSadaf Ebrahimi     monitor->ExpectSuccess();
269*b7893ccfSSadaf Ebrahimi     cb->begin();
270*b7893ccfSSadaf Ebrahimi     uint32_t num_buf_barrier = (buf_barrier) ? 1 : 0;
271*b7893ccfSSadaf Ebrahimi     uint32_t num_img_barrier = (img_barrier) ? 1 : 0;
272*b7893ccfSSadaf Ebrahimi     cb->PipelineBarrier(src_stages, dst_stages, 0, 0, nullptr, num_buf_barrier, buf_barrier, num_img_barrier, img_barrier);
273*b7893ccfSSadaf Ebrahimi     cb->end();
274*b7893ccfSSadaf Ebrahimi     cb->QueueCommandBuffer();  // Implicitly waits
275*b7893ccfSSadaf Ebrahimi     monitor->VerifyNotFound();
276*b7893ccfSSadaf Ebrahimi }
277*b7893ccfSSadaf Ebrahimi 
ValidOwnershipTransfer(ErrorMonitor * monitor,VkCommandBufferObj * cb_from,VkCommandBufferObj * cb_to,VkPipelineStageFlags src_stages,VkPipelineStageFlags dst_stages,const VkBufferMemoryBarrier * buf_barrier,const VkImageMemoryBarrier * img_barrier)278*b7893ccfSSadaf Ebrahimi void ValidOwnershipTransfer(ErrorMonitor *monitor, VkCommandBufferObj *cb_from, VkCommandBufferObj *cb_to,
279*b7893ccfSSadaf Ebrahimi                             VkPipelineStageFlags src_stages, VkPipelineStageFlags dst_stages,
280*b7893ccfSSadaf Ebrahimi                             const VkBufferMemoryBarrier *buf_barrier, const VkImageMemoryBarrier *img_barrier) {
281*b7893ccfSSadaf Ebrahimi     ValidOwnershipTransferOp(monitor, cb_from, src_stages, dst_stages, buf_barrier, img_barrier);
282*b7893ccfSSadaf Ebrahimi     ValidOwnershipTransferOp(monitor, cb_to, src_stages, dst_stages, buf_barrier, img_barrier);
283*b7893ccfSSadaf Ebrahimi }
284*b7893ccfSSadaf Ebrahimi 
GPDIFPHelper(VkPhysicalDevice dev,const VkImageCreateInfo * ci,VkImageFormatProperties * limits)285*b7893ccfSSadaf Ebrahimi VkResult GPDIFPHelper(VkPhysicalDevice dev, const VkImageCreateInfo *ci, VkImageFormatProperties *limits) {
286*b7893ccfSSadaf Ebrahimi     VkImageFormatProperties tmp_limits;
287*b7893ccfSSadaf Ebrahimi     limits = limits ? limits : &tmp_limits;
288*b7893ccfSSadaf Ebrahimi     return vkGetPhysicalDeviceImageFormatProperties(dev, ci->format, ci->imageType, ci->tiling, ci->usage, ci->flags, limits);
289*b7893ccfSSadaf Ebrahimi }
290*b7893ccfSSadaf Ebrahimi 
FindFormatLinearWithoutMips(VkPhysicalDevice gpu,VkImageCreateInfo image_ci)291*b7893ccfSSadaf Ebrahimi VkFormat FindFormatLinearWithoutMips(VkPhysicalDevice gpu, VkImageCreateInfo image_ci) {
292*b7893ccfSSadaf Ebrahimi     image_ci.tiling = VK_IMAGE_TILING_LINEAR;
293*b7893ccfSSadaf Ebrahimi 
294*b7893ccfSSadaf Ebrahimi     const VkFormat first_vk_format = static_cast<VkFormat>(1);
295*b7893ccfSSadaf Ebrahimi     const VkFormat last_vk_format = static_cast<VkFormat>(130);  // avoid compressed/feature protected, otherwise 184
296*b7893ccfSSadaf Ebrahimi 
297*b7893ccfSSadaf Ebrahimi     for (VkFormat format = first_vk_format; format <= last_vk_format; format = static_cast<VkFormat>(format + 1)) {
298*b7893ccfSSadaf Ebrahimi         image_ci.format = format;
299*b7893ccfSSadaf Ebrahimi 
300*b7893ccfSSadaf Ebrahimi         // WORKAROUND for dev_sim and mock_icd not containing valid format limits yet
301*b7893ccfSSadaf Ebrahimi         VkFormatProperties format_props;
302*b7893ccfSSadaf Ebrahimi         vkGetPhysicalDeviceFormatProperties(gpu, format, &format_props);
303*b7893ccfSSadaf Ebrahimi         const VkFormatFeatureFlags core_filter = 0x1FFF;
304*b7893ccfSSadaf Ebrahimi         const auto features = (image_ci.tiling == VK_IMAGE_TILING_LINEAR) ? format_props.linearTilingFeatures & core_filter
305*b7893ccfSSadaf Ebrahimi                                                                           : format_props.optimalTilingFeatures & core_filter;
306*b7893ccfSSadaf Ebrahimi         if (!(features & core_filter)) continue;
307*b7893ccfSSadaf Ebrahimi 
308*b7893ccfSSadaf Ebrahimi         VkImageFormatProperties img_limits;
309*b7893ccfSSadaf Ebrahimi         if (VK_SUCCESS == GPDIFPHelper(gpu, &image_ci, &img_limits) && img_limits.maxMipLevels == 1) return format;
310*b7893ccfSSadaf Ebrahimi     }
311*b7893ccfSSadaf Ebrahimi 
312*b7893ccfSSadaf Ebrahimi     return VK_FORMAT_UNDEFINED;
313*b7893ccfSSadaf Ebrahimi }
314*b7893ccfSSadaf Ebrahimi 
FindFormatWithoutSamples(VkPhysicalDevice gpu,VkImageCreateInfo & image_ci)315*b7893ccfSSadaf Ebrahimi bool FindFormatWithoutSamples(VkPhysicalDevice gpu, VkImageCreateInfo &image_ci) {
316*b7893ccfSSadaf Ebrahimi     const VkFormat first_vk_format = static_cast<VkFormat>(1);
317*b7893ccfSSadaf Ebrahimi     const VkFormat last_vk_format = static_cast<VkFormat>(130);  // avoid compressed/feature protected, otherwise 184
318*b7893ccfSSadaf Ebrahimi 
319*b7893ccfSSadaf Ebrahimi     for (VkFormat format = first_vk_format; format <= last_vk_format; format = static_cast<VkFormat>(format + 1)) {
320*b7893ccfSSadaf Ebrahimi         image_ci.format = format;
321*b7893ccfSSadaf Ebrahimi 
322*b7893ccfSSadaf Ebrahimi         // WORKAROUND for dev_sim and mock_icd not containing valid format limits yet
323*b7893ccfSSadaf Ebrahimi         VkFormatProperties format_props;
324*b7893ccfSSadaf Ebrahimi         vkGetPhysicalDeviceFormatProperties(gpu, format, &format_props);
325*b7893ccfSSadaf Ebrahimi         const VkFormatFeatureFlags core_filter = 0x1FFF;
326*b7893ccfSSadaf Ebrahimi         const auto features = (image_ci.tiling == VK_IMAGE_TILING_LINEAR) ? format_props.linearTilingFeatures & core_filter
327*b7893ccfSSadaf Ebrahimi                                                                           : format_props.optimalTilingFeatures & core_filter;
328*b7893ccfSSadaf Ebrahimi         if (!(features & core_filter)) continue;
329*b7893ccfSSadaf Ebrahimi 
330*b7893ccfSSadaf Ebrahimi         for (VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_64_BIT; samples > 0;
331*b7893ccfSSadaf Ebrahimi              samples = static_cast<VkSampleCountFlagBits>(samples >> 1)) {
332*b7893ccfSSadaf Ebrahimi             image_ci.samples = samples;
333*b7893ccfSSadaf Ebrahimi             VkImageFormatProperties img_limits;
334*b7893ccfSSadaf Ebrahimi             if (VK_SUCCESS == GPDIFPHelper(gpu, &image_ci, &img_limits) && !(img_limits.sampleCounts & samples)) return true;
335*b7893ccfSSadaf Ebrahimi         }
336*b7893ccfSSadaf Ebrahimi     }
337*b7893ccfSSadaf Ebrahimi 
338*b7893ccfSSadaf Ebrahimi     return false;
339*b7893ccfSSadaf Ebrahimi }
340*b7893ccfSSadaf Ebrahimi 
FindUnsupportedImage(VkPhysicalDevice gpu,VkImageCreateInfo & image_ci)341*b7893ccfSSadaf Ebrahimi bool FindUnsupportedImage(VkPhysicalDevice gpu, VkImageCreateInfo &image_ci) {
342*b7893ccfSSadaf Ebrahimi     const VkFormat first_vk_format = static_cast<VkFormat>(1);
343*b7893ccfSSadaf Ebrahimi     const VkFormat last_vk_format = static_cast<VkFormat>(130);  // avoid compressed/feature protected, otherwise 184
344*b7893ccfSSadaf Ebrahimi 
345*b7893ccfSSadaf Ebrahimi     const std::vector<VkImageTiling> tilings = {VK_IMAGE_TILING_LINEAR, VK_IMAGE_TILING_OPTIMAL};
346*b7893ccfSSadaf Ebrahimi     for (const auto tiling : tilings) {
347*b7893ccfSSadaf Ebrahimi         image_ci.tiling = tiling;
348*b7893ccfSSadaf Ebrahimi 
349*b7893ccfSSadaf Ebrahimi         for (VkFormat format = first_vk_format; format <= last_vk_format; format = static_cast<VkFormat>(format + 1)) {
350*b7893ccfSSadaf Ebrahimi             image_ci.format = format;
351*b7893ccfSSadaf Ebrahimi 
352*b7893ccfSSadaf Ebrahimi             VkFormatProperties format_props;
353*b7893ccfSSadaf Ebrahimi             vkGetPhysicalDeviceFormatProperties(gpu, format, &format_props);
354*b7893ccfSSadaf Ebrahimi 
355*b7893ccfSSadaf Ebrahimi             const VkFormatFeatureFlags core_filter = 0x1FFF;
356*b7893ccfSSadaf Ebrahimi             const auto features = (tiling == VK_IMAGE_TILING_LINEAR) ? format_props.linearTilingFeatures & core_filter
357*b7893ccfSSadaf Ebrahimi                                                                      : format_props.optimalTilingFeatures & core_filter;
358*b7893ccfSSadaf Ebrahimi             if (!(features & core_filter)) continue;  // We wand supported by features, but not by ImageFormatProperties
359*b7893ccfSSadaf Ebrahimi 
360*b7893ccfSSadaf Ebrahimi             // get as many usage flags as possible
361*b7893ccfSSadaf Ebrahimi             image_ci.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
362*b7893ccfSSadaf Ebrahimi             if (features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) image_ci.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
363*b7893ccfSSadaf Ebrahimi             if (features & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) image_ci.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
364*b7893ccfSSadaf Ebrahimi             if (features & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) image_ci.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
365*b7893ccfSSadaf Ebrahimi             if (features & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
366*b7893ccfSSadaf Ebrahimi                 image_ci.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
367*b7893ccfSSadaf Ebrahimi 
368*b7893ccfSSadaf Ebrahimi             VkImageFormatProperties img_limits;
369*b7893ccfSSadaf Ebrahimi             if (VK_ERROR_FORMAT_NOT_SUPPORTED == GPDIFPHelper(gpu, &image_ci, &img_limits)) {
370*b7893ccfSSadaf Ebrahimi                 return true;
371*b7893ccfSSadaf Ebrahimi             }
372*b7893ccfSSadaf Ebrahimi         }
373*b7893ccfSSadaf Ebrahimi     }
374*b7893ccfSSadaf Ebrahimi 
375*b7893ccfSSadaf Ebrahimi     return false;
376*b7893ccfSSadaf Ebrahimi }
377*b7893ccfSSadaf Ebrahimi 
FindFormatWithoutFeatures(VkPhysicalDevice gpu,VkImageTiling tiling,VkFormatFeatureFlags undesired_features)378*b7893ccfSSadaf Ebrahimi VkFormat FindFormatWithoutFeatures(VkPhysicalDevice gpu, VkImageTiling tiling, VkFormatFeatureFlags undesired_features) {
379*b7893ccfSSadaf Ebrahimi     const VkFormat first_vk_format = static_cast<VkFormat>(1);
380*b7893ccfSSadaf Ebrahimi     const VkFormat last_vk_format = static_cast<VkFormat>(130);  // avoid compressed/feature protected, otherwise 184
381*b7893ccfSSadaf Ebrahimi 
382*b7893ccfSSadaf Ebrahimi     for (VkFormat format = first_vk_format; format <= last_vk_format; format = static_cast<VkFormat>(format + 1)) {
383*b7893ccfSSadaf Ebrahimi         VkFormatProperties format_props;
384*b7893ccfSSadaf Ebrahimi         vkGetPhysicalDeviceFormatProperties(gpu, format, &format_props);
385*b7893ccfSSadaf Ebrahimi 
386*b7893ccfSSadaf Ebrahimi         const VkFormatFeatureFlags core_filter = 0x1FFF;
387*b7893ccfSSadaf Ebrahimi         const auto features = (tiling == VK_IMAGE_TILING_LINEAR) ? format_props.linearTilingFeatures & core_filter
388*b7893ccfSSadaf Ebrahimi                                                                  : format_props.optimalTilingFeatures & core_filter;
389*b7893ccfSSadaf Ebrahimi 
390*b7893ccfSSadaf Ebrahimi         const auto valid_features = features & core_filter;
391*b7893ccfSSadaf Ebrahimi         if (undesired_features == UINT32_MAX) {
392*b7893ccfSSadaf Ebrahimi             if (!valid_features) return format;
393*b7893ccfSSadaf Ebrahimi         } else {
394*b7893ccfSSadaf Ebrahimi             if (valid_features && !(valid_features & undesired_features)) return format;
395*b7893ccfSSadaf Ebrahimi         }
396*b7893ccfSSadaf Ebrahimi     }
397*b7893ccfSSadaf Ebrahimi 
398*b7893ccfSSadaf Ebrahimi     return VK_FORMAT_UNDEFINED;
399*b7893ccfSSadaf Ebrahimi }
400*b7893ccfSSadaf Ebrahimi 
NegHeightViewportTests(VkDeviceObj * m_device,VkCommandBufferObj * m_commandBuffer,ErrorMonitor * m_errorMonitor)401*b7893ccfSSadaf Ebrahimi void NegHeightViewportTests(VkDeviceObj *m_device, VkCommandBufferObj *m_commandBuffer, ErrorMonitor *m_errorMonitor) {
402*b7893ccfSSadaf Ebrahimi     const auto &limits = m_device->props.limits;
403*b7893ccfSSadaf Ebrahimi 
404*b7893ccfSSadaf Ebrahimi     m_commandBuffer->begin();
405*b7893ccfSSadaf Ebrahimi 
406*b7893ccfSSadaf Ebrahimi     using std::vector;
407*b7893ccfSSadaf Ebrahimi     struct TestCase {
408*b7893ccfSSadaf Ebrahimi         VkViewport vp;
409*b7893ccfSSadaf Ebrahimi         vector<std::string> vuids;
410*b7893ccfSSadaf Ebrahimi     };
411*b7893ccfSSadaf Ebrahimi 
412*b7893ccfSSadaf Ebrahimi     // not necessarily boundary values (unspecified cast rounding), but guaranteed to be over limit
413*b7893ccfSSadaf Ebrahimi     const auto one_before_min_h = NearestSmaller(-static_cast<float>(limits.maxViewportDimensions[1]));
414*b7893ccfSSadaf Ebrahimi     const auto one_past_max_h = NearestGreater(static_cast<float>(limits.maxViewportDimensions[1]));
415*b7893ccfSSadaf Ebrahimi 
416*b7893ccfSSadaf Ebrahimi     const auto min_bound = limits.viewportBoundsRange[0];
417*b7893ccfSSadaf Ebrahimi     const auto max_bound = limits.viewportBoundsRange[1];
418*b7893ccfSSadaf Ebrahimi     const auto one_before_min_bound = NearestSmaller(min_bound);
419*b7893ccfSSadaf Ebrahimi     const auto one_past_max_bound = NearestGreater(max_bound);
420*b7893ccfSSadaf Ebrahimi 
421*b7893ccfSSadaf Ebrahimi     const vector<TestCase> test_cases = {{{0.0, 0.0, 64.0, one_before_min_h, 0.0, 1.0}, {"VUID-VkViewport-height-01773"}},
422*b7893ccfSSadaf Ebrahimi                                          {{0.0, 0.0, 64.0, one_past_max_h, 0.0, 1.0}, {"VUID-VkViewport-height-01773"}},
423*b7893ccfSSadaf Ebrahimi                                          {{0.0, 0.0, 64.0, NAN, 0.0, 1.0}, {"VUID-VkViewport-height-01773"}},
424*b7893ccfSSadaf Ebrahimi                                          {{0.0, one_before_min_bound, 64.0, 1.0, 0.0, 1.0}, {"VUID-VkViewport-y-01775"}},
425*b7893ccfSSadaf Ebrahimi                                          {{0.0, one_past_max_bound, 64.0, -1.0, 0.0, 1.0}, {"VUID-VkViewport-y-01776"}},
426*b7893ccfSSadaf Ebrahimi                                          {{0.0, min_bound, 64.0, -1.0, 0.0, 1.0}, {"VUID-VkViewport-y-01777"}},
427*b7893ccfSSadaf Ebrahimi                                          {{0.0, max_bound, 64.0, 1.0, 0.0, 1.0}, {"VUID-VkViewport-y-01233"}}};
428*b7893ccfSSadaf Ebrahimi 
429*b7893ccfSSadaf Ebrahimi     for (const auto &test_case : test_cases) {
430*b7893ccfSSadaf Ebrahimi         for (const auto vuid : test_case.vuids) {
431*b7893ccfSSadaf Ebrahimi             if (vuid == "VUID-Undefined")
432*b7893ccfSSadaf Ebrahimi                 m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
433*b7893ccfSSadaf Ebrahimi                                                      "is less than VkPhysicalDeviceLimits::viewportBoundsRange[0]");
434*b7893ccfSSadaf Ebrahimi             else
435*b7893ccfSSadaf Ebrahimi                 m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, vuid);
436*b7893ccfSSadaf Ebrahimi         }
437*b7893ccfSSadaf Ebrahimi         vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &test_case.vp);
438*b7893ccfSSadaf Ebrahimi         m_errorMonitor->VerifyFound();
439*b7893ccfSSadaf Ebrahimi     }
440*b7893ccfSSadaf Ebrahimi }
441*b7893ccfSSadaf Ebrahimi 
CreateSamplerTest(VkLayerTest & test,const VkSamplerCreateInfo * pCreateInfo,std::string code)442*b7893ccfSSadaf Ebrahimi void CreateSamplerTest(VkLayerTest &test, const VkSamplerCreateInfo *pCreateInfo, std::string code) {
443*b7893ccfSSadaf Ebrahimi     VkResult err;
444*b7893ccfSSadaf Ebrahimi     VkSampler sampler = VK_NULL_HANDLE;
445*b7893ccfSSadaf Ebrahimi     if (code.length())
446*b7893ccfSSadaf Ebrahimi         test.Monitor()->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT, code);
447*b7893ccfSSadaf Ebrahimi     else
448*b7893ccfSSadaf Ebrahimi         test.Monitor()->ExpectSuccess();
449*b7893ccfSSadaf Ebrahimi 
450*b7893ccfSSadaf Ebrahimi     err = vkCreateSampler(test.device(), pCreateInfo, NULL, &sampler);
451*b7893ccfSSadaf Ebrahimi     if (code.length())
452*b7893ccfSSadaf Ebrahimi         test.Monitor()->VerifyFound();
453*b7893ccfSSadaf Ebrahimi     else
454*b7893ccfSSadaf Ebrahimi         test.Monitor()->VerifyNotFound();
455*b7893ccfSSadaf Ebrahimi 
456*b7893ccfSSadaf Ebrahimi     if (VK_SUCCESS == err) {
457*b7893ccfSSadaf Ebrahimi         vkDestroySampler(test.device(), sampler, NULL);
458*b7893ccfSSadaf Ebrahimi     }
459*b7893ccfSSadaf Ebrahimi }
460*b7893ccfSSadaf Ebrahimi 
CreateBufferTest(VkLayerTest & test,const VkBufferCreateInfo * pCreateInfo,std::string code)461*b7893ccfSSadaf Ebrahimi void CreateBufferTest(VkLayerTest &test, const VkBufferCreateInfo *pCreateInfo, std::string code) {
462*b7893ccfSSadaf Ebrahimi     VkResult err;
463*b7893ccfSSadaf Ebrahimi     VkBuffer buffer = VK_NULL_HANDLE;
464*b7893ccfSSadaf Ebrahimi     if (code.length())
465*b7893ccfSSadaf Ebrahimi         test.Monitor()->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, code);
466*b7893ccfSSadaf Ebrahimi     else
467*b7893ccfSSadaf Ebrahimi         test.Monitor()->ExpectSuccess();
468*b7893ccfSSadaf Ebrahimi 
469*b7893ccfSSadaf Ebrahimi     err = vkCreateBuffer(test.device(), pCreateInfo, NULL, &buffer);
470*b7893ccfSSadaf Ebrahimi     if (code.length())
471*b7893ccfSSadaf Ebrahimi         test.Monitor()->VerifyFound();
472*b7893ccfSSadaf Ebrahimi     else
473*b7893ccfSSadaf Ebrahimi         test.Monitor()->VerifyNotFound();
474*b7893ccfSSadaf Ebrahimi 
475*b7893ccfSSadaf Ebrahimi     if (VK_SUCCESS == err) {
476*b7893ccfSSadaf Ebrahimi         vkDestroyBuffer(test.device(), buffer, NULL);
477*b7893ccfSSadaf Ebrahimi     }
478*b7893ccfSSadaf Ebrahimi }
479*b7893ccfSSadaf Ebrahimi 
CreateImageTest(VkLayerTest & test,const VkImageCreateInfo * pCreateInfo,std::string code)480*b7893ccfSSadaf Ebrahimi void CreateImageTest(VkLayerTest &test, const VkImageCreateInfo *pCreateInfo, std::string code) {
481*b7893ccfSSadaf Ebrahimi     VkResult err;
482*b7893ccfSSadaf Ebrahimi     VkImage image = VK_NULL_HANDLE;
483*b7893ccfSSadaf Ebrahimi     if (code.length())
484*b7893ccfSSadaf Ebrahimi         test.Monitor()->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, code);
485*b7893ccfSSadaf Ebrahimi     else
486*b7893ccfSSadaf Ebrahimi         test.Monitor()->ExpectSuccess();
487*b7893ccfSSadaf Ebrahimi 
488*b7893ccfSSadaf Ebrahimi     err = vkCreateImage(test.device(), pCreateInfo, NULL, &image);
489*b7893ccfSSadaf Ebrahimi     if (code.length())
490*b7893ccfSSadaf Ebrahimi         test.Monitor()->VerifyFound();
491*b7893ccfSSadaf Ebrahimi     else
492*b7893ccfSSadaf Ebrahimi         test.Monitor()->VerifyNotFound();
493*b7893ccfSSadaf Ebrahimi 
494*b7893ccfSSadaf Ebrahimi     if (VK_SUCCESS == err) {
495*b7893ccfSSadaf Ebrahimi         vkDestroyImage(test.device(), image, NULL);
496*b7893ccfSSadaf Ebrahimi     }
497*b7893ccfSSadaf Ebrahimi }
498*b7893ccfSSadaf Ebrahimi 
CreateBufferViewTest(VkLayerTest & test,const VkBufferViewCreateInfo * pCreateInfo,const std::vector<std::string> & codes)499*b7893ccfSSadaf Ebrahimi void CreateBufferViewTest(VkLayerTest &test, const VkBufferViewCreateInfo *pCreateInfo, const std::vector<std::string> &codes) {
500*b7893ccfSSadaf Ebrahimi     VkResult err;
501*b7893ccfSSadaf Ebrahimi     VkBufferView view = VK_NULL_HANDLE;
502*b7893ccfSSadaf Ebrahimi     if (codes.size())
503*b7893ccfSSadaf Ebrahimi         std::for_each(codes.begin(), codes.end(),
504*b7893ccfSSadaf Ebrahimi                       [&](const std::string &s) { test.Monitor()->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, s); });
505*b7893ccfSSadaf Ebrahimi     else
506*b7893ccfSSadaf Ebrahimi         test.Monitor()->ExpectSuccess();
507*b7893ccfSSadaf Ebrahimi 
508*b7893ccfSSadaf Ebrahimi     err = vkCreateBufferView(test.device(), pCreateInfo, NULL, &view);
509*b7893ccfSSadaf Ebrahimi     if (codes.size())
510*b7893ccfSSadaf Ebrahimi         test.Monitor()->VerifyFound();
511*b7893ccfSSadaf Ebrahimi     else
512*b7893ccfSSadaf Ebrahimi         test.Monitor()->VerifyNotFound();
513*b7893ccfSSadaf Ebrahimi 
514*b7893ccfSSadaf Ebrahimi     if (VK_SUCCESS == err) {
515*b7893ccfSSadaf Ebrahimi         vkDestroyBufferView(test.device(), view, NULL);
516*b7893ccfSSadaf Ebrahimi     }
517*b7893ccfSSadaf Ebrahimi }
518*b7893ccfSSadaf Ebrahimi 
CreateImageViewTest(VkLayerTest & test,const VkImageViewCreateInfo * pCreateInfo,std::string code)519*b7893ccfSSadaf Ebrahimi void CreateImageViewTest(VkLayerTest &test, const VkImageViewCreateInfo *pCreateInfo, std::string code) {
520*b7893ccfSSadaf Ebrahimi     VkResult err;
521*b7893ccfSSadaf Ebrahimi     VkImageView view = VK_NULL_HANDLE;
522*b7893ccfSSadaf Ebrahimi     if (code.length())
523*b7893ccfSSadaf Ebrahimi         test.Monitor()->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, code);
524*b7893ccfSSadaf Ebrahimi     else
525*b7893ccfSSadaf Ebrahimi         test.Monitor()->ExpectSuccess();
526*b7893ccfSSadaf Ebrahimi 
527*b7893ccfSSadaf Ebrahimi     err = vkCreateImageView(test.device(), pCreateInfo, NULL, &view);
528*b7893ccfSSadaf Ebrahimi     if (code.length())
529*b7893ccfSSadaf Ebrahimi         test.Monitor()->VerifyFound();
530*b7893ccfSSadaf Ebrahimi     else
531*b7893ccfSSadaf Ebrahimi         test.Monitor()->VerifyNotFound();
532*b7893ccfSSadaf Ebrahimi 
533*b7893ccfSSadaf Ebrahimi     if (VK_SUCCESS == err) {
534*b7893ccfSSadaf Ebrahimi         vkDestroyImageView(test.device(), view, NULL);
535*b7893ccfSSadaf Ebrahimi     }
536*b7893ccfSSadaf Ebrahimi }
537*b7893ccfSSadaf Ebrahimi 
SafeSaneSamplerCreateInfo()538*b7893ccfSSadaf Ebrahimi VkSamplerCreateInfo SafeSaneSamplerCreateInfo() {
539*b7893ccfSSadaf Ebrahimi     VkSamplerCreateInfo sampler_create_info = {};
540*b7893ccfSSadaf Ebrahimi     sampler_create_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
541*b7893ccfSSadaf Ebrahimi     sampler_create_info.pNext = nullptr;
542*b7893ccfSSadaf Ebrahimi     sampler_create_info.magFilter = VK_FILTER_NEAREST;
543*b7893ccfSSadaf Ebrahimi     sampler_create_info.minFilter = VK_FILTER_NEAREST;
544*b7893ccfSSadaf Ebrahimi     sampler_create_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
545*b7893ccfSSadaf Ebrahimi     sampler_create_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
546*b7893ccfSSadaf Ebrahimi     sampler_create_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
547*b7893ccfSSadaf Ebrahimi     sampler_create_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
548*b7893ccfSSadaf Ebrahimi     sampler_create_info.mipLodBias = 0.0;
549*b7893ccfSSadaf Ebrahimi     sampler_create_info.anisotropyEnable = VK_FALSE;
550*b7893ccfSSadaf Ebrahimi     sampler_create_info.maxAnisotropy = 1.0;
551*b7893ccfSSadaf Ebrahimi     sampler_create_info.compareEnable = VK_FALSE;
552*b7893ccfSSadaf Ebrahimi     sampler_create_info.compareOp = VK_COMPARE_OP_NEVER;
553*b7893ccfSSadaf Ebrahimi     sampler_create_info.minLod = 0.0;
554*b7893ccfSSadaf Ebrahimi     sampler_create_info.maxLod = 16.0;
555*b7893ccfSSadaf Ebrahimi     sampler_create_info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
556*b7893ccfSSadaf Ebrahimi     sampler_create_info.unnormalizedCoordinates = VK_FALSE;
557*b7893ccfSSadaf Ebrahimi 
558*b7893ccfSSadaf Ebrahimi     return sampler_create_info;
559*b7893ccfSSadaf Ebrahimi }
560*b7893ccfSSadaf Ebrahimi 
SafeSaneImageViewCreateInfo(VkImage image,VkFormat format,VkImageAspectFlags aspect_mask)561*b7893ccfSSadaf Ebrahimi VkImageViewCreateInfo SafeSaneImageViewCreateInfo(VkImage image, VkFormat format, VkImageAspectFlags aspect_mask) {
562*b7893ccfSSadaf Ebrahimi     VkImageViewCreateInfo image_view_create_info = {};
563*b7893ccfSSadaf Ebrahimi     image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
564*b7893ccfSSadaf Ebrahimi     image_view_create_info.image = image;
565*b7893ccfSSadaf Ebrahimi     image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
566*b7893ccfSSadaf Ebrahimi     image_view_create_info.format = format;
567*b7893ccfSSadaf Ebrahimi     image_view_create_info.subresourceRange.layerCount = 1;
568*b7893ccfSSadaf Ebrahimi     image_view_create_info.subresourceRange.baseMipLevel = 0;
569*b7893ccfSSadaf Ebrahimi     image_view_create_info.subresourceRange.levelCount = 1;
570*b7893ccfSSadaf Ebrahimi     image_view_create_info.subresourceRange.aspectMask = aspect_mask;
571*b7893ccfSSadaf Ebrahimi 
572*b7893ccfSSadaf Ebrahimi     return image_view_create_info;
573*b7893ccfSSadaf Ebrahimi }
574*b7893ccfSSadaf Ebrahimi 
SafeSaneImageViewCreateInfo(const VkImageObj & image,VkFormat format,VkImageAspectFlags aspect_mask)575*b7893ccfSSadaf Ebrahimi VkImageViewCreateInfo SafeSaneImageViewCreateInfo(const VkImageObj &image, VkFormat format, VkImageAspectFlags aspect_mask) {
576*b7893ccfSSadaf Ebrahimi     return SafeSaneImageViewCreateInfo(image.handle(), format, aspect_mask);
577*b7893ccfSSadaf Ebrahimi }
578*b7893ccfSSadaf Ebrahimi 
CheckCreateRenderPass2Support(VkRenderFramework * renderFramework,std::vector<const char * > & device_extension_names)579*b7893ccfSSadaf Ebrahimi bool CheckCreateRenderPass2Support(VkRenderFramework *renderFramework, std::vector<const char *> &device_extension_names) {
580*b7893ccfSSadaf Ebrahimi     if (renderFramework->DeviceExtensionSupported(renderFramework->gpu(), nullptr, VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME)) {
581*b7893ccfSSadaf Ebrahimi         device_extension_names.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME);
582*b7893ccfSSadaf Ebrahimi         device_extension_names.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME);
583*b7893ccfSSadaf Ebrahimi         device_extension_names.push_back(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
584*b7893ccfSSadaf Ebrahimi         return true;
585*b7893ccfSSadaf Ebrahimi     }
586*b7893ccfSSadaf Ebrahimi     return false;
587*b7893ccfSSadaf Ebrahimi }
588*b7893ccfSSadaf Ebrahimi 
CheckDescriptorIndexingSupportAndInitFramework(VkRenderFramework * renderFramework,std::vector<const char * > & instance_extension_names,std::vector<const char * > & device_extension_names,VkValidationFeaturesEXT * features,void * userData)589*b7893ccfSSadaf Ebrahimi bool CheckDescriptorIndexingSupportAndInitFramework(VkRenderFramework *renderFramework,
590*b7893ccfSSadaf Ebrahimi                                                     std::vector<const char *> &instance_extension_names,
591*b7893ccfSSadaf Ebrahimi                                                     std::vector<const char *> &device_extension_names,
592*b7893ccfSSadaf Ebrahimi                                                     VkValidationFeaturesEXT *features, void *userData) {
593*b7893ccfSSadaf Ebrahimi     bool descriptor_indexing = renderFramework->InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
594*b7893ccfSSadaf Ebrahimi     if (descriptor_indexing) {
595*b7893ccfSSadaf Ebrahimi         instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
596*b7893ccfSSadaf Ebrahimi     }
597*b7893ccfSSadaf Ebrahimi     renderFramework->InitFramework(myDbgFunc, userData, features);
598*b7893ccfSSadaf Ebrahimi     descriptor_indexing = descriptor_indexing && renderFramework->DeviceExtensionSupported(renderFramework->gpu(), nullptr,
599*b7893ccfSSadaf Ebrahimi                                                                                            VK_KHR_MAINTENANCE3_EXTENSION_NAME);
600*b7893ccfSSadaf Ebrahimi     descriptor_indexing = descriptor_indexing && renderFramework->DeviceExtensionSupported(
601*b7893ccfSSadaf Ebrahimi                                                      renderFramework->gpu(), nullptr, VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
602*b7893ccfSSadaf Ebrahimi     if (descriptor_indexing) {
603*b7893ccfSSadaf Ebrahimi         device_extension_names.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME);
604*b7893ccfSSadaf Ebrahimi         device_extension_names.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
605*b7893ccfSSadaf Ebrahimi         return true;
606*b7893ccfSSadaf Ebrahimi     }
607*b7893ccfSSadaf Ebrahimi     return false;
608*b7893ccfSSadaf Ebrahimi }
609*b7893ccfSSadaf Ebrahimi 
ErrorMonitor()610*b7893ccfSSadaf Ebrahimi ErrorMonitor::ErrorMonitor() {
611*b7893ccfSSadaf Ebrahimi     test_platform_thread_create_mutex(&mutex_);
612*b7893ccfSSadaf Ebrahimi     test_platform_thread_lock_mutex(&mutex_);
613*b7893ccfSSadaf Ebrahimi     Reset();
614*b7893ccfSSadaf Ebrahimi     test_platform_thread_unlock_mutex(&mutex_);
615*b7893ccfSSadaf Ebrahimi }
616*b7893ccfSSadaf Ebrahimi 
~ErrorMonitor()617*b7893ccfSSadaf Ebrahimi ErrorMonitor::~ErrorMonitor() { test_platform_thread_delete_mutex(&mutex_); }
618*b7893ccfSSadaf Ebrahimi 
Reset()619*b7893ccfSSadaf Ebrahimi void ErrorMonitor::Reset() {
620*b7893ccfSSadaf Ebrahimi     message_flags_ = VK_DEBUG_REPORT_ERROR_BIT_EXT;
621*b7893ccfSSadaf Ebrahimi     bailout_ = NULL;
622*b7893ccfSSadaf Ebrahimi     message_found_ = VK_FALSE;
623*b7893ccfSSadaf Ebrahimi     failure_message_strings_.clear();
624*b7893ccfSSadaf Ebrahimi     desired_message_strings_.clear();
625*b7893ccfSSadaf Ebrahimi     ignore_message_strings_.clear();
626*b7893ccfSSadaf Ebrahimi     other_messages_.clear();
627*b7893ccfSSadaf Ebrahimi }
628*b7893ccfSSadaf Ebrahimi 
SetDesiredFailureMsg(const VkFlags msgFlags,const std::string msg)629*b7893ccfSSadaf Ebrahimi void ErrorMonitor::SetDesiredFailureMsg(const VkFlags msgFlags, const std::string msg) {
630*b7893ccfSSadaf Ebrahimi     SetDesiredFailureMsg(msgFlags, msg.c_str());
631*b7893ccfSSadaf Ebrahimi }
632*b7893ccfSSadaf Ebrahimi 
SetDesiredFailureMsg(const VkFlags msgFlags,const char * const msgString)633*b7893ccfSSadaf Ebrahimi void ErrorMonitor::SetDesiredFailureMsg(const VkFlags msgFlags, const char *const msgString) {
634*b7893ccfSSadaf Ebrahimi     test_platform_thread_lock_mutex(&mutex_);
635*b7893ccfSSadaf Ebrahimi     desired_message_strings_.insert(msgString);
636*b7893ccfSSadaf Ebrahimi     message_flags_ |= msgFlags;
637*b7893ccfSSadaf Ebrahimi     test_platform_thread_unlock_mutex(&mutex_);
638*b7893ccfSSadaf Ebrahimi }
639*b7893ccfSSadaf Ebrahimi 
SetUnexpectedError(const char * const msg)640*b7893ccfSSadaf Ebrahimi void ErrorMonitor::SetUnexpectedError(const char *const msg) {
641*b7893ccfSSadaf Ebrahimi     test_platform_thread_lock_mutex(&mutex_);
642*b7893ccfSSadaf Ebrahimi 
643*b7893ccfSSadaf Ebrahimi     ignore_message_strings_.emplace_back(msg);
644*b7893ccfSSadaf Ebrahimi 
645*b7893ccfSSadaf Ebrahimi     test_platform_thread_unlock_mutex(&mutex_);
646*b7893ccfSSadaf Ebrahimi }
647*b7893ccfSSadaf Ebrahimi 
CheckForDesiredMsg(const char * const msgString)648*b7893ccfSSadaf Ebrahimi VkBool32 ErrorMonitor::CheckForDesiredMsg(const char *const msgString) {
649*b7893ccfSSadaf Ebrahimi     VkBool32 result = VK_FALSE;
650*b7893ccfSSadaf Ebrahimi     test_platform_thread_lock_mutex(&mutex_);
651*b7893ccfSSadaf Ebrahimi     if (bailout_ != nullptr) {
652*b7893ccfSSadaf Ebrahimi         *bailout_ = true;
653*b7893ccfSSadaf Ebrahimi     }
654*b7893ccfSSadaf Ebrahimi     string errorString(msgString);
655*b7893ccfSSadaf Ebrahimi     bool found_expected = false;
656*b7893ccfSSadaf Ebrahimi 
657*b7893ccfSSadaf Ebrahimi     if (!IgnoreMessage(errorString)) {
658*b7893ccfSSadaf Ebrahimi         for (auto desired_msg_it = desired_message_strings_.begin(); desired_msg_it != desired_message_strings_.end();
659*b7893ccfSSadaf Ebrahimi              ++desired_msg_it) {
660*b7893ccfSSadaf Ebrahimi             if ((*desired_msg_it).length() == 0) {
661*b7893ccfSSadaf Ebrahimi                 // An empty desired_msg string "" indicates a positive test - not expecting an error.
662*b7893ccfSSadaf Ebrahimi                 // Return true to avoid calling layers/driver with this error.
663*b7893ccfSSadaf Ebrahimi                 // And don't erase the "" string, so it remains if another error is found.
664*b7893ccfSSadaf Ebrahimi                 result = VK_TRUE;
665*b7893ccfSSadaf Ebrahimi                 found_expected = true;
666*b7893ccfSSadaf Ebrahimi                 message_found_ = true;
667*b7893ccfSSadaf Ebrahimi                 failure_message_strings_.insert(errorString);
668*b7893ccfSSadaf Ebrahimi             } else if (errorString.find(*desired_msg_it) != string::npos) {
669*b7893ccfSSadaf Ebrahimi                 found_expected = true;
670*b7893ccfSSadaf Ebrahimi                 failure_message_strings_.insert(errorString);
671*b7893ccfSSadaf Ebrahimi                 message_found_ = true;
672*b7893ccfSSadaf Ebrahimi                 result = VK_TRUE;
673*b7893ccfSSadaf Ebrahimi                 // Remove a maximum of one failure message from the set
674*b7893ccfSSadaf Ebrahimi                 // Multiset mutation is acceptable because `break` causes flow of control to exit the for loop
675*b7893ccfSSadaf Ebrahimi                 desired_message_strings_.erase(desired_msg_it);
676*b7893ccfSSadaf Ebrahimi                 break;
677*b7893ccfSSadaf Ebrahimi             }
678*b7893ccfSSadaf Ebrahimi         }
679*b7893ccfSSadaf Ebrahimi 
680*b7893ccfSSadaf Ebrahimi         if (!found_expected) {
681*b7893ccfSSadaf Ebrahimi             printf("Unexpected: %s\n", msgString);
682*b7893ccfSSadaf Ebrahimi             other_messages_.push_back(errorString);
683*b7893ccfSSadaf Ebrahimi         }
684*b7893ccfSSadaf Ebrahimi     }
685*b7893ccfSSadaf Ebrahimi 
686*b7893ccfSSadaf Ebrahimi     test_platform_thread_unlock_mutex(&mutex_);
687*b7893ccfSSadaf Ebrahimi     return result;
688*b7893ccfSSadaf Ebrahimi }
689*b7893ccfSSadaf Ebrahimi 
GetOtherFailureMsgs() const690*b7893ccfSSadaf Ebrahimi vector<string> ErrorMonitor::GetOtherFailureMsgs() const { return other_messages_; }
691*b7893ccfSSadaf Ebrahimi 
GetMessageFlags() const692*b7893ccfSSadaf Ebrahimi VkDebugReportFlagsEXT ErrorMonitor::GetMessageFlags() const { return message_flags_; }
693*b7893ccfSSadaf Ebrahimi 
AnyDesiredMsgFound() const694*b7893ccfSSadaf Ebrahimi bool ErrorMonitor::AnyDesiredMsgFound() const { return message_found_; }
695*b7893ccfSSadaf Ebrahimi 
AllDesiredMsgsFound() const696*b7893ccfSSadaf Ebrahimi bool ErrorMonitor::AllDesiredMsgsFound() const { return desired_message_strings_.empty(); }
697*b7893ccfSSadaf Ebrahimi 
SetError(const char * const errorString)698*b7893ccfSSadaf Ebrahimi void ErrorMonitor::SetError(const char *const errorString) {
699*b7893ccfSSadaf Ebrahimi     message_found_ = true;
700*b7893ccfSSadaf Ebrahimi     failure_message_strings_.insert(errorString);
701*b7893ccfSSadaf Ebrahimi }
702*b7893ccfSSadaf Ebrahimi 
SetBailout(bool * bailout)703*b7893ccfSSadaf Ebrahimi void ErrorMonitor::SetBailout(bool *bailout) { bailout_ = bailout; }
704*b7893ccfSSadaf Ebrahimi 
DumpFailureMsgs() const705*b7893ccfSSadaf Ebrahimi void ErrorMonitor::DumpFailureMsgs() const {
706*b7893ccfSSadaf Ebrahimi     vector<string> otherMsgs = GetOtherFailureMsgs();
707*b7893ccfSSadaf Ebrahimi     if (otherMsgs.size()) {
708*b7893ccfSSadaf Ebrahimi         cout << "Other error messages logged for this test were:" << endl;
709*b7893ccfSSadaf Ebrahimi         for (auto iter = otherMsgs.begin(); iter != otherMsgs.end(); iter++) {
710*b7893ccfSSadaf Ebrahimi             cout << "     " << *iter << endl;
711*b7893ccfSSadaf Ebrahimi         }
712*b7893ccfSSadaf Ebrahimi     }
713*b7893ccfSSadaf Ebrahimi }
714*b7893ccfSSadaf Ebrahimi 
ExpectSuccess(VkDebugReportFlagsEXT const message_flag_mask)715*b7893ccfSSadaf Ebrahimi void ErrorMonitor::ExpectSuccess(VkDebugReportFlagsEXT const message_flag_mask) {
716*b7893ccfSSadaf Ebrahimi     // Match ANY message matching specified type
717*b7893ccfSSadaf Ebrahimi     SetDesiredFailureMsg(message_flag_mask, "");
718*b7893ccfSSadaf Ebrahimi     message_flags_ = message_flag_mask;  // override mask handling in SetDesired...
719*b7893ccfSSadaf Ebrahimi }
720*b7893ccfSSadaf Ebrahimi 
VerifyFound()721*b7893ccfSSadaf Ebrahimi void ErrorMonitor::VerifyFound() {
722*b7893ccfSSadaf Ebrahimi     // Not receiving expected message(s) is a failure. /Before/ throwing, dump any other messages
723*b7893ccfSSadaf Ebrahimi     if (!AllDesiredMsgsFound()) {
724*b7893ccfSSadaf Ebrahimi         DumpFailureMsgs();
725*b7893ccfSSadaf Ebrahimi         for (const auto desired_msg : desired_message_strings_) {
726*b7893ccfSSadaf Ebrahimi             ADD_FAILURE() << "Did not receive expected error '" << desired_msg << "'";
727*b7893ccfSSadaf Ebrahimi         }
728*b7893ccfSSadaf Ebrahimi     } else if (GetOtherFailureMsgs().size() > 0) {
729*b7893ccfSSadaf Ebrahimi         // Fail test case for any unexpected errors
730*b7893ccfSSadaf Ebrahimi #if defined(ANDROID)
731*b7893ccfSSadaf Ebrahimi         // This will get unexpected errors into the adb log
732*b7893ccfSSadaf Ebrahimi         for (auto msg : other_messages_) {
733*b7893ccfSSadaf Ebrahimi             __android_log_print(ANDROID_LOG_INFO, "VulkanLayerValidationTests", "[ UNEXPECTED_ERR ] '%s'", msg.c_str());
734*b7893ccfSSadaf Ebrahimi         }
735*b7893ccfSSadaf Ebrahimi #else
736*b7893ccfSSadaf Ebrahimi         ADD_FAILURE() << "Received unexpected error(s).";
737*b7893ccfSSadaf Ebrahimi #endif
738*b7893ccfSSadaf Ebrahimi     }
739*b7893ccfSSadaf Ebrahimi     Reset();
740*b7893ccfSSadaf Ebrahimi }
741*b7893ccfSSadaf Ebrahimi 
VerifyNotFound()742*b7893ccfSSadaf Ebrahimi void ErrorMonitor::VerifyNotFound() {
743*b7893ccfSSadaf Ebrahimi     // ExpectSuccess() configured us to match anything. Any error is a failure.
744*b7893ccfSSadaf Ebrahimi     if (AnyDesiredMsgFound()) {
745*b7893ccfSSadaf Ebrahimi         DumpFailureMsgs();
746*b7893ccfSSadaf Ebrahimi         for (const auto msg : failure_message_strings_) {
747*b7893ccfSSadaf Ebrahimi             ADD_FAILURE() << "Expected to succeed but got error: " << msg;
748*b7893ccfSSadaf Ebrahimi         }
749*b7893ccfSSadaf Ebrahimi     } else if (GetOtherFailureMsgs().size() > 0) {
750*b7893ccfSSadaf Ebrahimi         // Fail test case for any unexpected errors
751*b7893ccfSSadaf Ebrahimi #if defined(ANDROID)
752*b7893ccfSSadaf Ebrahimi         // This will get unexpected errors into the adb log
753*b7893ccfSSadaf Ebrahimi         for (auto msg : other_messages_) {
754*b7893ccfSSadaf Ebrahimi             __android_log_print(ANDROID_LOG_INFO, "VulkanLayerValidationTests", "[ UNEXPECTED_ERR ] '%s'", msg.c_str());
755*b7893ccfSSadaf Ebrahimi         }
756*b7893ccfSSadaf Ebrahimi #else
757*b7893ccfSSadaf Ebrahimi         ADD_FAILURE() << "Received unexpected error(s).";
758*b7893ccfSSadaf Ebrahimi #endif
759*b7893ccfSSadaf Ebrahimi     }
760*b7893ccfSSadaf Ebrahimi     Reset();
761*b7893ccfSSadaf Ebrahimi }
762*b7893ccfSSadaf Ebrahimi 
IgnoreMessage(std::string const & msg) const763*b7893ccfSSadaf Ebrahimi bool ErrorMonitor::IgnoreMessage(std::string const &msg) const {
764*b7893ccfSSadaf Ebrahimi     if (ignore_message_strings_.empty()) {
765*b7893ccfSSadaf Ebrahimi         return false;
766*b7893ccfSSadaf Ebrahimi     }
767*b7893ccfSSadaf Ebrahimi 
768*b7893ccfSSadaf Ebrahimi     return std::find_if(ignore_message_strings_.begin(), ignore_message_strings_.end(), [&msg](std::string const &str) {
769*b7893ccfSSadaf Ebrahimi                return msg.find(str) != std::string::npos;
770*b7893ccfSSadaf Ebrahimi            }) != ignore_message_strings_.end();
771*b7893ccfSSadaf Ebrahimi }
772*b7893ccfSSadaf Ebrahimi 
VKTriangleTest(BsoFailSelect failCase)773*b7893ccfSSadaf Ebrahimi void VkLayerTest::VKTriangleTest(BsoFailSelect failCase) {
774*b7893ccfSSadaf Ebrahimi     ASSERT_TRUE(m_device && m_device->initialized());  // VKTriangleTest assumes Init() has finished
775*b7893ccfSSadaf Ebrahimi 
776*b7893ccfSSadaf Ebrahimi     ASSERT_NO_FATAL_FAILURE(InitViewport());
777*b7893ccfSSadaf Ebrahimi 
778*b7893ccfSSadaf Ebrahimi     VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
779*b7893ccfSSadaf Ebrahimi     VkShaderObj ps(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this);
780*b7893ccfSSadaf Ebrahimi 
781*b7893ccfSSadaf Ebrahimi     VkPipelineObj pipelineobj(m_device);
782*b7893ccfSSadaf Ebrahimi     pipelineobj.AddDefaultColorAttachment();
783*b7893ccfSSadaf Ebrahimi     pipelineobj.AddShader(&vs);
784*b7893ccfSSadaf Ebrahimi     pipelineobj.AddShader(&ps);
785*b7893ccfSSadaf Ebrahimi 
786*b7893ccfSSadaf Ebrahimi     bool failcase_needs_depth = false;  // to mark cases that need depth attachment
787*b7893ccfSSadaf Ebrahimi 
788*b7893ccfSSadaf Ebrahimi     VkBufferObj index_buffer;
789*b7893ccfSSadaf Ebrahimi 
790*b7893ccfSSadaf Ebrahimi     switch (failCase) {
791*b7893ccfSSadaf Ebrahimi         case BsoFailLineWidth: {
792*b7893ccfSSadaf Ebrahimi             pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_LINE_WIDTH);
793*b7893ccfSSadaf Ebrahimi             VkPipelineInputAssemblyStateCreateInfo ia_state = {};
794*b7893ccfSSadaf Ebrahimi             ia_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
795*b7893ccfSSadaf Ebrahimi             ia_state.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
796*b7893ccfSSadaf Ebrahimi             pipelineobj.SetInputAssembly(&ia_state);
797*b7893ccfSSadaf Ebrahimi             break;
798*b7893ccfSSadaf Ebrahimi         }
799*b7893ccfSSadaf Ebrahimi         case BsoFailLineStipple: {
800*b7893ccfSSadaf Ebrahimi             pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_LINE_STIPPLE_EXT);
801*b7893ccfSSadaf Ebrahimi             VkPipelineInputAssemblyStateCreateInfo ia_state = {};
802*b7893ccfSSadaf Ebrahimi             ia_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
803*b7893ccfSSadaf Ebrahimi             ia_state.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
804*b7893ccfSSadaf Ebrahimi             pipelineobj.SetInputAssembly(&ia_state);
805*b7893ccfSSadaf Ebrahimi 
806*b7893ccfSSadaf Ebrahimi             VkPipelineRasterizationLineStateCreateInfoEXT line_state = {};
807*b7893ccfSSadaf Ebrahimi             line_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
808*b7893ccfSSadaf Ebrahimi             line_state.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
809*b7893ccfSSadaf Ebrahimi             line_state.stippledLineEnable = VK_TRUE;
810*b7893ccfSSadaf Ebrahimi             line_state.lineStippleFactor = 0;
811*b7893ccfSSadaf Ebrahimi             line_state.lineStipplePattern = 0;
812*b7893ccfSSadaf Ebrahimi             pipelineobj.SetLineState(&line_state);
813*b7893ccfSSadaf Ebrahimi             break;
814*b7893ccfSSadaf Ebrahimi         }
815*b7893ccfSSadaf Ebrahimi         case BsoFailDepthBias: {
816*b7893ccfSSadaf Ebrahimi             pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_DEPTH_BIAS);
817*b7893ccfSSadaf Ebrahimi             VkPipelineRasterizationStateCreateInfo rs_state = {};
818*b7893ccfSSadaf Ebrahimi             rs_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
819*b7893ccfSSadaf Ebrahimi             rs_state.depthBiasEnable = VK_TRUE;
820*b7893ccfSSadaf Ebrahimi             rs_state.lineWidth = 1.0f;
821*b7893ccfSSadaf Ebrahimi             pipelineobj.SetRasterization(&rs_state);
822*b7893ccfSSadaf Ebrahimi             break;
823*b7893ccfSSadaf Ebrahimi         }
824*b7893ccfSSadaf Ebrahimi         case BsoFailViewport: {
825*b7893ccfSSadaf Ebrahimi             pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_VIEWPORT);
826*b7893ccfSSadaf Ebrahimi             break;
827*b7893ccfSSadaf Ebrahimi         }
828*b7893ccfSSadaf Ebrahimi         case BsoFailScissor: {
829*b7893ccfSSadaf Ebrahimi             pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_SCISSOR);
830*b7893ccfSSadaf Ebrahimi             break;
831*b7893ccfSSadaf Ebrahimi         }
832*b7893ccfSSadaf Ebrahimi         case BsoFailBlend: {
833*b7893ccfSSadaf Ebrahimi             pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_BLEND_CONSTANTS);
834*b7893ccfSSadaf Ebrahimi             VkPipelineColorBlendAttachmentState att_state = {};
835*b7893ccfSSadaf Ebrahimi             att_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR;
836*b7893ccfSSadaf Ebrahimi             att_state.blendEnable = VK_TRUE;
837*b7893ccfSSadaf Ebrahimi             pipelineobj.AddColorAttachment(0, att_state);
838*b7893ccfSSadaf Ebrahimi             break;
839*b7893ccfSSadaf Ebrahimi         }
840*b7893ccfSSadaf Ebrahimi         case BsoFailDepthBounds: {
841*b7893ccfSSadaf Ebrahimi             failcase_needs_depth = true;
842*b7893ccfSSadaf Ebrahimi             pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_DEPTH_BOUNDS);
843*b7893ccfSSadaf Ebrahimi             break;
844*b7893ccfSSadaf Ebrahimi         }
845*b7893ccfSSadaf Ebrahimi         case BsoFailStencilReadMask: {
846*b7893ccfSSadaf Ebrahimi             failcase_needs_depth = true;
847*b7893ccfSSadaf Ebrahimi             pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK);
848*b7893ccfSSadaf Ebrahimi             break;
849*b7893ccfSSadaf Ebrahimi         }
850*b7893ccfSSadaf Ebrahimi         case BsoFailStencilWriteMask: {
851*b7893ccfSSadaf Ebrahimi             failcase_needs_depth = true;
852*b7893ccfSSadaf Ebrahimi             pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK);
853*b7893ccfSSadaf Ebrahimi             break;
854*b7893ccfSSadaf Ebrahimi         }
855*b7893ccfSSadaf Ebrahimi         case BsoFailStencilReference: {
856*b7893ccfSSadaf Ebrahimi             failcase_needs_depth = true;
857*b7893ccfSSadaf Ebrahimi             pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
858*b7893ccfSSadaf Ebrahimi             break;
859*b7893ccfSSadaf Ebrahimi         }
860*b7893ccfSSadaf Ebrahimi 
861*b7893ccfSSadaf Ebrahimi         case BsoFailIndexBuffer:
862*b7893ccfSSadaf Ebrahimi             break;
863*b7893ccfSSadaf Ebrahimi         case BsoFailIndexBufferBadSize:
864*b7893ccfSSadaf Ebrahimi         case BsoFailIndexBufferBadOffset:
865*b7893ccfSSadaf Ebrahimi         case BsoFailIndexBufferBadMapSize:
866*b7893ccfSSadaf Ebrahimi         case BsoFailIndexBufferBadMapOffset: {
867*b7893ccfSSadaf Ebrahimi             // Create an index buffer for these tests.
868*b7893ccfSSadaf Ebrahimi             // There is no need to populate it because we should bail before trying to draw.
869*b7893ccfSSadaf Ebrahimi             uint32_t const indices[] = {0};
870*b7893ccfSSadaf Ebrahimi             VkBufferCreateInfo buffer_info = {};
871*b7893ccfSSadaf Ebrahimi             buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
872*b7893ccfSSadaf Ebrahimi             buffer_info.size = 1024;
873*b7893ccfSSadaf Ebrahimi             buffer_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
874*b7893ccfSSadaf Ebrahimi             buffer_info.queueFamilyIndexCount = 1;
875*b7893ccfSSadaf Ebrahimi             buffer_info.pQueueFamilyIndices = indices;
876*b7893ccfSSadaf Ebrahimi             index_buffer.init(*m_device, buffer_info, (VkMemoryPropertyFlags)VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
877*b7893ccfSSadaf Ebrahimi         } break;
878*b7893ccfSSadaf Ebrahimi         case BsoFailCmdClearAttachments:
879*b7893ccfSSadaf Ebrahimi             break;
880*b7893ccfSSadaf Ebrahimi         case BsoFailNone:
881*b7893ccfSSadaf Ebrahimi             break;
882*b7893ccfSSadaf Ebrahimi         default:
883*b7893ccfSSadaf Ebrahimi             break;
884*b7893ccfSSadaf Ebrahimi     }
885*b7893ccfSSadaf Ebrahimi 
886*b7893ccfSSadaf Ebrahimi     VkDescriptorSetObj descriptorSet(m_device);
887*b7893ccfSSadaf Ebrahimi 
888*b7893ccfSSadaf Ebrahimi     VkImageView *depth_attachment = nullptr;
889*b7893ccfSSadaf Ebrahimi     if (failcase_needs_depth) {
890*b7893ccfSSadaf Ebrahimi         m_depth_stencil_fmt = FindSupportedDepthStencilFormat(gpu());
891*b7893ccfSSadaf Ebrahimi         ASSERT_TRUE(m_depth_stencil_fmt != VK_FORMAT_UNDEFINED);
892*b7893ccfSSadaf Ebrahimi 
893*b7893ccfSSadaf Ebrahimi         m_depthStencil->Init(m_device, static_cast<uint32_t>(m_width), static_cast<uint32_t>(m_height), m_depth_stencil_fmt,
894*b7893ccfSSadaf Ebrahimi                              VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
895*b7893ccfSSadaf Ebrahimi         depth_attachment = m_depthStencil->BindInfo();
896*b7893ccfSSadaf Ebrahimi     }
897*b7893ccfSSadaf Ebrahimi 
898*b7893ccfSSadaf Ebrahimi     ASSERT_NO_FATAL_FAILURE(InitRenderTarget(1, depth_attachment));
899*b7893ccfSSadaf Ebrahimi     m_commandBuffer->begin();
900*b7893ccfSSadaf Ebrahimi 
901*b7893ccfSSadaf Ebrahimi     GenericDrawPreparation(m_commandBuffer, pipelineobj, descriptorSet, failCase);
902*b7893ccfSSadaf Ebrahimi 
903*b7893ccfSSadaf Ebrahimi     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
904*b7893ccfSSadaf Ebrahimi 
905*b7893ccfSSadaf Ebrahimi     // render triangle
906*b7893ccfSSadaf Ebrahimi     if (failCase == BsoFailIndexBuffer) {
907*b7893ccfSSadaf Ebrahimi         // Use DrawIndexed w/o an index buffer bound
908*b7893ccfSSadaf Ebrahimi         m_commandBuffer->DrawIndexed(3, 1, 0, 0, 0);
909*b7893ccfSSadaf Ebrahimi     } else if (failCase == BsoFailIndexBufferBadSize) {
910*b7893ccfSSadaf Ebrahimi         // Bind the index buffer and draw one too many indices
911*b7893ccfSSadaf Ebrahimi         m_commandBuffer->BindIndexBuffer(&index_buffer, 0, VK_INDEX_TYPE_UINT16);
912*b7893ccfSSadaf Ebrahimi         m_commandBuffer->DrawIndexed(513, 1, 0, 0, 0);
913*b7893ccfSSadaf Ebrahimi     } else if (failCase == BsoFailIndexBufferBadOffset) {
914*b7893ccfSSadaf Ebrahimi         // Bind the index buffer and draw one past the end of the buffer using the offset
915*b7893ccfSSadaf Ebrahimi         m_commandBuffer->BindIndexBuffer(&index_buffer, 0, VK_INDEX_TYPE_UINT16);
916*b7893ccfSSadaf Ebrahimi         m_commandBuffer->DrawIndexed(512, 1, 1, 0, 0);
917*b7893ccfSSadaf Ebrahimi     } else if (failCase == BsoFailIndexBufferBadMapSize) {
918*b7893ccfSSadaf Ebrahimi         // Bind the index buffer at the middle point and draw one too many indices
919*b7893ccfSSadaf Ebrahimi         m_commandBuffer->BindIndexBuffer(&index_buffer, 512, VK_INDEX_TYPE_UINT16);
920*b7893ccfSSadaf Ebrahimi         m_commandBuffer->DrawIndexed(257, 1, 0, 0, 0);
921*b7893ccfSSadaf Ebrahimi     } else if (failCase == BsoFailIndexBufferBadMapOffset) {
922*b7893ccfSSadaf Ebrahimi         // Bind the index buffer at the middle point and draw one past the end of the buffer
923*b7893ccfSSadaf Ebrahimi         m_commandBuffer->BindIndexBuffer(&index_buffer, 512, VK_INDEX_TYPE_UINT16);
924*b7893ccfSSadaf Ebrahimi         m_commandBuffer->DrawIndexed(256, 1, 1, 0, 0);
925*b7893ccfSSadaf Ebrahimi     } else {
926*b7893ccfSSadaf Ebrahimi         m_commandBuffer->Draw(3, 1, 0, 0);
927*b7893ccfSSadaf Ebrahimi     }
928*b7893ccfSSadaf Ebrahimi 
929*b7893ccfSSadaf Ebrahimi     if (failCase == BsoFailCmdClearAttachments) {
930*b7893ccfSSadaf Ebrahimi         VkClearAttachment color_attachment = {};
931*b7893ccfSSadaf Ebrahimi         color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
932*b7893ccfSSadaf Ebrahimi         color_attachment.colorAttachment = 2000000000;  // Someone who knew what they were doing would use 0 for the index;
933*b7893ccfSSadaf Ebrahimi         VkClearRect clear_rect = {{{0, 0}, {static_cast<uint32_t>(m_width), static_cast<uint32_t>(m_height)}}, 0, 1};
934*b7893ccfSSadaf Ebrahimi 
935*b7893ccfSSadaf Ebrahimi         vkCmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect);
936*b7893ccfSSadaf Ebrahimi     }
937*b7893ccfSSadaf Ebrahimi 
938*b7893ccfSSadaf Ebrahimi     // finalize recording of the command buffer
939*b7893ccfSSadaf Ebrahimi     m_commandBuffer->EndRenderPass();
940*b7893ccfSSadaf Ebrahimi     m_commandBuffer->end();
941*b7893ccfSSadaf Ebrahimi     m_commandBuffer->QueueCommandBuffer(true);
942*b7893ccfSSadaf Ebrahimi     DestroyRenderTarget();
943*b7893ccfSSadaf Ebrahimi }
944*b7893ccfSSadaf Ebrahimi 
GenericDrawPreparation(VkCommandBufferObj * commandBuffer,VkPipelineObj & pipelineobj,VkDescriptorSetObj & descriptorSet,BsoFailSelect failCase)945*b7893ccfSSadaf Ebrahimi void VkLayerTest::GenericDrawPreparation(VkCommandBufferObj *commandBuffer, VkPipelineObj &pipelineobj,
946*b7893ccfSSadaf Ebrahimi                                          VkDescriptorSetObj &descriptorSet, BsoFailSelect failCase) {
947*b7893ccfSSadaf Ebrahimi     commandBuffer->ClearAllBuffers(m_renderTargets, m_clear_color, m_depthStencil, m_depth_clear_color, m_stencil_clear_color);
948*b7893ccfSSadaf Ebrahimi 
949*b7893ccfSSadaf Ebrahimi     commandBuffer->PrepareAttachments(m_renderTargets, m_depthStencil);
950*b7893ccfSSadaf Ebrahimi     // Make sure depthWriteEnable is set so that Depth fail test will work
951*b7893ccfSSadaf Ebrahimi     // correctly
952*b7893ccfSSadaf Ebrahimi     // Make sure stencilTestEnable is set so that Stencil fail test will work
953*b7893ccfSSadaf Ebrahimi     // correctly
954*b7893ccfSSadaf Ebrahimi     VkStencilOpState stencil = {};
955*b7893ccfSSadaf Ebrahimi     stencil.failOp = VK_STENCIL_OP_KEEP;
956*b7893ccfSSadaf Ebrahimi     stencil.passOp = VK_STENCIL_OP_KEEP;
957*b7893ccfSSadaf Ebrahimi     stencil.depthFailOp = VK_STENCIL_OP_KEEP;
958*b7893ccfSSadaf Ebrahimi     stencil.compareOp = VK_COMPARE_OP_NEVER;
959*b7893ccfSSadaf Ebrahimi 
960*b7893ccfSSadaf Ebrahimi     VkPipelineDepthStencilStateCreateInfo ds_ci = {};
961*b7893ccfSSadaf Ebrahimi     ds_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
962*b7893ccfSSadaf Ebrahimi     ds_ci.pNext = NULL;
963*b7893ccfSSadaf Ebrahimi     ds_ci.depthTestEnable = VK_FALSE;
964*b7893ccfSSadaf Ebrahimi     ds_ci.depthWriteEnable = VK_TRUE;
965*b7893ccfSSadaf Ebrahimi     ds_ci.depthCompareOp = VK_COMPARE_OP_NEVER;
966*b7893ccfSSadaf Ebrahimi     ds_ci.depthBoundsTestEnable = VK_FALSE;
967*b7893ccfSSadaf Ebrahimi     if (failCase == BsoFailDepthBounds) {
968*b7893ccfSSadaf Ebrahimi         ds_ci.depthBoundsTestEnable = VK_TRUE;
969*b7893ccfSSadaf Ebrahimi         ds_ci.maxDepthBounds = 0.0f;
970*b7893ccfSSadaf Ebrahimi         ds_ci.minDepthBounds = 0.0f;
971*b7893ccfSSadaf Ebrahimi     }
972*b7893ccfSSadaf Ebrahimi     ds_ci.stencilTestEnable = VK_TRUE;
973*b7893ccfSSadaf Ebrahimi     ds_ci.front = stencil;
974*b7893ccfSSadaf Ebrahimi     ds_ci.back = stencil;
975*b7893ccfSSadaf Ebrahimi 
976*b7893ccfSSadaf Ebrahimi     pipelineobj.SetDepthStencil(&ds_ci);
977*b7893ccfSSadaf Ebrahimi     pipelineobj.SetViewport(m_viewports);
978*b7893ccfSSadaf Ebrahimi     pipelineobj.SetScissor(m_scissors);
979*b7893ccfSSadaf Ebrahimi     descriptorSet.CreateVKDescriptorSet(commandBuffer);
980*b7893ccfSSadaf Ebrahimi     VkResult err = pipelineobj.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass());
981*b7893ccfSSadaf Ebrahimi     ASSERT_VK_SUCCESS(err);
982*b7893ccfSSadaf Ebrahimi     vkCmdBindPipeline(commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineobj.handle());
983*b7893ccfSSadaf Ebrahimi     commandBuffer->BindDescriptorSet(descriptorSet);
984*b7893ccfSSadaf Ebrahimi }
985*b7893ccfSSadaf Ebrahimi 
Init(VkPhysicalDeviceFeatures * features,VkPhysicalDeviceFeatures2 * features2,const VkCommandPoolCreateFlags flags,void * instance_pnext)986*b7893ccfSSadaf Ebrahimi void VkLayerTest::Init(VkPhysicalDeviceFeatures *features, VkPhysicalDeviceFeatures2 *features2,
987*b7893ccfSSadaf Ebrahimi                        const VkCommandPoolCreateFlags flags, void *instance_pnext) {
988*b7893ccfSSadaf Ebrahimi     InitFramework(myDbgFunc, m_errorMonitor, instance_pnext);
989*b7893ccfSSadaf Ebrahimi     InitState(features, features2, flags);
990*b7893ccfSSadaf Ebrahimi }
991*b7893ccfSSadaf Ebrahimi 
Monitor()992*b7893ccfSSadaf Ebrahimi ErrorMonitor *VkLayerTest::Monitor() { return m_errorMonitor; }
993*b7893ccfSSadaf Ebrahimi 
CommandBuffer()994*b7893ccfSSadaf Ebrahimi VkCommandBufferObj *VkLayerTest::CommandBuffer() { return m_commandBuffer; }
995*b7893ccfSSadaf Ebrahimi 
VkLayerTest()996*b7893ccfSSadaf Ebrahimi VkLayerTest::VkLayerTest() {
997*b7893ccfSSadaf Ebrahimi     m_enableWSI = false;
998*b7893ccfSSadaf Ebrahimi 
999*b7893ccfSSadaf Ebrahimi     m_instance_layer_names.clear();
1000*b7893ccfSSadaf Ebrahimi     m_instance_extension_names.clear();
1001*b7893ccfSSadaf Ebrahimi     m_device_extension_names.clear();
1002*b7893ccfSSadaf Ebrahimi 
1003*b7893ccfSSadaf Ebrahimi     // Add default instance extensions to the list
1004*b7893ccfSSadaf Ebrahimi     m_instance_extension_names.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
1005*b7893ccfSSadaf Ebrahimi 
1006*b7893ccfSSadaf Ebrahimi     if (VkTestFramework::m_khronos_layer_disable) {
1007*b7893ccfSSadaf Ebrahimi         m_instance_layer_names.push_back("VK_LAYER_GOOGLE_threading");
1008*b7893ccfSSadaf Ebrahimi         m_instance_layer_names.push_back("VK_LAYER_LUNARG_parameter_validation");
1009*b7893ccfSSadaf Ebrahimi         m_instance_layer_names.push_back("VK_LAYER_LUNARG_object_tracker");
1010*b7893ccfSSadaf Ebrahimi         m_instance_layer_names.push_back("VK_LAYER_LUNARG_core_validation");
1011*b7893ccfSSadaf Ebrahimi         m_instance_layer_names.push_back("VK_LAYER_GOOGLE_unique_objects");
1012*b7893ccfSSadaf Ebrahimi     } else {
1013*b7893ccfSSadaf Ebrahimi         m_instance_layer_names.push_back("VK_LAYER_KHRONOS_validation");
1014*b7893ccfSSadaf Ebrahimi     }
1015*b7893ccfSSadaf Ebrahimi     if (VkTestFramework::m_devsim_layer) {
1016*b7893ccfSSadaf Ebrahimi         if (InstanceLayerSupported("VK_LAYER_LUNARG_device_simulation")) {
1017*b7893ccfSSadaf Ebrahimi             m_instance_layer_names.push_back("VK_LAYER_LUNARG_device_simulation");
1018*b7893ccfSSadaf Ebrahimi         } else {
1019*b7893ccfSSadaf Ebrahimi             VkTestFramework::m_devsim_layer = false;
1020*b7893ccfSSadaf Ebrahimi             printf("             Did not find VK_LAYER_LUNARG_device_simulation layer so it will not be enabled.\n");
1021*b7893ccfSSadaf Ebrahimi         }
1022*b7893ccfSSadaf Ebrahimi     }
1023*b7893ccfSSadaf Ebrahimi 
1024*b7893ccfSSadaf Ebrahimi     this->app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
1025*b7893ccfSSadaf Ebrahimi     this->app_info.pNext = NULL;
1026*b7893ccfSSadaf Ebrahimi     this->app_info.pApplicationName = "layer_tests";
1027*b7893ccfSSadaf Ebrahimi     this->app_info.applicationVersion = 1;
1028*b7893ccfSSadaf Ebrahimi     this->app_info.pEngineName = "unittest";
1029*b7893ccfSSadaf Ebrahimi     this->app_info.engineVersion = 1;
1030*b7893ccfSSadaf Ebrahimi     this->app_info.apiVersion = VK_API_VERSION_1_0;
1031*b7893ccfSSadaf Ebrahimi 
1032*b7893ccfSSadaf Ebrahimi     m_errorMonitor = new ErrorMonitor;
1033*b7893ccfSSadaf Ebrahimi 
1034*b7893ccfSSadaf Ebrahimi     // Find out what version the instance supports and record the default target instance
1035*b7893ccfSSadaf Ebrahimi     auto enumerateInstanceVersion = (PFN_vkEnumerateInstanceVersion)vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion");
1036*b7893ccfSSadaf Ebrahimi     if (enumerateInstanceVersion) {
1037*b7893ccfSSadaf Ebrahimi         enumerateInstanceVersion(&m_instance_api_version);
1038*b7893ccfSSadaf Ebrahimi     } else {
1039*b7893ccfSSadaf Ebrahimi         m_instance_api_version = VK_API_VERSION_1_0;
1040*b7893ccfSSadaf Ebrahimi     }
1041*b7893ccfSSadaf Ebrahimi     m_target_api_version = app_info.apiVersion;
1042*b7893ccfSSadaf Ebrahimi }
1043*b7893ccfSSadaf Ebrahimi 
AddSurfaceInstanceExtension()1044*b7893ccfSSadaf Ebrahimi bool VkLayerTest::AddSurfaceInstanceExtension() {
1045*b7893ccfSSadaf Ebrahimi     m_enableWSI = true;
1046*b7893ccfSSadaf Ebrahimi     if (!InstanceExtensionSupported(VK_KHR_SURFACE_EXTENSION_NAME)) {
1047*b7893ccfSSadaf Ebrahimi         printf("%s VK_KHR_SURFACE_EXTENSION_NAME extension not supported\n", kSkipPrefix);
1048*b7893ccfSSadaf Ebrahimi         return false;
1049*b7893ccfSSadaf Ebrahimi     }
1050*b7893ccfSSadaf Ebrahimi     m_instance_extension_names.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
1051*b7893ccfSSadaf Ebrahimi 
1052*b7893ccfSSadaf Ebrahimi     bool bSupport = false;
1053*b7893ccfSSadaf Ebrahimi #if defined(VK_USE_PLATFORM_WIN32_KHR)
1054*b7893ccfSSadaf Ebrahimi     if (!InstanceExtensionSupported(VK_KHR_WIN32_SURFACE_EXTENSION_NAME)) {
1055*b7893ccfSSadaf Ebrahimi         printf("%s VK_KHR_WIN32_SURFACE_EXTENSION_NAME extension not supported\n", kSkipPrefix);
1056*b7893ccfSSadaf Ebrahimi         return false;
1057*b7893ccfSSadaf Ebrahimi     }
1058*b7893ccfSSadaf Ebrahimi     m_instance_extension_names.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
1059*b7893ccfSSadaf Ebrahimi     bSupport = true;
1060*b7893ccfSSadaf Ebrahimi #endif
1061*b7893ccfSSadaf Ebrahimi 
1062*b7893ccfSSadaf Ebrahimi #if defined(VK_USE_PLATFORM_ANDROID_KHR) && defined(VALIDATION_APK)
1063*b7893ccfSSadaf Ebrahimi     if (!InstanceExtensionSupported(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) {
1064*b7893ccfSSadaf Ebrahimi         printf("%s VK_KHR_ANDROID_SURFACE_EXTENSION_NAME extension not supported\n", kSkipPrefix);
1065*b7893ccfSSadaf Ebrahimi         return false;
1066*b7893ccfSSadaf Ebrahimi     }
1067*b7893ccfSSadaf Ebrahimi     m_instance_extension_names.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
1068*b7893ccfSSadaf Ebrahimi     bSupport = true;
1069*b7893ccfSSadaf Ebrahimi #endif
1070*b7893ccfSSadaf Ebrahimi 
1071*b7893ccfSSadaf Ebrahimi #if defined(VK_USE_PLATFORM_XLIB_KHR)
1072*b7893ccfSSadaf Ebrahimi     if (!InstanceExtensionSupported(VK_KHR_XLIB_SURFACE_EXTENSION_NAME)) {
1073*b7893ccfSSadaf Ebrahimi         printf("%s VK_KHR_XLIB_SURFACE_EXTENSION_NAME extension not supported\n", kSkipPrefix);
1074*b7893ccfSSadaf Ebrahimi         return false;
1075*b7893ccfSSadaf Ebrahimi     }
1076*b7893ccfSSadaf Ebrahimi     if (XOpenDisplay(NULL)) {
1077*b7893ccfSSadaf Ebrahimi         m_instance_extension_names.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
1078*b7893ccfSSadaf Ebrahimi         bSupport = true;
1079*b7893ccfSSadaf Ebrahimi     }
1080*b7893ccfSSadaf Ebrahimi #endif
1081*b7893ccfSSadaf Ebrahimi 
1082*b7893ccfSSadaf Ebrahimi #if defined(VK_USE_PLATFORM_XCB_KHR)
1083*b7893ccfSSadaf Ebrahimi     if (!InstanceExtensionSupported(VK_KHR_XCB_SURFACE_EXTENSION_NAME)) {
1084*b7893ccfSSadaf Ebrahimi         printf("%s VK_KHR_XCB_SURFACE_EXTENSION_NAME extension not supported\n", kSkipPrefix);
1085*b7893ccfSSadaf Ebrahimi         return false;
1086*b7893ccfSSadaf Ebrahimi     }
1087*b7893ccfSSadaf Ebrahimi     if (!bSupport && xcb_connect(NULL, NULL)) {
1088*b7893ccfSSadaf Ebrahimi         m_instance_extension_names.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
1089*b7893ccfSSadaf Ebrahimi         bSupport = true;
1090*b7893ccfSSadaf Ebrahimi     }
1091*b7893ccfSSadaf Ebrahimi #endif
1092*b7893ccfSSadaf Ebrahimi 
1093*b7893ccfSSadaf Ebrahimi     if (bSupport) return true;
1094*b7893ccfSSadaf Ebrahimi     printf("%s No platform's surface extension supported\n", kSkipPrefix);
1095*b7893ccfSSadaf Ebrahimi     return false;
1096*b7893ccfSSadaf Ebrahimi }
1097*b7893ccfSSadaf Ebrahimi 
AddSwapchainDeviceExtension()1098*b7893ccfSSadaf Ebrahimi bool VkLayerTest::AddSwapchainDeviceExtension() {
1099*b7893ccfSSadaf Ebrahimi     if (!DeviceExtensionSupported(gpu(), nullptr, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
1100*b7893ccfSSadaf Ebrahimi         printf("%s VK_KHR_SWAPCHAIN_EXTENSION_NAME extension not supported\n", kSkipPrefix);
1101*b7893ccfSSadaf Ebrahimi         return false;
1102*b7893ccfSSadaf Ebrahimi     }
1103*b7893ccfSSadaf Ebrahimi     m_device_extension_names.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
1104*b7893ccfSSadaf Ebrahimi     return true;
1105*b7893ccfSSadaf Ebrahimi }
1106*b7893ccfSSadaf Ebrahimi 
SetTargetApiVersion(uint32_t target_api_version)1107*b7893ccfSSadaf Ebrahimi uint32_t VkLayerTest::SetTargetApiVersion(uint32_t target_api_version) {
1108*b7893ccfSSadaf Ebrahimi     if (target_api_version == 0) target_api_version = VK_API_VERSION_1_0;
1109*b7893ccfSSadaf Ebrahimi     if (target_api_version <= m_instance_api_version) {
1110*b7893ccfSSadaf Ebrahimi         m_target_api_version = target_api_version;
1111*b7893ccfSSadaf Ebrahimi         app_info.apiVersion = m_target_api_version;
1112*b7893ccfSSadaf Ebrahimi     }
1113*b7893ccfSSadaf Ebrahimi     return m_target_api_version;
1114*b7893ccfSSadaf Ebrahimi }
DeviceValidationVersion()1115*b7893ccfSSadaf Ebrahimi uint32_t VkLayerTest::DeviceValidationVersion() {
1116*b7893ccfSSadaf Ebrahimi     // The validation layers, assume the version we are validating to is the apiVersion unless the device apiVersion is lower
1117*b7893ccfSSadaf Ebrahimi     VkPhysicalDeviceProperties props;
1118*b7893ccfSSadaf Ebrahimi     GetPhysicalDeviceProperties(&props);
1119*b7893ccfSSadaf Ebrahimi     return std::min(m_target_api_version, props.apiVersion);
1120*b7893ccfSSadaf Ebrahimi }
1121*b7893ccfSSadaf Ebrahimi 
LoadDeviceProfileLayer(PFN_vkSetPhysicalDeviceFormatPropertiesEXT & fpvkSetPhysicalDeviceFormatPropertiesEXT,PFN_vkGetOriginalPhysicalDeviceFormatPropertiesEXT & fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT)1122*b7893ccfSSadaf Ebrahimi bool VkLayerTest::LoadDeviceProfileLayer(
1123*b7893ccfSSadaf Ebrahimi     PFN_vkSetPhysicalDeviceFormatPropertiesEXT &fpvkSetPhysicalDeviceFormatPropertiesEXT,
1124*b7893ccfSSadaf Ebrahimi     PFN_vkGetOriginalPhysicalDeviceFormatPropertiesEXT &fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT) {
1125*b7893ccfSSadaf Ebrahimi     // Load required functions
1126*b7893ccfSSadaf Ebrahimi     fpvkSetPhysicalDeviceFormatPropertiesEXT =
1127*b7893ccfSSadaf Ebrahimi         (PFN_vkSetPhysicalDeviceFormatPropertiesEXT)vkGetInstanceProcAddr(instance(), "vkSetPhysicalDeviceFormatPropertiesEXT");
1128*b7893ccfSSadaf Ebrahimi     fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT = (PFN_vkGetOriginalPhysicalDeviceFormatPropertiesEXT)vkGetInstanceProcAddr(
1129*b7893ccfSSadaf Ebrahimi         instance(), "vkGetOriginalPhysicalDeviceFormatPropertiesEXT");
1130*b7893ccfSSadaf Ebrahimi 
1131*b7893ccfSSadaf Ebrahimi     if (!(fpvkSetPhysicalDeviceFormatPropertiesEXT) || !(fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT)) {
1132*b7893ccfSSadaf Ebrahimi         printf("%s Can't find device_profile_api functions; skipped.\n", kSkipPrefix);
1133*b7893ccfSSadaf Ebrahimi         return 0;
1134*b7893ccfSSadaf Ebrahimi     }
1135*b7893ccfSSadaf Ebrahimi 
1136*b7893ccfSSadaf Ebrahimi     return 1;
1137*b7893ccfSSadaf Ebrahimi }
1138*b7893ccfSSadaf Ebrahimi 
~VkLayerTest()1139*b7893ccfSSadaf Ebrahimi VkLayerTest::~VkLayerTest() {
1140*b7893ccfSSadaf Ebrahimi     // Clean up resources before we reset
1141*b7893ccfSSadaf Ebrahimi     delete m_errorMonitor;
1142*b7893ccfSSadaf Ebrahimi }
1143*b7893ccfSSadaf Ebrahimi 
GetTestConditionValid(VkDeviceObj * aVulkanDevice,eTestEnFlags aTestFlag,VkBufferUsageFlags aBufferUsage)1144*b7893ccfSSadaf Ebrahimi bool VkBufferTest::GetTestConditionValid(VkDeviceObj *aVulkanDevice, eTestEnFlags aTestFlag, VkBufferUsageFlags aBufferUsage) {
1145*b7893ccfSSadaf Ebrahimi     if (eInvalidDeviceOffset != aTestFlag && eInvalidMemoryOffset != aTestFlag) {
1146*b7893ccfSSadaf Ebrahimi         return true;
1147*b7893ccfSSadaf Ebrahimi     }
1148*b7893ccfSSadaf Ebrahimi     VkDeviceSize offset_limit = 0;
1149*b7893ccfSSadaf Ebrahimi     if (eInvalidMemoryOffset == aTestFlag) {
1150*b7893ccfSSadaf Ebrahimi         VkBuffer vulkanBuffer;
1151*b7893ccfSSadaf Ebrahimi         VkBufferCreateInfo buffer_create_info = {};
1152*b7893ccfSSadaf Ebrahimi         buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1153*b7893ccfSSadaf Ebrahimi         buffer_create_info.size = 32;
1154*b7893ccfSSadaf Ebrahimi         buffer_create_info.usage = aBufferUsage;
1155*b7893ccfSSadaf Ebrahimi 
1156*b7893ccfSSadaf Ebrahimi         vkCreateBuffer(aVulkanDevice->device(), &buffer_create_info, nullptr, &vulkanBuffer);
1157*b7893ccfSSadaf Ebrahimi         VkMemoryRequirements memory_reqs = {};
1158*b7893ccfSSadaf Ebrahimi 
1159*b7893ccfSSadaf Ebrahimi         vkGetBufferMemoryRequirements(aVulkanDevice->device(), vulkanBuffer, &memory_reqs);
1160*b7893ccfSSadaf Ebrahimi         vkDestroyBuffer(aVulkanDevice->device(), vulkanBuffer, nullptr);
1161*b7893ccfSSadaf Ebrahimi         offset_limit = memory_reqs.alignment;
1162*b7893ccfSSadaf Ebrahimi     } else if ((VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) & aBufferUsage) {
1163*b7893ccfSSadaf Ebrahimi         offset_limit = aVulkanDevice->props.limits.minTexelBufferOffsetAlignment;
1164*b7893ccfSSadaf Ebrahimi     } else if (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT & aBufferUsage) {
1165*b7893ccfSSadaf Ebrahimi         offset_limit = aVulkanDevice->props.limits.minUniformBufferOffsetAlignment;
1166*b7893ccfSSadaf Ebrahimi     } else if (VK_BUFFER_USAGE_STORAGE_BUFFER_BIT & aBufferUsage) {
1167*b7893ccfSSadaf Ebrahimi         offset_limit = aVulkanDevice->props.limits.minStorageBufferOffsetAlignment;
1168*b7893ccfSSadaf Ebrahimi     }
1169*b7893ccfSSadaf Ebrahimi     return eOffsetAlignment < offset_limit;
1170*b7893ccfSSadaf Ebrahimi }
1171*b7893ccfSSadaf Ebrahimi 
VkBufferTest(VkDeviceObj * aVulkanDevice,VkBufferUsageFlags aBufferUsage,eTestEnFlags aTestFlag)1172*b7893ccfSSadaf Ebrahimi VkBufferTest::VkBufferTest(VkDeviceObj *aVulkanDevice, VkBufferUsageFlags aBufferUsage, eTestEnFlags aTestFlag)
1173*b7893ccfSSadaf Ebrahimi     : AllocateCurrent(true),
1174*b7893ccfSSadaf Ebrahimi       BoundCurrent(false),
1175*b7893ccfSSadaf Ebrahimi       CreateCurrent(false),
1176*b7893ccfSSadaf Ebrahimi       InvalidDeleteEn(false),
1177*b7893ccfSSadaf Ebrahimi       VulkanDevice(aVulkanDevice->device()) {
1178*b7893ccfSSadaf Ebrahimi     if (eBindNullBuffer == aTestFlag || eBindFakeBuffer == aTestFlag) {
1179*b7893ccfSSadaf Ebrahimi         VkMemoryAllocateInfo memory_allocate_info = {};
1180*b7893ccfSSadaf Ebrahimi         memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
1181*b7893ccfSSadaf Ebrahimi         memory_allocate_info.allocationSize = 1;   // fake size -- shouldn't matter for the test
1182*b7893ccfSSadaf Ebrahimi         memory_allocate_info.memoryTypeIndex = 0;  // fake type -- shouldn't matter for the test
1183*b7893ccfSSadaf Ebrahimi         vkAllocateMemory(VulkanDevice, &memory_allocate_info, nullptr, &VulkanMemory);
1184*b7893ccfSSadaf Ebrahimi 
1185*b7893ccfSSadaf Ebrahimi         VulkanBuffer = (aTestFlag == eBindNullBuffer) ? VK_NULL_HANDLE : (VkBuffer)0xCDCDCDCDCDCDCDCD;
1186*b7893ccfSSadaf Ebrahimi 
1187*b7893ccfSSadaf Ebrahimi         vkBindBufferMemory(VulkanDevice, VulkanBuffer, VulkanMemory, 0);
1188*b7893ccfSSadaf Ebrahimi     } else {
1189*b7893ccfSSadaf Ebrahimi         VkBufferCreateInfo buffer_create_info = {};
1190*b7893ccfSSadaf Ebrahimi         buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1191*b7893ccfSSadaf Ebrahimi         buffer_create_info.size = 32;
1192*b7893ccfSSadaf Ebrahimi         buffer_create_info.usage = aBufferUsage;
1193*b7893ccfSSadaf Ebrahimi 
1194*b7893ccfSSadaf Ebrahimi         vkCreateBuffer(VulkanDevice, &buffer_create_info, nullptr, &VulkanBuffer);
1195*b7893ccfSSadaf Ebrahimi 
1196*b7893ccfSSadaf Ebrahimi         CreateCurrent = true;
1197*b7893ccfSSadaf Ebrahimi 
1198*b7893ccfSSadaf Ebrahimi         VkMemoryRequirements memory_requirements;
1199*b7893ccfSSadaf Ebrahimi         vkGetBufferMemoryRequirements(VulkanDevice, VulkanBuffer, &memory_requirements);
1200*b7893ccfSSadaf Ebrahimi 
1201*b7893ccfSSadaf Ebrahimi         VkMemoryAllocateInfo memory_allocate_info = {};
1202*b7893ccfSSadaf Ebrahimi         memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
1203*b7893ccfSSadaf Ebrahimi         memory_allocate_info.allocationSize = memory_requirements.size + eOffsetAlignment;
1204*b7893ccfSSadaf Ebrahimi         bool pass = aVulkanDevice->phy().set_memory_type(memory_requirements.memoryTypeBits, &memory_allocate_info,
1205*b7893ccfSSadaf Ebrahimi                                                          VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
1206*b7893ccfSSadaf Ebrahimi         if (!pass) {
1207*b7893ccfSSadaf Ebrahimi             CreateCurrent = false;
1208*b7893ccfSSadaf Ebrahimi             vkDestroyBuffer(VulkanDevice, VulkanBuffer, nullptr);
1209*b7893ccfSSadaf Ebrahimi             return;
1210*b7893ccfSSadaf Ebrahimi         }
1211*b7893ccfSSadaf Ebrahimi 
1212*b7893ccfSSadaf Ebrahimi         vkAllocateMemory(VulkanDevice, &memory_allocate_info, NULL, &VulkanMemory);
1213*b7893ccfSSadaf Ebrahimi         // NB: 1 is intentionally an invalid offset value
1214*b7893ccfSSadaf Ebrahimi         const bool offset_en = eInvalidDeviceOffset == aTestFlag || eInvalidMemoryOffset == aTestFlag;
1215*b7893ccfSSadaf Ebrahimi         vkBindBufferMemory(VulkanDevice, VulkanBuffer, VulkanMemory, offset_en ? eOffsetAlignment : 0);
1216*b7893ccfSSadaf Ebrahimi         BoundCurrent = true;
1217*b7893ccfSSadaf Ebrahimi 
1218*b7893ccfSSadaf Ebrahimi         InvalidDeleteEn = (eFreeInvalidHandle == aTestFlag);
1219*b7893ccfSSadaf Ebrahimi     }
1220*b7893ccfSSadaf Ebrahimi }
1221*b7893ccfSSadaf Ebrahimi 
~VkBufferTest()1222*b7893ccfSSadaf Ebrahimi VkBufferTest::~VkBufferTest() {
1223*b7893ccfSSadaf Ebrahimi     if (CreateCurrent) {
1224*b7893ccfSSadaf Ebrahimi         vkDestroyBuffer(VulkanDevice, VulkanBuffer, nullptr);
1225*b7893ccfSSadaf Ebrahimi     }
1226*b7893ccfSSadaf Ebrahimi     if (AllocateCurrent) {
1227*b7893ccfSSadaf Ebrahimi         if (InvalidDeleteEn) {
1228*b7893ccfSSadaf Ebrahimi             auto bad_memory = CastFromUint64<VkDeviceMemory>(CastToUint64(VulkanMemory) + 1);
1229*b7893ccfSSadaf Ebrahimi             vkFreeMemory(VulkanDevice, bad_memory, nullptr);
1230*b7893ccfSSadaf Ebrahimi         }
1231*b7893ccfSSadaf Ebrahimi         vkFreeMemory(VulkanDevice, VulkanMemory, nullptr);
1232*b7893ccfSSadaf Ebrahimi     }
1233*b7893ccfSSadaf Ebrahimi }
1234*b7893ccfSSadaf Ebrahimi 
GetBufferCurrent()1235*b7893ccfSSadaf Ebrahimi bool VkBufferTest::GetBufferCurrent() { return AllocateCurrent && BoundCurrent && CreateCurrent; }
1236*b7893ccfSSadaf Ebrahimi 
GetBuffer()1237*b7893ccfSSadaf Ebrahimi const VkBuffer &VkBufferTest::GetBuffer() { return VulkanBuffer; }
1238*b7893ccfSSadaf Ebrahimi 
TestDoubleDestroy()1239*b7893ccfSSadaf Ebrahimi void VkBufferTest::TestDoubleDestroy() {
1240*b7893ccfSSadaf Ebrahimi     // Destroy the buffer but leave the flag set, which will cause
1241*b7893ccfSSadaf Ebrahimi     // the buffer to be destroyed again in the destructor.
1242*b7893ccfSSadaf Ebrahimi     vkDestroyBuffer(VulkanDevice, VulkanBuffer, nullptr);
1243*b7893ccfSSadaf Ebrahimi }
1244*b7893ccfSSadaf Ebrahimi 
1245*b7893ccfSSadaf Ebrahimi uint32_t VkVerticesObj::BindIdGenerator;
1246*b7893ccfSSadaf Ebrahimi 
VkVerticesObj(VkDeviceObj * aVulkanDevice,unsigned aAttributeCount,unsigned aBindingCount,unsigned aByteStride,VkDeviceSize aVertexCount,const float * aVerticies)1247*b7893ccfSSadaf Ebrahimi VkVerticesObj::VkVerticesObj(VkDeviceObj *aVulkanDevice, unsigned aAttributeCount, unsigned aBindingCount, unsigned aByteStride,
1248*b7893ccfSSadaf Ebrahimi                              VkDeviceSize aVertexCount, const float *aVerticies)
1249*b7893ccfSSadaf Ebrahimi     : BoundCurrent(false),
1250*b7893ccfSSadaf Ebrahimi       AttributeCount(aAttributeCount),
1251*b7893ccfSSadaf Ebrahimi       BindingCount(aBindingCount),
1252*b7893ccfSSadaf Ebrahimi       BindId(BindIdGenerator),
1253*b7893ccfSSadaf Ebrahimi       PipelineVertexInputStateCreateInfo(),
1254*b7893ccfSSadaf Ebrahimi       VulkanMemoryBuffer(aVulkanDevice, static_cast<int>(aByteStride * aVertexCount), reinterpret_cast<const void *>(aVerticies),
1255*b7893ccfSSadaf Ebrahimi                          VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) {
1256*b7893ccfSSadaf Ebrahimi     BindIdGenerator++;  // NB: This can wrap w/misuse
1257*b7893ccfSSadaf Ebrahimi 
1258*b7893ccfSSadaf Ebrahimi     VertexInputAttributeDescription = new VkVertexInputAttributeDescription[AttributeCount];
1259*b7893ccfSSadaf Ebrahimi     VertexInputBindingDescription = new VkVertexInputBindingDescription[BindingCount];
1260*b7893ccfSSadaf Ebrahimi 
1261*b7893ccfSSadaf Ebrahimi     PipelineVertexInputStateCreateInfo.pVertexAttributeDescriptions = VertexInputAttributeDescription;
1262*b7893ccfSSadaf Ebrahimi     PipelineVertexInputStateCreateInfo.vertexAttributeDescriptionCount = AttributeCount;
1263*b7893ccfSSadaf Ebrahimi     PipelineVertexInputStateCreateInfo.pVertexBindingDescriptions = VertexInputBindingDescription;
1264*b7893ccfSSadaf Ebrahimi     PipelineVertexInputStateCreateInfo.vertexBindingDescriptionCount = BindingCount;
1265*b7893ccfSSadaf Ebrahimi     PipelineVertexInputStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
1266*b7893ccfSSadaf Ebrahimi 
1267*b7893ccfSSadaf Ebrahimi     unsigned i = 0;
1268*b7893ccfSSadaf Ebrahimi     do {
1269*b7893ccfSSadaf Ebrahimi         VertexInputAttributeDescription[i].binding = BindId;
1270*b7893ccfSSadaf Ebrahimi         VertexInputAttributeDescription[i].location = i;
1271*b7893ccfSSadaf Ebrahimi         VertexInputAttributeDescription[i].format = VK_FORMAT_R32G32B32_SFLOAT;
1272*b7893ccfSSadaf Ebrahimi         VertexInputAttributeDescription[i].offset = sizeof(float) * aByteStride;
1273*b7893ccfSSadaf Ebrahimi         i++;
1274*b7893ccfSSadaf Ebrahimi     } while (AttributeCount < i);
1275*b7893ccfSSadaf Ebrahimi 
1276*b7893ccfSSadaf Ebrahimi     i = 0;
1277*b7893ccfSSadaf Ebrahimi     do {
1278*b7893ccfSSadaf Ebrahimi         VertexInputBindingDescription[i].binding = BindId;
1279*b7893ccfSSadaf Ebrahimi         VertexInputBindingDescription[i].stride = aByteStride;
1280*b7893ccfSSadaf Ebrahimi         VertexInputBindingDescription[i].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
1281*b7893ccfSSadaf Ebrahimi         i++;
1282*b7893ccfSSadaf Ebrahimi     } while (BindingCount < i);
1283*b7893ccfSSadaf Ebrahimi }
1284*b7893ccfSSadaf Ebrahimi 
~VkVerticesObj()1285*b7893ccfSSadaf Ebrahimi VkVerticesObj::~VkVerticesObj() {
1286*b7893ccfSSadaf Ebrahimi     if (VertexInputAttributeDescription) {
1287*b7893ccfSSadaf Ebrahimi         delete[] VertexInputAttributeDescription;
1288*b7893ccfSSadaf Ebrahimi     }
1289*b7893ccfSSadaf Ebrahimi     if (VertexInputBindingDescription) {
1290*b7893ccfSSadaf Ebrahimi         delete[] VertexInputBindingDescription;
1291*b7893ccfSSadaf Ebrahimi     }
1292*b7893ccfSSadaf Ebrahimi }
1293*b7893ccfSSadaf Ebrahimi 
AddVertexInputToPipe(VkPipelineObj & aPipelineObj)1294*b7893ccfSSadaf Ebrahimi bool VkVerticesObj::AddVertexInputToPipe(VkPipelineObj &aPipelineObj) {
1295*b7893ccfSSadaf Ebrahimi     aPipelineObj.AddVertexInputAttribs(VertexInputAttributeDescription, AttributeCount);
1296*b7893ccfSSadaf Ebrahimi     aPipelineObj.AddVertexInputBindings(VertexInputBindingDescription, BindingCount);
1297*b7893ccfSSadaf Ebrahimi     return true;
1298*b7893ccfSSadaf Ebrahimi }
1299*b7893ccfSSadaf Ebrahimi 
AddVertexInputToPipeHelpr(CreatePipelineHelper * pipelineHelper)1300*b7893ccfSSadaf Ebrahimi bool VkVerticesObj::AddVertexInputToPipeHelpr(CreatePipelineHelper *pipelineHelper) {
1301*b7893ccfSSadaf Ebrahimi     pipelineHelper->vi_ci_.pVertexBindingDescriptions = VertexInputBindingDescription;
1302*b7893ccfSSadaf Ebrahimi     pipelineHelper->vi_ci_.vertexBindingDescriptionCount = BindingCount;
1303*b7893ccfSSadaf Ebrahimi     pipelineHelper->vi_ci_.pVertexAttributeDescriptions = VertexInputAttributeDescription;
1304*b7893ccfSSadaf Ebrahimi     pipelineHelper->vi_ci_.vertexAttributeDescriptionCount = AttributeCount;
1305*b7893ccfSSadaf Ebrahimi     return true;
1306*b7893ccfSSadaf Ebrahimi }
1307*b7893ccfSSadaf Ebrahimi 
BindVertexBuffers(VkCommandBuffer aCommandBuffer,unsigned aOffsetCount,VkDeviceSize * aOffsetList)1308*b7893ccfSSadaf Ebrahimi void VkVerticesObj::BindVertexBuffers(VkCommandBuffer aCommandBuffer, unsigned aOffsetCount, VkDeviceSize *aOffsetList) {
1309*b7893ccfSSadaf Ebrahimi     VkDeviceSize *offsetList;
1310*b7893ccfSSadaf Ebrahimi     unsigned offsetCount;
1311*b7893ccfSSadaf Ebrahimi 
1312*b7893ccfSSadaf Ebrahimi     if (aOffsetCount) {
1313*b7893ccfSSadaf Ebrahimi         offsetList = aOffsetList;
1314*b7893ccfSSadaf Ebrahimi         offsetCount = aOffsetCount;
1315*b7893ccfSSadaf Ebrahimi     } else {
1316*b7893ccfSSadaf Ebrahimi         offsetList = new VkDeviceSize[1]();
1317*b7893ccfSSadaf Ebrahimi         offsetCount = 1;
1318*b7893ccfSSadaf Ebrahimi     }
1319*b7893ccfSSadaf Ebrahimi 
1320*b7893ccfSSadaf Ebrahimi     vkCmdBindVertexBuffers(aCommandBuffer, BindId, offsetCount, &VulkanMemoryBuffer.handle(), offsetList);
1321*b7893ccfSSadaf Ebrahimi     BoundCurrent = true;
1322*b7893ccfSSadaf Ebrahimi 
1323*b7893ccfSSadaf Ebrahimi     if (!aOffsetCount) {
1324*b7893ccfSSadaf Ebrahimi         delete[] offsetList;
1325*b7893ccfSSadaf Ebrahimi     }
1326*b7893ccfSSadaf Ebrahimi }
1327*b7893ccfSSadaf Ebrahimi 
OneOffDescriptorSet(VkDeviceObj * device,const Bindings & bindings,VkDescriptorSetLayoutCreateFlags layout_flags,void * layout_pnext,VkDescriptorPoolCreateFlags poolFlags,void * allocate_pnext)1328*b7893ccfSSadaf Ebrahimi OneOffDescriptorSet::OneOffDescriptorSet(VkDeviceObj *device, const Bindings &bindings,
1329*b7893ccfSSadaf Ebrahimi                                          VkDescriptorSetLayoutCreateFlags layout_flags, void *layout_pnext,
1330*b7893ccfSSadaf Ebrahimi                                          VkDescriptorPoolCreateFlags poolFlags, void *allocate_pnext)
1331*b7893ccfSSadaf Ebrahimi     : device_{device}, pool_{}, layout_(device, bindings, layout_flags, layout_pnext), set_{} {
1332*b7893ccfSSadaf Ebrahimi     VkResult err;
1333*b7893ccfSSadaf Ebrahimi 
1334*b7893ccfSSadaf Ebrahimi     std::vector<VkDescriptorPoolSize> sizes;
1335*b7893ccfSSadaf Ebrahimi     for (const auto &b : bindings) sizes.push_back({b.descriptorType, std::max(1u, b.descriptorCount)});
1336*b7893ccfSSadaf Ebrahimi 
1337*b7893ccfSSadaf Ebrahimi     VkDescriptorPoolCreateInfo dspci = {
1338*b7893ccfSSadaf Ebrahimi         VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, nullptr, poolFlags, 1, uint32_t(sizes.size()), sizes.data()};
1339*b7893ccfSSadaf Ebrahimi     err = vkCreateDescriptorPool(device_->handle(), &dspci, nullptr, &pool_);
1340*b7893ccfSSadaf Ebrahimi     if (err != VK_SUCCESS) return;
1341*b7893ccfSSadaf Ebrahimi 
1342*b7893ccfSSadaf Ebrahimi     VkDescriptorSetAllocateInfo alloc_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, allocate_pnext, pool_, 1,
1343*b7893ccfSSadaf Ebrahimi                                               &layout_.handle()};
1344*b7893ccfSSadaf Ebrahimi     err = vkAllocateDescriptorSets(device_->handle(), &alloc_info, &set_);
1345*b7893ccfSSadaf Ebrahimi }
1346*b7893ccfSSadaf Ebrahimi 
~OneOffDescriptorSet()1347*b7893ccfSSadaf Ebrahimi OneOffDescriptorSet::~OneOffDescriptorSet() {
1348*b7893ccfSSadaf Ebrahimi     // No need to destroy set-- it's going away with the pool.
1349*b7893ccfSSadaf Ebrahimi     vkDestroyDescriptorPool(device_->handle(), pool_, nullptr);
1350*b7893ccfSSadaf Ebrahimi }
1351*b7893ccfSSadaf Ebrahimi 
Initialized()1352*b7893ccfSSadaf Ebrahimi bool OneOffDescriptorSet::Initialized() { return pool_ != VK_NULL_HANDLE && layout_.initialized() && set_ != VK_NULL_HANDLE; }
1353*b7893ccfSSadaf Ebrahimi 
WriteDescriptorBufferInfo(int blinding,VkBuffer buffer,VkDeviceSize size,VkDescriptorType descriptorType)1354*b7893ccfSSadaf Ebrahimi void OneOffDescriptorSet::WriteDescriptorBufferInfo(int blinding, VkBuffer buffer, VkDeviceSize size,
1355*b7893ccfSSadaf Ebrahimi                                                     VkDescriptorType descriptorType) {
1356*b7893ccfSSadaf Ebrahimi     VkDescriptorBufferInfo buffer_info = {};
1357*b7893ccfSSadaf Ebrahimi     buffer_info.buffer = buffer;
1358*b7893ccfSSadaf Ebrahimi     buffer_info.offset = 0;
1359*b7893ccfSSadaf Ebrahimi     buffer_info.range = size;
1360*b7893ccfSSadaf Ebrahimi     buffer_infos.emplace_back(buffer_info);
1361*b7893ccfSSadaf Ebrahimi     size_t index = buffer_infos.size() - 1;
1362*b7893ccfSSadaf Ebrahimi 
1363*b7893ccfSSadaf Ebrahimi     VkWriteDescriptorSet descriptor_write;
1364*b7893ccfSSadaf Ebrahimi     memset(&descriptor_write, 0, sizeof(descriptor_write));
1365*b7893ccfSSadaf Ebrahimi     descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1366*b7893ccfSSadaf Ebrahimi     descriptor_write.dstSet = set_;
1367*b7893ccfSSadaf Ebrahimi     descriptor_write.dstBinding = blinding;
1368*b7893ccfSSadaf Ebrahimi     descriptor_write.descriptorCount = 1;
1369*b7893ccfSSadaf Ebrahimi     descriptor_write.descriptorType = descriptorType;
1370*b7893ccfSSadaf Ebrahimi     descriptor_write.pBufferInfo = &buffer_infos[index];
1371*b7893ccfSSadaf Ebrahimi     descriptor_write.pImageInfo = nullptr;
1372*b7893ccfSSadaf Ebrahimi     descriptor_write.pTexelBufferView = nullptr;
1373*b7893ccfSSadaf Ebrahimi 
1374*b7893ccfSSadaf Ebrahimi     descriptor_writes.emplace_back(descriptor_write);
1375*b7893ccfSSadaf Ebrahimi }
1376*b7893ccfSSadaf Ebrahimi 
WriteDescriptorBufferView(int blinding,VkBufferView & buffer_view,VkDescriptorType descriptorType)1377*b7893ccfSSadaf Ebrahimi void OneOffDescriptorSet::WriteDescriptorBufferView(int blinding, VkBufferView &buffer_view, VkDescriptorType descriptorType) {
1378*b7893ccfSSadaf Ebrahimi     VkWriteDescriptorSet descriptor_write;
1379*b7893ccfSSadaf Ebrahimi     memset(&descriptor_write, 0, sizeof(descriptor_write));
1380*b7893ccfSSadaf Ebrahimi     descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1381*b7893ccfSSadaf Ebrahimi     descriptor_write.dstSet = set_;
1382*b7893ccfSSadaf Ebrahimi     descriptor_write.dstBinding = blinding;
1383*b7893ccfSSadaf Ebrahimi     descriptor_write.descriptorCount = 1;
1384*b7893ccfSSadaf Ebrahimi     descriptor_write.descriptorType = descriptorType;
1385*b7893ccfSSadaf Ebrahimi     descriptor_write.pTexelBufferView = &buffer_view;
1386*b7893ccfSSadaf Ebrahimi     descriptor_write.pImageInfo = nullptr;
1387*b7893ccfSSadaf Ebrahimi     descriptor_write.pBufferInfo = nullptr;
1388*b7893ccfSSadaf Ebrahimi 
1389*b7893ccfSSadaf Ebrahimi     descriptor_writes.emplace_back(descriptor_write);
1390*b7893ccfSSadaf Ebrahimi }
1391*b7893ccfSSadaf Ebrahimi 
WriteDescriptorImageInfo(int blinding,VkImageView image_view,VkSampler sampler,VkDescriptorType descriptorType)1392*b7893ccfSSadaf Ebrahimi void OneOffDescriptorSet::WriteDescriptorImageInfo(int blinding, VkImageView image_view, VkSampler sampler,
1393*b7893ccfSSadaf Ebrahimi                                                    VkDescriptorType descriptorType) {
1394*b7893ccfSSadaf Ebrahimi     VkDescriptorImageInfo image_info = {};
1395*b7893ccfSSadaf Ebrahimi     image_info.imageView = image_view;
1396*b7893ccfSSadaf Ebrahimi     image_info.sampler = sampler;
1397*b7893ccfSSadaf Ebrahimi     image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
1398*b7893ccfSSadaf Ebrahimi     image_infos.emplace_back(image_info);
1399*b7893ccfSSadaf Ebrahimi     size_t index = image_infos.size() - 1;
1400*b7893ccfSSadaf Ebrahimi 
1401*b7893ccfSSadaf Ebrahimi     VkWriteDescriptorSet descriptor_write;
1402*b7893ccfSSadaf Ebrahimi     memset(&descriptor_write, 0, sizeof(descriptor_write));
1403*b7893ccfSSadaf Ebrahimi     descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1404*b7893ccfSSadaf Ebrahimi     descriptor_write.dstSet = set_;
1405*b7893ccfSSadaf Ebrahimi     descriptor_write.dstBinding = blinding;
1406*b7893ccfSSadaf Ebrahimi     descriptor_write.descriptorCount = 1;
1407*b7893ccfSSadaf Ebrahimi     descriptor_write.descriptorType = descriptorType;
1408*b7893ccfSSadaf Ebrahimi     descriptor_write.pImageInfo = &image_infos[index];
1409*b7893ccfSSadaf Ebrahimi     descriptor_write.pBufferInfo = nullptr;
1410*b7893ccfSSadaf Ebrahimi     descriptor_write.pTexelBufferView = nullptr;
1411*b7893ccfSSadaf Ebrahimi 
1412*b7893ccfSSadaf Ebrahimi     descriptor_writes.emplace_back(descriptor_write);
1413*b7893ccfSSadaf Ebrahimi }
1414*b7893ccfSSadaf Ebrahimi 
UpdateDescriptorSets()1415*b7893ccfSSadaf Ebrahimi void OneOffDescriptorSet::UpdateDescriptorSets() {
1416*b7893ccfSSadaf Ebrahimi     vkUpdateDescriptorSets(device_->handle(), descriptor_writes.size(), descriptor_writes.data(), 0, NULL);
1417*b7893ccfSSadaf Ebrahimi }
1418*b7893ccfSSadaf Ebrahimi 
CreatePipelineHelper(VkLayerTest & test)1419*b7893ccfSSadaf Ebrahimi CreatePipelineHelper::CreatePipelineHelper(VkLayerTest &test) : layer_test_(test) {}
1420*b7893ccfSSadaf Ebrahimi 
~CreatePipelineHelper()1421*b7893ccfSSadaf Ebrahimi CreatePipelineHelper::~CreatePipelineHelper() {
1422*b7893ccfSSadaf Ebrahimi     VkDevice device = layer_test_.device();
1423*b7893ccfSSadaf Ebrahimi     vkDestroyPipelineCache(device, pipeline_cache_, nullptr);
1424*b7893ccfSSadaf Ebrahimi     vkDestroyPipeline(device, pipeline_, nullptr);
1425*b7893ccfSSadaf Ebrahimi }
1426*b7893ccfSSadaf Ebrahimi 
InitDescriptorSetInfo()1427*b7893ccfSSadaf Ebrahimi void CreatePipelineHelper::InitDescriptorSetInfo() {
1428*b7893ccfSSadaf Ebrahimi     dsl_bindings_ = {{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}};
1429*b7893ccfSSadaf Ebrahimi }
1430*b7893ccfSSadaf Ebrahimi 
InitInputAndVertexInfo()1431*b7893ccfSSadaf Ebrahimi void CreatePipelineHelper::InitInputAndVertexInfo() {
1432*b7893ccfSSadaf Ebrahimi     vi_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
1433*b7893ccfSSadaf Ebrahimi 
1434*b7893ccfSSadaf Ebrahimi     ia_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
1435*b7893ccfSSadaf Ebrahimi     ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1436*b7893ccfSSadaf Ebrahimi }
1437*b7893ccfSSadaf Ebrahimi 
InitMultisampleInfo()1438*b7893ccfSSadaf Ebrahimi void CreatePipelineHelper::InitMultisampleInfo() {
1439*b7893ccfSSadaf Ebrahimi     pipe_ms_state_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
1440*b7893ccfSSadaf Ebrahimi     pipe_ms_state_ci_.pNext = nullptr;
1441*b7893ccfSSadaf Ebrahimi     pipe_ms_state_ci_.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
1442*b7893ccfSSadaf Ebrahimi     pipe_ms_state_ci_.sampleShadingEnable = VK_FALSE;
1443*b7893ccfSSadaf Ebrahimi     pipe_ms_state_ci_.minSampleShading = 1.0;
1444*b7893ccfSSadaf Ebrahimi     pipe_ms_state_ci_.pSampleMask = NULL;
1445*b7893ccfSSadaf Ebrahimi }
1446*b7893ccfSSadaf Ebrahimi 
InitPipelineLayoutInfo()1447*b7893ccfSSadaf Ebrahimi void CreatePipelineHelper::InitPipelineLayoutInfo() {
1448*b7893ccfSSadaf Ebrahimi     pipeline_layout_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
1449*b7893ccfSSadaf Ebrahimi     pipeline_layout_ci_.setLayoutCount = 1;     // Not really changeable because InitState() sets exactly one pSetLayout
1450*b7893ccfSSadaf Ebrahimi     pipeline_layout_ci_.pSetLayouts = nullptr;  // must bound after it is created
1451*b7893ccfSSadaf Ebrahimi }
1452*b7893ccfSSadaf Ebrahimi 
InitViewportInfo()1453*b7893ccfSSadaf Ebrahimi void CreatePipelineHelper::InitViewportInfo() {
1454*b7893ccfSSadaf Ebrahimi     viewport_ = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f};
1455*b7893ccfSSadaf Ebrahimi     scissor_ = {{0, 0}, {64, 64}};
1456*b7893ccfSSadaf Ebrahimi 
1457*b7893ccfSSadaf Ebrahimi     vp_state_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
1458*b7893ccfSSadaf Ebrahimi     vp_state_ci_.pNext = nullptr;
1459*b7893ccfSSadaf Ebrahimi     vp_state_ci_.viewportCount = 1;
1460*b7893ccfSSadaf Ebrahimi     vp_state_ci_.pViewports = &viewport_;  // ignored if dynamic
1461*b7893ccfSSadaf Ebrahimi     vp_state_ci_.scissorCount = 1;
1462*b7893ccfSSadaf Ebrahimi     vp_state_ci_.pScissors = &scissor_;  // ignored if dynamic
1463*b7893ccfSSadaf Ebrahimi }
1464*b7893ccfSSadaf Ebrahimi 
InitDynamicStateInfo()1465*b7893ccfSSadaf Ebrahimi void CreatePipelineHelper::InitDynamicStateInfo() {
1466*b7893ccfSSadaf Ebrahimi     // Use a "validity" check on the {} initialized structure to detect initialization
1467*b7893ccfSSadaf Ebrahimi     // during late bind
1468*b7893ccfSSadaf Ebrahimi }
1469*b7893ccfSSadaf Ebrahimi 
InitShaderInfo()1470*b7893ccfSSadaf Ebrahimi void CreatePipelineHelper::InitShaderInfo() {
1471*b7893ccfSSadaf Ebrahimi     vs_.reset(new VkShaderObj(layer_test_.DeviceObj(), bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, &layer_test_));
1472*b7893ccfSSadaf Ebrahimi     fs_.reset(new VkShaderObj(layer_test_.DeviceObj(), bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, &layer_test_));
1473*b7893ccfSSadaf Ebrahimi     // We shouldn't need a fragment shader but add it to be able to run on more devices
1474*b7893ccfSSadaf Ebrahimi     shader_stages_ = {vs_->GetStageCreateInfo(), fs_->GetStageCreateInfo()};
1475*b7893ccfSSadaf Ebrahimi }
1476*b7893ccfSSadaf Ebrahimi 
InitRasterizationInfo()1477*b7893ccfSSadaf Ebrahimi void CreatePipelineHelper::InitRasterizationInfo() {
1478*b7893ccfSSadaf Ebrahimi     rs_state_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
1479*b7893ccfSSadaf Ebrahimi     rs_state_ci_.pNext = &line_state_ci_;
1480*b7893ccfSSadaf Ebrahimi     rs_state_ci_.flags = 0;
1481*b7893ccfSSadaf Ebrahimi     rs_state_ci_.depthClampEnable = VK_FALSE;
1482*b7893ccfSSadaf Ebrahimi     rs_state_ci_.rasterizerDiscardEnable = VK_FALSE;
1483*b7893ccfSSadaf Ebrahimi     rs_state_ci_.polygonMode = VK_POLYGON_MODE_FILL;
1484*b7893ccfSSadaf Ebrahimi     rs_state_ci_.cullMode = VK_CULL_MODE_BACK_BIT;
1485*b7893ccfSSadaf Ebrahimi     rs_state_ci_.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
1486*b7893ccfSSadaf Ebrahimi     rs_state_ci_.depthBiasEnable = VK_FALSE;
1487*b7893ccfSSadaf Ebrahimi     rs_state_ci_.lineWidth = 1.0F;
1488*b7893ccfSSadaf Ebrahimi }
1489*b7893ccfSSadaf Ebrahimi 
InitLineRasterizationInfo()1490*b7893ccfSSadaf Ebrahimi void CreatePipelineHelper::InitLineRasterizationInfo() {
1491*b7893ccfSSadaf Ebrahimi     line_state_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
1492*b7893ccfSSadaf Ebrahimi     line_state_ci_.pNext = nullptr;
1493*b7893ccfSSadaf Ebrahimi     line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
1494*b7893ccfSSadaf Ebrahimi     line_state_ci_.stippledLineEnable = VK_FALSE;
1495*b7893ccfSSadaf Ebrahimi     line_state_ci_.lineStippleFactor = 0;
1496*b7893ccfSSadaf Ebrahimi     line_state_ci_.lineStipplePattern = 0;
1497*b7893ccfSSadaf Ebrahimi }
1498*b7893ccfSSadaf Ebrahimi 
InitBlendStateInfo()1499*b7893ccfSSadaf Ebrahimi void CreatePipelineHelper::InitBlendStateInfo() {
1500*b7893ccfSSadaf Ebrahimi     cb_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
1501*b7893ccfSSadaf Ebrahimi     cb_ci_.logicOpEnable = VK_FALSE;
1502*b7893ccfSSadaf Ebrahimi     cb_ci_.logicOp = VK_LOGIC_OP_COPY;  // ignored if enable is VK_FALSE above
1503*b7893ccfSSadaf Ebrahimi     cb_ci_.attachmentCount = layer_test_.RenderPassInfo().subpassCount;
1504*b7893ccfSSadaf Ebrahimi     ASSERT_TRUE(IsValidVkStruct(layer_test_.RenderPassInfo()));
1505*b7893ccfSSadaf Ebrahimi     cb_ci_.pAttachments = &cb_attachments_;
1506*b7893ccfSSadaf Ebrahimi     for (int i = 0; i < 4; i++) {
1507*b7893ccfSSadaf Ebrahimi         cb_ci_.blendConstants[0] = 1.0F;
1508*b7893ccfSSadaf Ebrahimi     }
1509*b7893ccfSSadaf Ebrahimi }
1510*b7893ccfSSadaf Ebrahimi 
InitGraphicsPipelineInfo()1511*b7893ccfSSadaf Ebrahimi void CreatePipelineHelper::InitGraphicsPipelineInfo() {
1512*b7893ccfSSadaf Ebrahimi     // Color-only rendering in a subpass with no depth/stencil attachment
1513*b7893ccfSSadaf Ebrahimi     // Active Pipeline Shader Stages
1514*b7893ccfSSadaf Ebrahimi     //    Vertex Shader
1515*b7893ccfSSadaf Ebrahimi     //    Fragment Shader
1516*b7893ccfSSadaf Ebrahimi     // Required: Fixed-Function Pipeline Stages
1517*b7893ccfSSadaf Ebrahimi     //    VkPipelineVertexInputStateCreateInfo
1518*b7893ccfSSadaf Ebrahimi     //    VkPipelineInputAssemblyStateCreateInfo
1519*b7893ccfSSadaf Ebrahimi     //    VkPipelineViewportStateCreateInfo
1520*b7893ccfSSadaf Ebrahimi     //    VkPipelineRasterizationStateCreateInfo
1521*b7893ccfSSadaf Ebrahimi     //    VkPipelineMultisampleStateCreateInfo
1522*b7893ccfSSadaf Ebrahimi     //    VkPipelineColorBlendStateCreateInfo
1523*b7893ccfSSadaf Ebrahimi     gp_ci_.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
1524*b7893ccfSSadaf Ebrahimi     gp_ci_.pNext = nullptr;
1525*b7893ccfSSadaf Ebrahimi     gp_ci_.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT;
1526*b7893ccfSSadaf Ebrahimi     gp_ci_.pVertexInputState = &vi_ci_;
1527*b7893ccfSSadaf Ebrahimi     gp_ci_.pInputAssemblyState = &ia_ci_;
1528*b7893ccfSSadaf Ebrahimi     gp_ci_.pTessellationState = nullptr;
1529*b7893ccfSSadaf Ebrahimi     gp_ci_.pViewportState = &vp_state_ci_;
1530*b7893ccfSSadaf Ebrahimi     gp_ci_.pRasterizationState = &rs_state_ci_;
1531*b7893ccfSSadaf Ebrahimi     gp_ci_.pMultisampleState = &pipe_ms_state_ci_;
1532*b7893ccfSSadaf Ebrahimi     gp_ci_.pDepthStencilState = nullptr;
1533*b7893ccfSSadaf Ebrahimi     gp_ci_.pColorBlendState = &cb_ci_;
1534*b7893ccfSSadaf Ebrahimi     gp_ci_.pDynamicState = nullptr;
1535*b7893ccfSSadaf Ebrahimi     gp_ci_.renderPass = layer_test_.renderPass();
1536*b7893ccfSSadaf Ebrahimi }
1537*b7893ccfSSadaf Ebrahimi 
InitPipelineCacheInfo()1538*b7893ccfSSadaf Ebrahimi void CreatePipelineHelper::InitPipelineCacheInfo() {
1539*b7893ccfSSadaf Ebrahimi     pc_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
1540*b7893ccfSSadaf Ebrahimi     pc_ci_.pNext = nullptr;
1541*b7893ccfSSadaf Ebrahimi     pc_ci_.flags = 0;
1542*b7893ccfSSadaf Ebrahimi     pc_ci_.initialDataSize = 0;
1543*b7893ccfSSadaf Ebrahimi     pc_ci_.pInitialData = nullptr;
1544*b7893ccfSSadaf Ebrahimi }
1545*b7893ccfSSadaf Ebrahimi 
InitTesselationState()1546*b7893ccfSSadaf Ebrahimi void CreatePipelineHelper::InitTesselationState() {
1547*b7893ccfSSadaf Ebrahimi     // TBD -- add shaders and create_info
1548*b7893ccfSSadaf Ebrahimi }
1549*b7893ccfSSadaf Ebrahimi 
InitInfo()1550*b7893ccfSSadaf Ebrahimi void CreatePipelineHelper::InitInfo() {
1551*b7893ccfSSadaf Ebrahimi     InitDescriptorSetInfo();
1552*b7893ccfSSadaf Ebrahimi     InitInputAndVertexInfo();
1553*b7893ccfSSadaf Ebrahimi     InitMultisampleInfo();
1554*b7893ccfSSadaf Ebrahimi     InitPipelineLayoutInfo();
1555*b7893ccfSSadaf Ebrahimi     InitViewportInfo();
1556*b7893ccfSSadaf Ebrahimi     InitDynamicStateInfo();
1557*b7893ccfSSadaf Ebrahimi     InitShaderInfo();
1558*b7893ccfSSadaf Ebrahimi     InitRasterizationInfo();
1559*b7893ccfSSadaf Ebrahimi     InitLineRasterizationInfo();
1560*b7893ccfSSadaf Ebrahimi     InitBlendStateInfo();
1561*b7893ccfSSadaf Ebrahimi     InitGraphicsPipelineInfo();
1562*b7893ccfSSadaf Ebrahimi     InitPipelineCacheInfo();
1563*b7893ccfSSadaf Ebrahimi }
1564*b7893ccfSSadaf Ebrahimi 
InitState()1565*b7893ccfSSadaf Ebrahimi void CreatePipelineHelper::InitState() {
1566*b7893ccfSSadaf Ebrahimi     VkResult err;
1567*b7893ccfSSadaf Ebrahimi     descriptor_set_.reset(new OneOffDescriptorSet(layer_test_.DeviceObj(), dsl_bindings_));
1568*b7893ccfSSadaf Ebrahimi     ASSERT_TRUE(descriptor_set_->Initialized());
1569*b7893ccfSSadaf Ebrahimi 
1570*b7893ccfSSadaf Ebrahimi     const std::vector<VkPushConstantRange> push_ranges(
1571*b7893ccfSSadaf Ebrahimi         pipeline_layout_ci_.pPushConstantRanges,
1572*b7893ccfSSadaf Ebrahimi         pipeline_layout_ci_.pPushConstantRanges + pipeline_layout_ci_.pushConstantRangeCount);
1573*b7893ccfSSadaf Ebrahimi     pipeline_layout_ = VkPipelineLayoutObj(layer_test_.DeviceObj(), {&descriptor_set_->layout_}, push_ranges);
1574*b7893ccfSSadaf Ebrahimi 
1575*b7893ccfSSadaf Ebrahimi     err = vkCreatePipelineCache(layer_test_.device(), &pc_ci_, NULL, &pipeline_cache_);
1576*b7893ccfSSadaf Ebrahimi     ASSERT_VK_SUCCESS(err);
1577*b7893ccfSSadaf Ebrahimi }
1578*b7893ccfSSadaf Ebrahimi 
LateBindPipelineInfo()1579*b7893ccfSSadaf Ebrahimi void CreatePipelineHelper::LateBindPipelineInfo() {
1580*b7893ccfSSadaf Ebrahimi     // By value or dynamically located items must be late bound
1581*b7893ccfSSadaf Ebrahimi     gp_ci_.layout = pipeline_layout_.handle();
1582*b7893ccfSSadaf Ebrahimi     gp_ci_.stageCount = shader_stages_.size();
1583*b7893ccfSSadaf Ebrahimi     gp_ci_.pStages = shader_stages_.data();
1584*b7893ccfSSadaf Ebrahimi     if ((gp_ci_.pTessellationState == nullptr) && IsValidVkStruct(tess_ci_)) {
1585*b7893ccfSSadaf Ebrahimi         gp_ci_.pTessellationState = &tess_ci_;
1586*b7893ccfSSadaf Ebrahimi     }
1587*b7893ccfSSadaf Ebrahimi     if ((gp_ci_.pDynamicState == nullptr) && IsValidVkStruct(dyn_state_ci_)) {
1588*b7893ccfSSadaf Ebrahimi         gp_ci_.pDynamicState = &dyn_state_ci_;
1589*b7893ccfSSadaf Ebrahimi     }
1590*b7893ccfSSadaf Ebrahimi }
1591*b7893ccfSSadaf Ebrahimi 
CreateGraphicsPipeline(bool implicit_destroy,bool do_late_bind)1592*b7893ccfSSadaf Ebrahimi VkResult CreatePipelineHelper::CreateGraphicsPipeline(bool implicit_destroy, bool do_late_bind) {
1593*b7893ccfSSadaf Ebrahimi     VkResult err;
1594*b7893ccfSSadaf Ebrahimi     if (do_late_bind) {
1595*b7893ccfSSadaf Ebrahimi         LateBindPipelineInfo();
1596*b7893ccfSSadaf Ebrahimi     }
1597*b7893ccfSSadaf Ebrahimi     if (implicit_destroy && (pipeline_ != VK_NULL_HANDLE)) {
1598*b7893ccfSSadaf Ebrahimi         vkDestroyPipeline(layer_test_.device(), pipeline_, nullptr);
1599*b7893ccfSSadaf Ebrahimi         pipeline_ = VK_NULL_HANDLE;
1600*b7893ccfSSadaf Ebrahimi     }
1601*b7893ccfSSadaf Ebrahimi     err = vkCreateGraphicsPipelines(layer_test_.device(), pipeline_cache_, 1, &gp_ci_, NULL, &pipeline_);
1602*b7893ccfSSadaf Ebrahimi     return err;
1603*b7893ccfSSadaf Ebrahimi }
1604*b7893ccfSSadaf Ebrahimi 
CreateComputePipelineHelper(VkLayerTest & test)1605*b7893ccfSSadaf Ebrahimi CreateComputePipelineHelper::CreateComputePipelineHelper(VkLayerTest &test) : layer_test_(test) {}
1606*b7893ccfSSadaf Ebrahimi 
~CreateComputePipelineHelper()1607*b7893ccfSSadaf Ebrahimi CreateComputePipelineHelper::~CreateComputePipelineHelper() {
1608*b7893ccfSSadaf Ebrahimi     VkDevice device = layer_test_.device();
1609*b7893ccfSSadaf Ebrahimi     vkDestroyPipelineCache(device, pipeline_cache_, nullptr);
1610*b7893ccfSSadaf Ebrahimi     vkDestroyPipeline(device, pipeline_, nullptr);
1611*b7893ccfSSadaf Ebrahimi }
1612*b7893ccfSSadaf Ebrahimi 
InitDescriptorSetInfo()1613*b7893ccfSSadaf Ebrahimi void CreateComputePipelineHelper::InitDescriptorSetInfo() {
1614*b7893ccfSSadaf Ebrahimi     dsl_bindings_ = {{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}};
1615*b7893ccfSSadaf Ebrahimi }
1616*b7893ccfSSadaf Ebrahimi 
InitPipelineLayoutInfo()1617*b7893ccfSSadaf Ebrahimi void CreateComputePipelineHelper::InitPipelineLayoutInfo() {
1618*b7893ccfSSadaf Ebrahimi     pipeline_layout_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
1619*b7893ccfSSadaf Ebrahimi     pipeline_layout_ci_.setLayoutCount = 1;     // Not really changeable because InitState() sets exactly one pSetLayout
1620*b7893ccfSSadaf Ebrahimi     pipeline_layout_ci_.pSetLayouts = nullptr;  // must bound after it is created
1621*b7893ccfSSadaf Ebrahimi }
1622*b7893ccfSSadaf Ebrahimi 
InitShaderInfo()1623*b7893ccfSSadaf Ebrahimi void CreateComputePipelineHelper::InitShaderInfo() {
1624*b7893ccfSSadaf Ebrahimi     cs_.reset(new VkShaderObj(layer_test_.DeviceObj(), bindStateMinimalShaderText, VK_SHADER_STAGE_COMPUTE_BIT, &layer_test_));
1625*b7893ccfSSadaf Ebrahimi     // We shouldn't need a fragment shader but add it to be able to run on more devices
1626*b7893ccfSSadaf Ebrahimi }
1627*b7893ccfSSadaf Ebrahimi 
InitComputePipelineInfo()1628*b7893ccfSSadaf Ebrahimi void CreateComputePipelineHelper::InitComputePipelineInfo() {
1629*b7893ccfSSadaf Ebrahimi     cp_ci_.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
1630*b7893ccfSSadaf Ebrahimi     cp_ci_.pNext = nullptr;
1631*b7893ccfSSadaf Ebrahimi     cp_ci_.flags = 0;
1632*b7893ccfSSadaf Ebrahimi }
1633*b7893ccfSSadaf Ebrahimi 
InitPipelineCacheInfo()1634*b7893ccfSSadaf Ebrahimi void CreateComputePipelineHelper::InitPipelineCacheInfo() {
1635*b7893ccfSSadaf Ebrahimi     pc_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
1636*b7893ccfSSadaf Ebrahimi     pc_ci_.pNext = nullptr;
1637*b7893ccfSSadaf Ebrahimi     pc_ci_.flags = 0;
1638*b7893ccfSSadaf Ebrahimi     pc_ci_.initialDataSize = 0;
1639*b7893ccfSSadaf Ebrahimi     pc_ci_.pInitialData = nullptr;
1640*b7893ccfSSadaf Ebrahimi }
1641*b7893ccfSSadaf Ebrahimi 
InitInfo()1642*b7893ccfSSadaf Ebrahimi void CreateComputePipelineHelper::InitInfo() {
1643*b7893ccfSSadaf Ebrahimi     InitDescriptorSetInfo();
1644*b7893ccfSSadaf Ebrahimi     InitPipelineLayoutInfo();
1645*b7893ccfSSadaf Ebrahimi     InitShaderInfo();
1646*b7893ccfSSadaf Ebrahimi     InitComputePipelineInfo();
1647*b7893ccfSSadaf Ebrahimi     InitPipelineCacheInfo();
1648*b7893ccfSSadaf Ebrahimi }
1649*b7893ccfSSadaf Ebrahimi 
InitState()1650*b7893ccfSSadaf Ebrahimi void CreateComputePipelineHelper::InitState() {
1651*b7893ccfSSadaf Ebrahimi     VkResult err;
1652*b7893ccfSSadaf Ebrahimi     descriptor_set_.reset(new OneOffDescriptorSet(layer_test_.DeviceObj(), dsl_bindings_));
1653*b7893ccfSSadaf Ebrahimi     ASSERT_TRUE(descriptor_set_->Initialized());
1654*b7893ccfSSadaf Ebrahimi 
1655*b7893ccfSSadaf Ebrahimi     const std::vector<VkPushConstantRange> push_ranges(
1656*b7893ccfSSadaf Ebrahimi         pipeline_layout_ci_.pPushConstantRanges,
1657*b7893ccfSSadaf Ebrahimi         pipeline_layout_ci_.pPushConstantRanges + pipeline_layout_ci_.pushConstantRangeCount);
1658*b7893ccfSSadaf Ebrahimi     pipeline_layout_ = VkPipelineLayoutObj(layer_test_.DeviceObj(), {&descriptor_set_->layout_}, push_ranges);
1659*b7893ccfSSadaf Ebrahimi 
1660*b7893ccfSSadaf Ebrahimi     err = vkCreatePipelineCache(layer_test_.device(), &pc_ci_, NULL, &pipeline_cache_);
1661*b7893ccfSSadaf Ebrahimi     ASSERT_VK_SUCCESS(err);
1662*b7893ccfSSadaf Ebrahimi }
1663*b7893ccfSSadaf Ebrahimi 
LateBindPipelineInfo()1664*b7893ccfSSadaf Ebrahimi void CreateComputePipelineHelper::LateBindPipelineInfo() {
1665*b7893ccfSSadaf Ebrahimi     // By value or dynamically located items must be late bound
1666*b7893ccfSSadaf Ebrahimi     cp_ci_.layout = pipeline_layout_.handle();
1667*b7893ccfSSadaf Ebrahimi     cp_ci_.stage = cs_.get()->GetStageCreateInfo();
1668*b7893ccfSSadaf Ebrahimi }
1669*b7893ccfSSadaf Ebrahimi 
CreateComputePipeline(bool implicit_destroy,bool do_late_bind)1670*b7893ccfSSadaf Ebrahimi VkResult CreateComputePipelineHelper::CreateComputePipeline(bool implicit_destroy, bool do_late_bind) {
1671*b7893ccfSSadaf Ebrahimi     VkResult err;
1672*b7893ccfSSadaf Ebrahimi     if (do_late_bind) {
1673*b7893ccfSSadaf Ebrahimi         LateBindPipelineInfo();
1674*b7893ccfSSadaf Ebrahimi     }
1675*b7893ccfSSadaf Ebrahimi     if (implicit_destroy && (pipeline_ != VK_NULL_HANDLE)) {
1676*b7893ccfSSadaf Ebrahimi         vkDestroyPipeline(layer_test_.device(), pipeline_, nullptr);
1677*b7893ccfSSadaf Ebrahimi         pipeline_ = VK_NULL_HANDLE;
1678*b7893ccfSSadaf Ebrahimi     }
1679*b7893ccfSSadaf Ebrahimi     err = vkCreateComputePipelines(layer_test_.device(), pipeline_cache_, 1, &cp_ci_, NULL, &pipeline_);
1680*b7893ccfSSadaf Ebrahimi     return err;
1681*b7893ccfSSadaf Ebrahimi }
1682*b7893ccfSSadaf Ebrahimi 
CreateNVRayTracingPipelineHelper(VkLayerTest & test)1683*b7893ccfSSadaf Ebrahimi CreateNVRayTracingPipelineHelper::CreateNVRayTracingPipelineHelper(VkLayerTest &test) : layer_test_(test) {}
~CreateNVRayTracingPipelineHelper()1684*b7893ccfSSadaf Ebrahimi CreateNVRayTracingPipelineHelper::~CreateNVRayTracingPipelineHelper() {
1685*b7893ccfSSadaf Ebrahimi     VkDevice device = layer_test_.device();
1686*b7893ccfSSadaf Ebrahimi     vkDestroyPipelineCache(device, pipeline_cache_, nullptr);
1687*b7893ccfSSadaf Ebrahimi     vkDestroyPipeline(device, pipeline_, nullptr);
1688*b7893ccfSSadaf Ebrahimi }
1689*b7893ccfSSadaf Ebrahimi 
InitInstanceExtensions(VkLayerTest & test,std::vector<const char * > & instance_extension_names)1690*b7893ccfSSadaf Ebrahimi bool CreateNVRayTracingPipelineHelper::InitInstanceExtensions(VkLayerTest &test,
1691*b7893ccfSSadaf Ebrahimi                                                               std::vector<const char *> &instance_extension_names) {
1692*b7893ccfSSadaf Ebrahimi     if (test.InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
1693*b7893ccfSSadaf Ebrahimi         instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1694*b7893ccfSSadaf Ebrahimi     } else {
1695*b7893ccfSSadaf Ebrahimi         printf("%s Did not find required instance extension %s; skipped.\n", kSkipPrefix,
1696*b7893ccfSSadaf Ebrahimi                VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1697*b7893ccfSSadaf Ebrahimi         return false;
1698*b7893ccfSSadaf Ebrahimi     }
1699*b7893ccfSSadaf Ebrahimi     return true;
1700*b7893ccfSSadaf Ebrahimi }
1701*b7893ccfSSadaf Ebrahimi 
InitDeviceExtensions(VkLayerTest & test,std::vector<const char * > & device_extension_names)1702*b7893ccfSSadaf Ebrahimi bool CreateNVRayTracingPipelineHelper::InitDeviceExtensions(VkLayerTest &test, std::vector<const char *> &device_extension_names) {
1703*b7893ccfSSadaf Ebrahimi     std::array<const char *, 2> required_device_extensions = {
1704*b7893ccfSSadaf Ebrahimi         {VK_NV_RAY_TRACING_EXTENSION_NAME, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME}};
1705*b7893ccfSSadaf Ebrahimi     for (auto device_extension : required_device_extensions) {
1706*b7893ccfSSadaf Ebrahimi         if (test.DeviceExtensionSupported(test.gpu(), nullptr, device_extension)) {
1707*b7893ccfSSadaf Ebrahimi             device_extension_names.push_back(device_extension);
1708*b7893ccfSSadaf Ebrahimi         } else {
1709*b7893ccfSSadaf Ebrahimi             printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, device_extension);
1710*b7893ccfSSadaf Ebrahimi             return false;
1711*b7893ccfSSadaf Ebrahimi         }
1712*b7893ccfSSadaf Ebrahimi     }
1713*b7893ccfSSadaf Ebrahimi     return true;
1714*b7893ccfSSadaf Ebrahimi }
1715*b7893ccfSSadaf Ebrahimi 
InitShaderGroups()1716*b7893ccfSSadaf Ebrahimi void CreateNVRayTracingPipelineHelper::InitShaderGroups() {
1717*b7893ccfSSadaf Ebrahimi     {
1718*b7893ccfSSadaf Ebrahimi         VkRayTracingShaderGroupCreateInfoNV group = {};
1719*b7893ccfSSadaf Ebrahimi         group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV;
1720*b7893ccfSSadaf Ebrahimi         group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV;
1721*b7893ccfSSadaf Ebrahimi         group.generalShader = 0;
1722*b7893ccfSSadaf Ebrahimi         group.closestHitShader = VK_SHADER_UNUSED_NV;
1723*b7893ccfSSadaf Ebrahimi         group.anyHitShader = VK_SHADER_UNUSED_NV;
1724*b7893ccfSSadaf Ebrahimi         group.intersectionShader = VK_SHADER_UNUSED_NV;
1725*b7893ccfSSadaf Ebrahimi         groups_.push_back(group);
1726*b7893ccfSSadaf Ebrahimi     }
1727*b7893ccfSSadaf Ebrahimi     {
1728*b7893ccfSSadaf Ebrahimi         VkRayTracingShaderGroupCreateInfoNV group = {};
1729*b7893ccfSSadaf Ebrahimi         group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV;
1730*b7893ccfSSadaf Ebrahimi         group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV;
1731*b7893ccfSSadaf Ebrahimi         group.generalShader = VK_SHADER_UNUSED_NV;
1732*b7893ccfSSadaf Ebrahimi         group.closestHitShader = 1;
1733*b7893ccfSSadaf Ebrahimi         group.anyHitShader = VK_SHADER_UNUSED_NV;
1734*b7893ccfSSadaf Ebrahimi         group.intersectionShader = VK_SHADER_UNUSED_NV;
1735*b7893ccfSSadaf Ebrahimi         groups_.push_back(group);
1736*b7893ccfSSadaf Ebrahimi     }
1737*b7893ccfSSadaf Ebrahimi     {
1738*b7893ccfSSadaf Ebrahimi         VkRayTracingShaderGroupCreateInfoNV group = {};
1739*b7893ccfSSadaf Ebrahimi         group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV;
1740*b7893ccfSSadaf Ebrahimi         group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV;
1741*b7893ccfSSadaf Ebrahimi         group.generalShader = 2;
1742*b7893ccfSSadaf Ebrahimi         group.closestHitShader = VK_SHADER_UNUSED_NV;
1743*b7893ccfSSadaf Ebrahimi         group.anyHitShader = VK_SHADER_UNUSED_NV;
1744*b7893ccfSSadaf Ebrahimi         group.intersectionShader = VK_SHADER_UNUSED_NV;
1745*b7893ccfSSadaf Ebrahimi         groups_.push_back(group);
1746*b7893ccfSSadaf Ebrahimi     }
1747*b7893ccfSSadaf Ebrahimi }
1748*b7893ccfSSadaf Ebrahimi 
InitDescriptorSetInfo()1749*b7893ccfSSadaf Ebrahimi void CreateNVRayTracingPipelineHelper::InitDescriptorSetInfo() {
1750*b7893ccfSSadaf Ebrahimi     dsl_bindings_ = {
1751*b7893ccfSSadaf Ebrahimi         {0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_RAYGEN_BIT_NV, nullptr},
1752*b7893ccfSSadaf Ebrahimi         {1, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV, 1, VK_SHADER_STAGE_RAYGEN_BIT_NV, nullptr},
1753*b7893ccfSSadaf Ebrahimi     };
1754*b7893ccfSSadaf Ebrahimi }
1755*b7893ccfSSadaf Ebrahimi 
InitPipelineLayoutInfo()1756*b7893ccfSSadaf Ebrahimi void CreateNVRayTracingPipelineHelper::InitPipelineLayoutInfo() {
1757*b7893ccfSSadaf Ebrahimi     pipeline_layout_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
1758*b7893ccfSSadaf Ebrahimi     pipeline_layout_ci_.setLayoutCount = 1;     // Not really changeable because InitState() sets exactly one pSetLayout
1759*b7893ccfSSadaf Ebrahimi     pipeline_layout_ci_.pSetLayouts = nullptr;  // must bound after it is created
1760*b7893ccfSSadaf Ebrahimi }
1761*b7893ccfSSadaf Ebrahimi 
InitShaderInfo()1762*b7893ccfSSadaf Ebrahimi void CreateNVRayTracingPipelineHelper::InitShaderInfo() {  // DONE
1763*b7893ccfSSadaf Ebrahimi     static const char rayGenShaderText[] =
1764*b7893ccfSSadaf Ebrahimi         "#version 460 core                                                \n"
1765*b7893ccfSSadaf Ebrahimi         "#extension GL_NV_ray_tracing : require                           \n"
1766*b7893ccfSSadaf Ebrahimi         "layout(set = 0, binding = 0, rgba8) uniform image2D image;       \n"
1767*b7893ccfSSadaf Ebrahimi         "layout(set = 0, binding = 1) uniform accelerationStructureNV as; \n"
1768*b7893ccfSSadaf Ebrahimi         "                                                                 \n"
1769*b7893ccfSSadaf Ebrahimi         "layout(location = 0) rayPayloadNV float payload;                 \n"
1770*b7893ccfSSadaf Ebrahimi         "                                                                 \n"
1771*b7893ccfSSadaf Ebrahimi         "void main()                                                      \n"
1772*b7893ccfSSadaf Ebrahimi         "{                                                                \n"
1773*b7893ccfSSadaf Ebrahimi         "   vec4 col = vec4(0, 0, 0, 1);                                  \n"
1774*b7893ccfSSadaf Ebrahimi         "                                                                 \n"
1775*b7893ccfSSadaf Ebrahimi         "   vec3 origin = vec3(float(gl_LaunchIDNV.x)/float(gl_LaunchSizeNV.x), "
1776*b7893ccfSSadaf Ebrahimi         "float(gl_LaunchIDNV.y)/float(gl_LaunchSizeNV.y), "
1777*b7893ccfSSadaf Ebrahimi         "1.0); \n"
1778*b7893ccfSSadaf Ebrahimi         "   vec3 dir = vec3(0.0, 0.0, -1.0);                              \n"
1779*b7893ccfSSadaf Ebrahimi         "                                                                 \n"
1780*b7893ccfSSadaf Ebrahimi         "   payload = 0.5;                                                \n"
1781*b7893ccfSSadaf Ebrahimi         "   traceNV(as, gl_RayFlagsCullBackFacingTrianglesNV, 0xff, 0, 1, 0, origin, 0.0, dir, 1000.0, 0); \n"
1782*b7893ccfSSadaf Ebrahimi         "                                                                 \n"
1783*b7893ccfSSadaf Ebrahimi         "   col.y = payload;                                              \n"
1784*b7893ccfSSadaf Ebrahimi         "                                                                 \n"
1785*b7893ccfSSadaf Ebrahimi         "   imageStore(image, ivec2(gl_LaunchIDNV.xy), col);              \n"
1786*b7893ccfSSadaf Ebrahimi         "}\n";
1787*b7893ccfSSadaf Ebrahimi 
1788*b7893ccfSSadaf Ebrahimi     static char const closestHitShaderText[] =
1789*b7893ccfSSadaf Ebrahimi         "#version 460 core                              \n"
1790*b7893ccfSSadaf Ebrahimi         "#extension GL_NV_ray_tracing : require         \n"
1791*b7893ccfSSadaf Ebrahimi         "layout(location = 0) rayPayloadInNV float hitValue;             \n"
1792*b7893ccfSSadaf Ebrahimi         "                                               \n"
1793*b7893ccfSSadaf Ebrahimi         "void main() {                                  \n"
1794*b7893ccfSSadaf Ebrahimi         "    hitValue = 1.0;                            \n"
1795*b7893ccfSSadaf Ebrahimi         "}                                              \n";
1796*b7893ccfSSadaf Ebrahimi 
1797*b7893ccfSSadaf Ebrahimi     static char const missShaderText[] =
1798*b7893ccfSSadaf Ebrahimi         "#version 460 core                              \n"
1799*b7893ccfSSadaf Ebrahimi         "#extension GL_NV_ray_tracing : require         \n"
1800*b7893ccfSSadaf Ebrahimi         "layout(location = 0) rayPayloadInNV float hitValue; \n"
1801*b7893ccfSSadaf Ebrahimi         "                                               \n"
1802*b7893ccfSSadaf Ebrahimi         "void main() {                                  \n"
1803*b7893ccfSSadaf Ebrahimi         "    hitValue = 0.0;                            \n"
1804*b7893ccfSSadaf Ebrahimi         "}                                              \n";
1805*b7893ccfSSadaf Ebrahimi 
1806*b7893ccfSSadaf Ebrahimi     rgs_.reset(new VkShaderObj(layer_test_.DeviceObj(), rayGenShaderText, VK_SHADER_STAGE_RAYGEN_BIT_NV, &layer_test_));
1807*b7893ccfSSadaf Ebrahimi     chs_.reset(new VkShaderObj(layer_test_.DeviceObj(), closestHitShaderText, VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV, &layer_test_));
1808*b7893ccfSSadaf Ebrahimi     mis_.reset(new VkShaderObj(layer_test_.DeviceObj(), missShaderText, VK_SHADER_STAGE_MISS_BIT_NV, &layer_test_));
1809*b7893ccfSSadaf Ebrahimi 
1810*b7893ccfSSadaf Ebrahimi     shader_stages_ = {rgs_->GetStageCreateInfo(), chs_->GetStageCreateInfo(), mis_->GetStageCreateInfo()};
1811*b7893ccfSSadaf Ebrahimi }
1812*b7893ccfSSadaf Ebrahimi 
InitNVRayTracingPipelineInfo()1813*b7893ccfSSadaf Ebrahimi void CreateNVRayTracingPipelineHelper::InitNVRayTracingPipelineInfo() {
1814*b7893ccfSSadaf Ebrahimi     rp_ci_.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV;
1815*b7893ccfSSadaf Ebrahimi 
1816*b7893ccfSSadaf Ebrahimi     rp_ci_.stageCount = shader_stages_.size();
1817*b7893ccfSSadaf Ebrahimi     rp_ci_.pStages = shader_stages_.data();
1818*b7893ccfSSadaf Ebrahimi     rp_ci_.groupCount = groups_.size();
1819*b7893ccfSSadaf Ebrahimi     rp_ci_.pGroups = groups_.data();
1820*b7893ccfSSadaf Ebrahimi }
1821*b7893ccfSSadaf Ebrahimi 
InitPipelineCacheInfo()1822*b7893ccfSSadaf Ebrahimi void CreateNVRayTracingPipelineHelper::InitPipelineCacheInfo() {
1823*b7893ccfSSadaf Ebrahimi     pc_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
1824*b7893ccfSSadaf Ebrahimi     pc_ci_.pNext = nullptr;
1825*b7893ccfSSadaf Ebrahimi     pc_ci_.flags = 0;
1826*b7893ccfSSadaf Ebrahimi     pc_ci_.initialDataSize = 0;
1827*b7893ccfSSadaf Ebrahimi     pc_ci_.pInitialData = nullptr;
1828*b7893ccfSSadaf Ebrahimi }
1829*b7893ccfSSadaf Ebrahimi 
InitInfo()1830*b7893ccfSSadaf Ebrahimi void CreateNVRayTracingPipelineHelper::InitInfo() {
1831*b7893ccfSSadaf Ebrahimi     InitShaderGroups();
1832*b7893ccfSSadaf Ebrahimi     InitDescriptorSetInfo();
1833*b7893ccfSSadaf Ebrahimi     InitPipelineLayoutInfo();
1834*b7893ccfSSadaf Ebrahimi     InitShaderInfo();
1835*b7893ccfSSadaf Ebrahimi     InitNVRayTracingPipelineInfo();
1836*b7893ccfSSadaf Ebrahimi     InitPipelineCacheInfo();
1837*b7893ccfSSadaf Ebrahimi }
1838*b7893ccfSSadaf Ebrahimi 
InitState()1839*b7893ccfSSadaf Ebrahimi void CreateNVRayTracingPipelineHelper::InitState() {
1840*b7893ccfSSadaf Ebrahimi     VkResult err;
1841*b7893ccfSSadaf Ebrahimi     descriptor_set_.reset(new OneOffDescriptorSet(layer_test_.DeviceObj(), dsl_bindings_));
1842*b7893ccfSSadaf Ebrahimi     ASSERT_TRUE(descriptor_set_->Initialized());
1843*b7893ccfSSadaf Ebrahimi 
1844*b7893ccfSSadaf Ebrahimi     pipeline_layout_ = VkPipelineLayoutObj(layer_test_.DeviceObj(), {&descriptor_set_->layout_});
1845*b7893ccfSSadaf Ebrahimi 
1846*b7893ccfSSadaf Ebrahimi     err = vkCreatePipelineCache(layer_test_.device(), &pc_ci_, NULL, &pipeline_cache_);
1847*b7893ccfSSadaf Ebrahimi     ASSERT_VK_SUCCESS(err);
1848*b7893ccfSSadaf Ebrahimi }
1849*b7893ccfSSadaf Ebrahimi 
LateBindPipelineInfo()1850*b7893ccfSSadaf Ebrahimi void CreateNVRayTracingPipelineHelper::LateBindPipelineInfo() {
1851*b7893ccfSSadaf Ebrahimi     // By value or dynamically located items must be late bound
1852*b7893ccfSSadaf Ebrahimi     rp_ci_.layout = pipeline_layout_.handle();
1853*b7893ccfSSadaf Ebrahimi     rp_ci_.stageCount = shader_stages_.size();
1854*b7893ccfSSadaf Ebrahimi     rp_ci_.pStages = shader_stages_.data();
1855*b7893ccfSSadaf Ebrahimi }
1856*b7893ccfSSadaf Ebrahimi 
CreateNVRayTracingPipeline(bool implicit_destroy,bool do_late_bind)1857*b7893ccfSSadaf Ebrahimi VkResult CreateNVRayTracingPipelineHelper::CreateNVRayTracingPipeline(bool implicit_destroy, bool do_late_bind) {
1858*b7893ccfSSadaf Ebrahimi     VkResult err;
1859*b7893ccfSSadaf Ebrahimi     if (do_late_bind) {
1860*b7893ccfSSadaf Ebrahimi         LateBindPipelineInfo();
1861*b7893ccfSSadaf Ebrahimi     }
1862*b7893ccfSSadaf Ebrahimi     if (implicit_destroy && (pipeline_ != VK_NULL_HANDLE)) {
1863*b7893ccfSSadaf Ebrahimi         vkDestroyPipeline(layer_test_.device(), pipeline_, nullptr);
1864*b7893ccfSSadaf Ebrahimi         pipeline_ = VK_NULL_HANDLE;
1865*b7893ccfSSadaf Ebrahimi     }
1866*b7893ccfSSadaf Ebrahimi 
1867*b7893ccfSSadaf Ebrahimi     PFN_vkCreateRayTracingPipelinesNV vkCreateRayTracingPipelinesNV =
1868*b7893ccfSSadaf Ebrahimi         (PFN_vkCreateRayTracingPipelinesNV)vkGetInstanceProcAddr(layer_test_.instance(), "vkCreateRayTracingPipelinesNV");
1869*b7893ccfSSadaf Ebrahimi     err = vkCreateRayTracingPipelinesNV(layer_test_.device(), pipeline_cache_, 1, &rp_ci_, nullptr, &pipeline_);
1870*b7893ccfSSadaf Ebrahimi     return err;
1871*b7893ccfSSadaf Ebrahimi }
1872*b7893ccfSSadaf Ebrahimi 
1873*b7893ccfSSadaf Ebrahimi namespace chain_util {
Head() const1874*b7893ccfSSadaf Ebrahimi const void *ExtensionChain::Head() const { return head_; }
1875*b7893ccfSSadaf Ebrahimi }  // namespace chain_util
1876*b7893ccfSSadaf Ebrahimi 
~QueueFamilyObjs()1877*b7893ccfSSadaf Ebrahimi BarrierQueueFamilyTestHelper::QueueFamilyObjs::~QueueFamilyObjs() {
1878*b7893ccfSSadaf Ebrahimi     delete command_buffer2;
1879*b7893ccfSSadaf Ebrahimi     delete command_buffer;
1880*b7893ccfSSadaf Ebrahimi     delete command_pool;
1881*b7893ccfSSadaf Ebrahimi     delete queue;
1882*b7893ccfSSadaf Ebrahimi }
1883*b7893ccfSSadaf Ebrahimi 
Init(VkDeviceObj * device,uint32_t qf_index,VkQueue qf_queue,VkCommandPoolCreateFlags cp_flags)1884*b7893ccfSSadaf Ebrahimi void BarrierQueueFamilyTestHelper::QueueFamilyObjs::Init(VkDeviceObj *device, uint32_t qf_index, VkQueue qf_queue,
1885*b7893ccfSSadaf Ebrahimi                                                          VkCommandPoolCreateFlags cp_flags) {
1886*b7893ccfSSadaf Ebrahimi     index = qf_index;
1887*b7893ccfSSadaf Ebrahimi     queue = new VkQueueObj(qf_queue, qf_index);
1888*b7893ccfSSadaf Ebrahimi     command_pool = new VkCommandPoolObj(device, qf_index, cp_flags);
1889*b7893ccfSSadaf Ebrahimi     command_buffer = new VkCommandBufferObj(device, command_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, queue);
1890*b7893ccfSSadaf Ebrahimi     command_buffer2 = new VkCommandBufferObj(device, command_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, queue);
1891*b7893ccfSSadaf Ebrahimi };
1892*b7893ccfSSadaf Ebrahimi 
Context(VkLayerTest * test,const std::vector<uint32_t> & queue_family_indices)1893*b7893ccfSSadaf Ebrahimi BarrierQueueFamilyTestHelper::Context::Context(VkLayerTest *test, const std::vector<uint32_t> &queue_family_indices)
1894*b7893ccfSSadaf Ebrahimi     : layer_test(test) {
1895*b7893ccfSSadaf Ebrahimi     if (0 == queue_family_indices.size()) {
1896*b7893ccfSSadaf Ebrahimi         return;  // This is invalid
1897*b7893ccfSSadaf Ebrahimi     }
1898*b7893ccfSSadaf Ebrahimi     VkDeviceObj *device_obj = layer_test->DeviceObj();
1899*b7893ccfSSadaf Ebrahimi     queue_families.reserve(queue_family_indices.size());
1900*b7893ccfSSadaf Ebrahimi     default_index = queue_family_indices[0];
1901*b7893ccfSSadaf Ebrahimi     for (auto qfi : queue_family_indices) {
1902*b7893ccfSSadaf Ebrahimi         VkQueue queue = device_obj->queue_family_queues(qfi)[0]->handle();
1903*b7893ccfSSadaf Ebrahimi         queue_families.emplace(std::make_pair(qfi, QueueFamilyObjs()));
1904*b7893ccfSSadaf Ebrahimi         queue_families[qfi].Init(device_obj, qfi, queue, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
1905*b7893ccfSSadaf Ebrahimi     }
1906*b7893ccfSSadaf Ebrahimi     Reset();
1907*b7893ccfSSadaf Ebrahimi }
1908*b7893ccfSSadaf Ebrahimi 
Reset()1909*b7893ccfSSadaf Ebrahimi void BarrierQueueFamilyTestHelper::Context::Reset() {
1910*b7893ccfSSadaf Ebrahimi     layer_test->DeviceObj()->wait();
1911*b7893ccfSSadaf Ebrahimi     for (auto &qf : queue_families) {
1912*b7893ccfSSadaf Ebrahimi         vkResetCommandPool(layer_test->device(), qf.second.command_pool->handle(), 0);
1913*b7893ccfSSadaf Ebrahimi     }
1914*b7893ccfSSadaf Ebrahimi }
1915*b7893ccfSSadaf Ebrahimi 
BarrierQueueFamilyTestHelper(Context * context)1916*b7893ccfSSadaf Ebrahimi BarrierQueueFamilyTestHelper::BarrierQueueFamilyTestHelper(Context *context)
1917*b7893ccfSSadaf Ebrahimi     : context_(context), image_(context->layer_test->DeviceObj()) {}
1918*b7893ccfSSadaf Ebrahimi 
Init(std::vector<uint32_t> * families,bool image_memory,bool buffer_memory)1919*b7893ccfSSadaf Ebrahimi void BarrierQueueFamilyTestHelper::Init(std::vector<uint32_t> *families, bool image_memory, bool buffer_memory) {
1920*b7893ccfSSadaf Ebrahimi     VkDeviceObj *device_obj = context_->layer_test->DeviceObj();
1921*b7893ccfSSadaf Ebrahimi 
1922*b7893ccfSSadaf Ebrahimi     image_.Init(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0, families,
1923*b7893ccfSSadaf Ebrahimi                 image_memory);
1924*b7893ccfSSadaf Ebrahimi 
1925*b7893ccfSSadaf Ebrahimi     ASSERT_TRUE(image_.initialized());
1926*b7893ccfSSadaf Ebrahimi 
1927*b7893ccfSSadaf Ebrahimi     image_barrier_ = image_.image_memory_barrier(VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_TRANSFER_READ_BIT, image_.Layout(),
1928*b7893ccfSSadaf Ebrahimi                                                  image_.Layout(), image_.subresource_range(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1));
1929*b7893ccfSSadaf Ebrahimi 
1930*b7893ccfSSadaf Ebrahimi     VkMemoryPropertyFlags mem_prop = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
1931*b7893ccfSSadaf Ebrahimi     buffer_.init_as_src_and_dst(*device_obj, 256, mem_prop, families, buffer_memory);
1932*b7893ccfSSadaf Ebrahimi     ASSERT_TRUE(buffer_.initialized());
1933*b7893ccfSSadaf Ebrahimi     buffer_barrier_ = buffer_.buffer_memory_barrier(VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_TRANSFER_READ_BIT, 0, VK_WHOLE_SIZE);
1934*b7893ccfSSadaf Ebrahimi }
1935*b7893ccfSSadaf Ebrahimi 
GetQueueFamilyInfo(Context * context,uint32_t qfi)1936*b7893ccfSSadaf Ebrahimi BarrierQueueFamilyTestHelper::QueueFamilyObjs *BarrierQueueFamilyTestHelper::GetQueueFamilyInfo(Context *context, uint32_t qfi) {
1937*b7893ccfSSadaf Ebrahimi     QueueFamilyObjs *qf;
1938*b7893ccfSSadaf Ebrahimi 
1939*b7893ccfSSadaf Ebrahimi     auto qf_it = context->queue_families.find(qfi);
1940*b7893ccfSSadaf Ebrahimi     if (qf_it != context->queue_families.end()) {
1941*b7893ccfSSadaf Ebrahimi         qf = &(qf_it->second);
1942*b7893ccfSSadaf Ebrahimi     } else {
1943*b7893ccfSSadaf Ebrahimi         qf = &(context->queue_families[context->default_index]);
1944*b7893ccfSSadaf Ebrahimi     }
1945*b7893ccfSSadaf Ebrahimi     return qf;
1946*b7893ccfSSadaf Ebrahimi }
1947*b7893ccfSSadaf Ebrahimi 
operator ()(std::string img_err,std::string buf_err,uint32_t src,uint32_t dst,bool positive,uint32_t queue_family_index,Modifier mod)1948*b7893ccfSSadaf Ebrahimi void BarrierQueueFamilyTestHelper::operator()(std::string img_err, std::string buf_err, uint32_t src, uint32_t dst, bool positive,
1949*b7893ccfSSadaf Ebrahimi                                               uint32_t queue_family_index, Modifier mod) {
1950*b7893ccfSSadaf Ebrahimi     auto monitor = context_->layer_test->Monitor();
1951*b7893ccfSSadaf Ebrahimi     if (img_err.length()) monitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT, img_err);
1952*b7893ccfSSadaf Ebrahimi     if (buf_err.length()) monitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT, buf_err);
1953*b7893ccfSSadaf Ebrahimi 
1954*b7893ccfSSadaf Ebrahimi     image_barrier_.srcQueueFamilyIndex = src;
1955*b7893ccfSSadaf Ebrahimi     image_barrier_.dstQueueFamilyIndex = dst;
1956*b7893ccfSSadaf Ebrahimi     buffer_barrier_.srcQueueFamilyIndex = src;
1957*b7893ccfSSadaf Ebrahimi     buffer_barrier_.dstQueueFamilyIndex = dst;
1958*b7893ccfSSadaf Ebrahimi 
1959*b7893ccfSSadaf Ebrahimi     QueueFamilyObjs *qf = GetQueueFamilyInfo(context_, queue_family_index);
1960*b7893ccfSSadaf Ebrahimi 
1961*b7893ccfSSadaf Ebrahimi     VkCommandBufferObj *command_buffer = qf->command_buffer;
1962*b7893ccfSSadaf Ebrahimi     for (int cb_repeat = 0; cb_repeat < (mod == Modifier::DOUBLE_COMMAND_BUFFER ? 2 : 1); cb_repeat++) {
1963*b7893ccfSSadaf Ebrahimi         command_buffer->begin();
1964*b7893ccfSSadaf Ebrahimi         for (int repeat = 0; repeat < (mod == Modifier::DOUBLE_RECORD ? 2 : 1); repeat++) {
1965*b7893ccfSSadaf Ebrahimi             vkCmdPipelineBarrier(command_buffer->handle(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1966*b7893ccfSSadaf Ebrahimi                                  VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 1, &buffer_barrier_, 1, &image_barrier_);
1967*b7893ccfSSadaf Ebrahimi         }
1968*b7893ccfSSadaf Ebrahimi         command_buffer->end();
1969*b7893ccfSSadaf Ebrahimi         command_buffer = qf->command_buffer2;  // Second pass (if any) goes to the secondary command_buffer.
1970*b7893ccfSSadaf Ebrahimi     }
1971*b7893ccfSSadaf Ebrahimi 
1972*b7893ccfSSadaf Ebrahimi     if (queue_family_index != kInvalidQueueFamily) {
1973*b7893ccfSSadaf Ebrahimi         if (mod == Modifier::DOUBLE_COMMAND_BUFFER) {
1974*b7893ccfSSadaf Ebrahimi             // the Fence resolves to VK_NULL_HANLE... i.e. no fence
1975*b7893ccfSSadaf Ebrahimi             qf->queue->submit({{qf->command_buffer, qf->command_buffer2}}, vk_testing::Fence(), positive);
1976*b7893ccfSSadaf Ebrahimi         } else {
1977*b7893ccfSSadaf Ebrahimi             qf->command_buffer->QueueCommandBuffer(positive);  // Check for success on positive tests only
1978*b7893ccfSSadaf Ebrahimi         }
1979*b7893ccfSSadaf Ebrahimi     }
1980*b7893ccfSSadaf Ebrahimi 
1981*b7893ccfSSadaf Ebrahimi     if (positive) {
1982*b7893ccfSSadaf Ebrahimi         monitor->VerifyNotFound();
1983*b7893ccfSSadaf Ebrahimi     } else {
1984*b7893ccfSSadaf Ebrahimi         monitor->VerifyFound();
1985*b7893ccfSSadaf Ebrahimi     }
1986*b7893ccfSSadaf Ebrahimi     context_->Reset();
1987*b7893ccfSSadaf Ebrahimi };
1988*b7893ccfSSadaf Ebrahimi 
print_android(const char * c)1989*b7893ccfSSadaf Ebrahimi void print_android(const char *c) {
1990*b7893ccfSSadaf Ebrahimi #ifdef VK_USE_PLATFORM_ANDROID_KHR
1991*b7893ccfSSadaf Ebrahimi     __android_log_print(ANDROID_LOG_INFO, "VulkanLayerValidationTests", "%s", c);
1992*b7893ccfSSadaf Ebrahimi #endif  // VK_USE_PLATFORM_ANDROID_KHR
1993*b7893ccfSSadaf Ebrahimi }
1994*b7893ccfSSadaf Ebrahimi 
1995*b7893ccfSSadaf Ebrahimi #if defined(ANDROID) && defined(VALIDATION_APK)
1996*b7893ccfSSadaf Ebrahimi const char *appTag = "VulkanLayerValidationTests";
1997*b7893ccfSSadaf Ebrahimi static bool initialized = false;
1998*b7893ccfSSadaf Ebrahimi static bool active = false;
1999*b7893ccfSSadaf Ebrahimi 
2000*b7893ccfSSadaf Ebrahimi // Convert Intents to argv
2001*b7893ccfSSadaf Ebrahimi // Ported from Hologram sample, only difference is flexible key
get_args(android_app & app,const char * intent_extra_data_key)2002*b7893ccfSSadaf Ebrahimi std::vector<std::string> get_args(android_app &app, const char *intent_extra_data_key) {
2003*b7893ccfSSadaf Ebrahimi     std::vector<std::string> args;
2004*b7893ccfSSadaf Ebrahimi     JavaVM &vm = *app.activity->vm;
2005*b7893ccfSSadaf Ebrahimi     JNIEnv *p_env;
2006*b7893ccfSSadaf Ebrahimi     if (vm.AttachCurrentThread(&p_env, nullptr) != JNI_OK) return args;
2007*b7893ccfSSadaf Ebrahimi 
2008*b7893ccfSSadaf Ebrahimi     JNIEnv &env = *p_env;
2009*b7893ccfSSadaf Ebrahimi     jobject activity = app.activity->clazz;
2010*b7893ccfSSadaf Ebrahimi     jmethodID get_intent_method = env.GetMethodID(env.GetObjectClass(activity), "getIntent", "()Landroid/content/Intent;");
2011*b7893ccfSSadaf Ebrahimi     jobject intent = env.CallObjectMethod(activity, get_intent_method);
2012*b7893ccfSSadaf Ebrahimi     jmethodID get_string_extra_method =
2013*b7893ccfSSadaf Ebrahimi         env.GetMethodID(env.GetObjectClass(intent), "getStringExtra", "(Ljava/lang/String;)Ljava/lang/String;");
2014*b7893ccfSSadaf Ebrahimi     jvalue get_string_extra_args;
2015*b7893ccfSSadaf Ebrahimi     get_string_extra_args.l = env.NewStringUTF(intent_extra_data_key);
2016*b7893ccfSSadaf Ebrahimi     jstring extra_str = static_cast<jstring>(env.CallObjectMethodA(intent, get_string_extra_method, &get_string_extra_args));
2017*b7893ccfSSadaf Ebrahimi 
2018*b7893ccfSSadaf Ebrahimi     std::string args_str;
2019*b7893ccfSSadaf Ebrahimi     if (extra_str) {
2020*b7893ccfSSadaf Ebrahimi         const char *extra_utf = env.GetStringUTFChars(extra_str, nullptr);
2021*b7893ccfSSadaf Ebrahimi         args_str = extra_utf;
2022*b7893ccfSSadaf Ebrahimi         env.ReleaseStringUTFChars(extra_str, extra_utf);
2023*b7893ccfSSadaf Ebrahimi         env.DeleteLocalRef(extra_str);
2024*b7893ccfSSadaf Ebrahimi     }
2025*b7893ccfSSadaf Ebrahimi 
2026*b7893ccfSSadaf Ebrahimi     env.DeleteLocalRef(get_string_extra_args.l);
2027*b7893ccfSSadaf Ebrahimi     env.DeleteLocalRef(intent);
2028*b7893ccfSSadaf Ebrahimi     vm.DetachCurrentThread();
2029*b7893ccfSSadaf Ebrahimi 
2030*b7893ccfSSadaf Ebrahimi     // split args_str
2031*b7893ccfSSadaf Ebrahimi     std::stringstream ss(args_str);
2032*b7893ccfSSadaf Ebrahimi     std::string arg;
2033*b7893ccfSSadaf Ebrahimi     while (std::getline(ss, arg, ' ')) {
2034*b7893ccfSSadaf Ebrahimi         if (!arg.empty()) args.push_back(arg);
2035*b7893ccfSSadaf Ebrahimi     }
2036*b7893ccfSSadaf Ebrahimi 
2037*b7893ccfSSadaf Ebrahimi     return args;
2038*b7893ccfSSadaf Ebrahimi }
2039*b7893ccfSSadaf Ebrahimi 
addFullTestCommentIfPresent(const::testing::TestInfo & test_info,std::string & error_message)2040*b7893ccfSSadaf Ebrahimi void addFullTestCommentIfPresent(const ::testing::TestInfo &test_info, std::string &error_message) {
2041*b7893ccfSSadaf Ebrahimi     const char *const type_param = test_info.type_param();
2042*b7893ccfSSadaf Ebrahimi     const char *const value_param = test_info.value_param();
2043*b7893ccfSSadaf Ebrahimi 
2044*b7893ccfSSadaf Ebrahimi     if (type_param != NULL || value_param != NULL) {
2045*b7893ccfSSadaf Ebrahimi         error_message.append(", where ");
2046*b7893ccfSSadaf Ebrahimi         if (type_param != NULL) {
2047*b7893ccfSSadaf Ebrahimi             error_message.append("TypeParam = ").append(type_param);
2048*b7893ccfSSadaf Ebrahimi             if (value_param != NULL) error_message.append(" and ");
2049*b7893ccfSSadaf Ebrahimi         }
2050*b7893ccfSSadaf Ebrahimi         if (value_param != NULL) {
2051*b7893ccfSSadaf Ebrahimi             error_message.append("GetParam() = ").append(value_param);
2052*b7893ccfSSadaf Ebrahimi         }
2053*b7893ccfSSadaf Ebrahimi     }
2054*b7893ccfSSadaf Ebrahimi }
2055*b7893ccfSSadaf Ebrahimi 
2056*b7893ccfSSadaf Ebrahimi // Inspired by https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md
2057*b7893ccfSSadaf Ebrahimi class LogcatPrinter : public ::testing::EmptyTestEventListener {
2058*b7893ccfSSadaf Ebrahimi     // Called before a test starts.
OnTestStart(const::testing::TestInfo & test_info)2059*b7893ccfSSadaf Ebrahimi     virtual void OnTestStart(const ::testing::TestInfo &test_info) {
2060*b7893ccfSSadaf Ebrahimi         __android_log_print(ANDROID_LOG_INFO, appTag, "[ RUN      ] %s.%s", test_info.test_case_name(), test_info.name());
2061*b7893ccfSSadaf Ebrahimi     }
2062*b7893ccfSSadaf Ebrahimi 
2063*b7893ccfSSadaf Ebrahimi     // Called after a failed assertion or a SUCCEED() invocation.
OnTestPartResult(const::testing::TestPartResult & result)2064*b7893ccfSSadaf Ebrahimi     virtual void OnTestPartResult(const ::testing::TestPartResult &result) {
2065*b7893ccfSSadaf Ebrahimi         // If the test part succeeded, we don't need to do anything.
2066*b7893ccfSSadaf Ebrahimi         if (result.type() == ::testing::TestPartResult::kSuccess) return;
2067*b7893ccfSSadaf Ebrahimi 
2068*b7893ccfSSadaf Ebrahimi         __android_log_print(ANDROID_LOG_INFO, appTag, "%s in %s:%d %s", result.failed() ? "*** Failure" : "Success",
2069*b7893ccfSSadaf Ebrahimi                             result.file_name(), result.line_number(), result.summary());
2070*b7893ccfSSadaf Ebrahimi     }
2071*b7893ccfSSadaf Ebrahimi 
2072*b7893ccfSSadaf Ebrahimi     // Called after a test ends.
OnTestEnd(const::testing::TestInfo & info)2073*b7893ccfSSadaf Ebrahimi     virtual void OnTestEnd(const ::testing::TestInfo &info) {
2074*b7893ccfSSadaf Ebrahimi         std::string result;
2075*b7893ccfSSadaf Ebrahimi         if (info.result()->Passed()) {
2076*b7893ccfSSadaf Ebrahimi             result.append("[       OK ]");
2077*b7893ccfSSadaf Ebrahimi         } else {
2078*b7893ccfSSadaf Ebrahimi             result.append("[  FAILED  ]");
2079*b7893ccfSSadaf Ebrahimi         }
2080*b7893ccfSSadaf Ebrahimi         result.append(info.test_case_name()).append(".").append(info.name());
2081*b7893ccfSSadaf Ebrahimi         if (info.result()->Failed()) addFullTestCommentIfPresent(info, result);
2082*b7893ccfSSadaf Ebrahimi 
2083*b7893ccfSSadaf Ebrahimi         if (::testing::GTEST_FLAG(print_time)) {
2084*b7893ccfSSadaf Ebrahimi             std::ostringstream os;
2085*b7893ccfSSadaf Ebrahimi             os << info.result()->elapsed_time();
2086*b7893ccfSSadaf Ebrahimi             result.append(" (").append(os.str()).append(" ms)");
2087*b7893ccfSSadaf Ebrahimi         }
2088*b7893ccfSSadaf Ebrahimi 
2089*b7893ccfSSadaf Ebrahimi         __android_log_print(ANDROID_LOG_INFO, appTag, "%s", result.c_str());
2090*b7893ccfSSadaf Ebrahimi     };
2091*b7893ccfSSadaf Ebrahimi };
2092*b7893ccfSSadaf Ebrahimi 
processInput(struct android_app * app,AInputEvent * event)2093*b7893ccfSSadaf Ebrahimi static int32_t processInput(struct android_app *app, AInputEvent *event) { return 0; }
2094*b7893ccfSSadaf Ebrahimi 
processCommand(struct android_app * app,int32_t cmd)2095*b7893ccfSSadaf Ebrahimi static void processCommand(struct android_app *app, int32_t cmd) {
2096*b7893ccfSSadaf Ebrahimi     switch (cmd) {
2097*b7893ccfSSadaf Ebrahimi         case APP_CMD_INIT_WINDOW: {
2098*b7893ccfSSadaf Ebrahimi             if (app->window) {
2099*b7893ccfSSadaf Ebrahimi                 initialized = true;
2100*b7893ccfSSadaf Ebrahimi                 VkTestFramework::window = app->window;
2101*b7893ccfSSadaf Ebrahimi             }
2102*b7893ccfSSadaf Ebrahimi             break;
2103*b7893ccfSSadaf Ebrahimi         }
2104*b7893ccfSSadaf Ebrahimi         case APP_CMD_GAINED_FOCUS: {
2105*b7893ccfSSadaf Ebrahimi             active = true;
2106*b7893ccfSSadaf Ebrahimi             break;
2107*b7893ccfSSadaf Ebrahimi         }
2108*b7893ccfSSadaf Ebrahimi         case APP_CMD_LOST_FOCUS: {
2109*b7893ccfSSadaf Ebrahimi             active = false;
2110*b7893ccfSSadaf Ebrahimi             break;
2111*b7893ccfSSadaf Ebrahimi         }
2112*b7893ccfSSadaf Ebrahimi     }
2113*b7893ccfSSadaf Ebrahimi }
2114*b7893ccfSSadaf Ebrahimi 
android_main(struct android_app * app)2115*b7893ccfSSadaf Ebrahimi void android_main(struct android_app *app) {
2116*b7893ccfSSadaf Ebrahimi     int vulkanSupport = InitVulkan();
2117*b7893ccfSSadaf Ebrahimi     if (vulkanSupport == 0) {
2118*b7893ccfSSadaf Ebrahimi         __android_log_print(ANDROID_LOG_INFO, appTag, "==== FAILED ==== No Vulkan support found");
2119*b7893ccfSSadaf Ebrahimi         return;
2120*b7893ccfSSadaf Ebrahimi     }
2121*b7893ccfSSadaf Ebrahimi 
2122*b7893ccfSSadaf Ebrahimi     app->onAppCmd = processCommand;
2123*b7893ccfSSadaf Ebrahimi     app->onInputEvent = processInput;
2124*b7893ccfSSadaf Ebrahimi 
2125*b7893ccfSSadaf Ebrahimi     while (1) {
2126*b7893ccfSSadaf Ebrahimi         int events;
2127*b7893ccfSSadaf Ebrahimi         struct android_poll_source *source;
2128*b7893ccfSSadaf Ebrahimi         while (ALooper_pollAll(active ? 0 : -1, NULL, &events, (void **)&source) >= 0) {
2129*b7893ccfSSadaf Ebrahimi             if (source) {
2130*b7893ccfSSadaf Ebrahimi                 source->process(app, source);
2131*b7893ccfSSadaf Ebrahimi             }
2132*b7893ccfSSadaf Ebrahimi 
2133*b7893ccfSSadaf Ebrahimi             if (app->destroyRequested != 0) {
2134*b7893ccfSSadaf Ebrahimi                 VkTestFramework::Finish();
2135*b7893ccfSSadaf Ebrahimi                 return;
2136*b7893ccfSSadaf Ebrahimi             }
2137*b7893ccfSSadaf Ebrahimi         }
2138*b7893ccfSSadaf Ebrahimi 
2139*b7893ccfSSadaf Ebrahimi         if (initialized && active) {
2140*b7893ccfSSadaf Ebrahimi             // Use the following key to send arguments to gtest, i.e.
2141*b7893ccfSSadaf Ebrahimi             // --es args "--gtest_filter=-VkLayerTest.foo"
2142*b7893ccfSSadaf Ebrahimi             const char key[] = "args";
2143*b7893ccfSSadaf Ebrahimi             std::vector<std::string> args = get_args(*app, key);
2144*b7893ccfSSadaf Ebrahimi 
2145*b7893ccfSSadaf Ebrahimi             std::string filter = "";
2146*b7893ccfSSadaf Ebrahimi             if (args.size() > 0) {
2147*b7893ccfSSadaf Ebrahimi                 __android_log_print(ANDROID_LOG_INFO, appTag, "Intent args = %s", args[0].c_str());
2148*b7893ccfSSadaf Ebrahimi                 filter += args[0];
2149*b7893ccfSSadaf Ebrahimi             } else {
2150*b7893ccfSSadaf Ebrahimi                 __android_log_print(ANDROID_LOG_INFO, appTag, "No Intent args detected");
2151*b7893ccfSSadaf Ebrahimi             }
2152*b7893ccfSSadaf Ebrahimi 
2153*b7893ccfSSadaf Ebrahimi             int argc = 2;
2154*b7893ccfSSadaf Ebrahimi             char *argv[] = {(char *)"foo", (char *)filter.c_str()};
2155*b7893ccfSSadaf Ebrahimi             __android_log_print(ANDROID_LOG_DEBUG, appTag, "filter = %s", argv[1]);
2156*b7893ccfSSadaf Ebrahimi 
2157*b7893ccfSSadaf Ebrahimi             // Route output to files until we can override the gtest output
2158*b7893ccfSSadaf Ebrahimi             freopen("/sdcard/Android/data/com.example.VulkanLayerValidationTests/files/out.txt", "w", stdout);
2159*b7893ccfSSadaf Ebrahimi             freopen("/sdcard/Android/data/com.example.VulkanLayerValidationTests/files/err.txt", "w", stderr);
2160*b7893ccfSSadaf Ebrahimi 
2161*b7893ccfSSadaf Ebrahimi             ::testing::InitGoogleTest(&argc, argv);
2162*b7893ccfSSadaf Ebrahimi 
2163*b7893ccfSSadaf Ebrahimi             ::testing::TestEventListeners &listeners = ::testing::UnitTest::GetInstance()->listeners();
2164*b7893ccfSSadaf Ebrahimi             listeners.Append(new LogcatPrinter);
2165*b7893ccfSSadaf Ebrahimi 
2166*b7893ccfSSadaf Ebrahimi             VkTestFramework::InitArgs(&argc, argv);
2167*b7893ccfSSadaf Ebrahimi             ::testing::AddGlobalTestEnvironment(new TestEnvironment);
2168*b7893ccfSSadaf Ebrahimi 
2169*b7893ccfSSadaf Ebrahimi             int result = RUN_ALL_TESTS();
2170*b7893ccfSSadaf Ebrahimi 
2171*b7893ccfSSadaf Ebrahimi             if (result != 0) {
2172*b7893ccfSSadaf Ebrahimi                 __android_log_print(ANDROID_LOG_INFO, appTag, "==== Tests FAILED ====");
2173*b7893ccfSSadaf Ebrahimi             } else {
2174*b7893ccfSSadaf Ebrahimi                 __android_log_print(ANDROID_LOG_INFO, appTag, "==== Tests PASSED ====");
2175*b7893ccfSSadaf Ebrahimi             }
2176*b7893ccfSSadaf Ebrahimi 
2177*b7893ccfSSadaf Ebrahimi             VkTestFramework::Finish();
2178*b7893ccfSSadaf Ebrahimi 
2179*b7893ccfSSadaf Ebrahimi             fclose(stdout);
2180*b7893ccfSSadaf Ebrahimi             fclose(stderr);
2181*b7893ccfSSadaf Ebrahimi 
2182*b7893ccfSSadaf Ebrahimi             ANativeActivity_finish(app->activity);
2183*b7893ccfSSadaf Ebrahimi             return;
2184*b7893ccfSSadaf Ebrahimi         }
2185*b7893ccfSSadaf Ebrahimi     }
2186*b7893ccfSSadaf Ebrahimi }
2187*b7893ccfSSadaf Ebrahimi #endif
2188*b7893ccfSSadaf Ebrahimi 
2189*b7893ccfSSadaf Ebrahimi #if defined(_WIN32) && !defined(NDEBUG)
2190*b7893ccfSSadaf Ebrahimi #include <crtdbg.h>
2191*b7893ccfSSadaf Ebrahimi #endif
2192*b7893ccfSSadaf Ebrahimi 
main(int argc,char ** argv)2193*b7893ccfSSadaf Ebrahimi int main(int argc, char **argv) {
2194*b7893ccfSSadaf Ebrahimi     int result;
2195*b7893ccfSSadaf Ebrahimi 
2196*b7893ccfSSadaf Ebrahimi #ifdef ANDROID
2197*b7893ccfSSadaf Ebrahimi     int vulkanSupport = InitVulkan();
2198*b7893ccfSSadaf Ebrahimi     if (vulkanSupport == 0) return 1;
2199*b7893ccfSSadaf Ebrahimi #endif
2200*b7893ccfSSadaf Ebrahimi 
2201*b7893ccfSSadaf Ebrahimi #if defined(_WIN32) && !defined(NDEBUG)
2202*b7893ccfSSadaf Ebrahimi     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2203*b7893ccfSSadaf Ebrahimi     _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
2204*b7893ccfSSadaf Ebrahimi #endif
2205*b7893ccfSSadaf Ebrahimi 
2206*b7893ccfSSadaf Ebrahimi     ::testing::InitGoogleTest(&argc, argv);
2207*b7893ccfSSadaf Ebrahimi     VkTestFramework::InitArgs(&argc, argv);
2208*b7893ccfSSadaf Ebrahimi 
2209*b7893ccfSSadaf Ebrahimi     ::testing::AddGlobalTestEnvironment(new TestEnvironment);
2210*b7893ccfSSadaf Ebrahimi 
2211*b7893ccfSSadaf Ebrahimi     result = RUN_ALL_TESTS();
2212*b7893ccfSSadaf Ebrahimi 
2213*b7893ccfSSadaf Ebrahimi     VkTestFramework::Finish();
2214*b7893ccfSSadaf Ebrahimi     return result;
2215*b7893ccfSSadaf Ebrahimi }
2216