xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemUtils.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
6  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Protected Memory Utility methods
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktProtectedMemUtils.hpp"
26 #include "vktCustomInstancesDevices.hpp"
27 
28 #include "deString.h"
29 #include "deRandom.hpp"
30 
31 #include "vkDeviceUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkDebugReportUtil.hpp"
35 #include "vkApiVersion.hpp"
36 #include "vkObjUtil.hpp"
37 #include "vkSafetyCriticalUtil.hpp"
38 
39 #include "vkPlatform.hpp"
40 #include "vktProtectedMemContext.hpp"
41 #include "vkWsiUtil.hpp"
42 #include "vkObjUtil.hpp"
43 
44 namespace vkt
45 {
46 
47 using namespace vk;
48 
49 namespace ProtectedMem
50 {
51 
52 typedef std::vector<vk::VkExtensionProperties> Extensions;
53 
makeProtectedMemInstance(vkt::Context & context,const std::vector<std::string> & extraExtensions)54 CustomInstance makeProtectedMemInstance(vkt::Context &context, const std::vector<std::string> &extraExtensions)
55 {
56     const PlatformInterface &vkp = context.getPlatformInterface();
57     const Extensions supportedExtensions(vk::enumerateInstanceExtensionProperties(vkp, DE_NULL));
58     std::vector<std::string> requiredExtensions = extraExtensions;
59 
60     uint32_t apiVersion = context.getUsedApiVersion();
61     if (!isCoreInstanceExtension(apiVersion, "VK_KHR_get_physical_device_properties2"))
62         requiredExtensions.push_back("VK_KHR_get_physical_device_properties2");
63 
64     // extract extension names
65     std::vector<std::string> extensions;
66     for (const auto &e : supportedExtensions)
67         extensions.push_back(e.extensionName);
68 
69     for (const auto &extName : requiredExtensions)
70     {
71         if (!isInstanceExtensionSupported(apiVersion, extensions, extName))
72             TCU_THROW(NotSupportedError, (extName + " is not supported").c_str());
73     }
74 
75     return createCustomInstanceWithExtensions(context, requiredExtensions);
76 }
77 
checkProtectedQueueSupport(Context & context)78 void checkProtectedQueueSupport(Context &context)
79 {
80 #ifdef NOT_PROTECTED
81     return;
82 #endif
83 
84     const vk::InstanceInterface &vkd = context.getInstanceInterface();
85     vk::VkPhysicalDevice physDevice  = context.getPhysicalDevice();
86     std::vector<vk::VkQueueFamilyProperties> properties;
87     uint32_t numFamilies = 0;
88 
89     vkd.getPhysicalDeviceQueueFamilyProperties(physDevice, &numFamilies, DE_NULL);
90     DE_ASSERT(numFamilies > 0);
91     properties.resize(numFamilies);
92 
93     vkd.getPhysicalDeviceQueueFamilyProperties(physDevice, &numFamilies, properties.data());
94 
95     for (auto prop : properties)
96         if (prop.queueFlags & vk::VK_QUEUE_PROTECTED_BIT)
97             return;
98 
99     TCU_THROW(NotSupportedError, "No protected queue found.");
100 }
101 
chooseProtectedMemQueueFamilyIndex(const vk::InstanceDriver & vkd,vk::VkPhysicalDevice physicalDevice,vk::VkSurfaceKHR surface)102 uint32_t chooseProtectedMemQueueFamilyIndex(const vk::InstanceDriver &vkd, vk::VkPhysicalDevice physicalDevice,
103                                             vk::VkSurfaceKHR surface)
104 {
105     std::vector<vk::VkQueueFamilyProperties> properties;
106     uint32_t numFamilies = 0;
107 
108     vkd.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
109     DE_ASSERT(numFamilies > 0);
110     properties.resize(numFamilies);
111 
112     vkd.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, properties.data());
113 
114     // Get a universal protected queue family index
115     vk::VkQueueFlags requiredFlags = vk::VK_QUEUE_GRAPHICS_BIT | vk::VK_QUEUE_COMPUTE_BIT
116 #ifndef NOT_PROTECTED
117                                      | vk::VK_QUEUE_PROTECTED_BIT
118 #endif
119         ;
120     for (size_t idx = 0; idx < properties.size(); ++idx)
121     {
122         vk::VkQueueFlags flags = properties[idx].queueFlags;
123 
124         if (surface != DE_NULL &&
125             vk::wsi::getPhysicalDeviceSurfaceSupport(vkd, physicalDevice, (uint32_t)idx, surface) == VK_FALSE)
126             continue; // Skip the queue family index if it does not support the surface
127 
128         if ((flags & requiredFlags) == requiredFlags)
129             return (uint32_t)idx;
130     }
131 
132     TCU_THROW(NotSupportedError, "No matching universal protected queue found");
133 }
134 
makeProtectedMemDevice(const vk::PlatformInterface & vkp,vk::VkInstance instance,const vk::InstanceDriver & vkd,vk::VkPhysicalDevice physicalDevice,const uint32_t queueFamilyIndex,const uint32_t apiVersion,const std::vector<std::string> & extraExtensions,de::SharedPtr<vk::ResourceInterface> resourceInterface,const tcu::CommandLine & cmdLine)135 vk::Move<vk::VkDevice> makeProtectedMemDevice(const vk::PlatformInterface &vkp, vk::VkInstance instance,
136                                               const vk::InstanceDriver &vkd, vk::VkPhysicalDevice physicalDevice,
137                                               const uint32_t queueFamilyIndex, const uint32_t apiVersion,
138                                               const std::vector<std::string> &extraExtensions,
139 #ifdef CTS_USES_VULKANSC
140                                               de::SharedPtr<vk::ResourceInterface> resourceInterface,
141 #endif // CTS_USES_VULKANSC
142                                               const tcu::CommandLine &cmdLine)
143 {
144     const Extensions supportedExtensions(vk::enumerateDeviceExtensionProperties(vkd, physicalDevice, DE_NULL));
145     std::vector<std::string> requiredExtensions;
146     std::vector<std::string> extensions = extraExtensions;
147 
148     if (apiVersion < VK_API_VERSION_1_1)
149         TCU_THROW(NotSupportedError, "Vulkan 1.1 is not supported");
150 
151     bool useYCbCr = de::contains(extensions.begin(), extensions.end(), std::string("VK_KHR_sampler_ycbcr_conversion"));
152 #ifndef CTS_USES_VULKANSC
153     bool useProtectedAccess =
154         de::contains(extensions.begin(), extensions.end(), std::string("VK_EXT_pipeline_protected_access"));
155 #endif
156 
157     // Check if the physical device supports the protected memory extension name
158     for (uint32_t ndx = 0; ndx < extensions.size(); ++ndx)
159     {
160         bool notInCore = !isCoreDeviceExtension(apiVersion, extensions[ndx]);
161         if (notInCore && !isExtensionStructSupported(supportedExtensions.begin(), supportedExtensions.end(),
162                                                      RequiredExtension(extensions[ndx])))
163             TCU_THROW(NotSupportedError, (extensions[ndx] + " is not supported").c_str());
164 
165         if (notInCore)
166             requiredExtensions.push_back(extensions[ndx]);
167     }
168 
169     std::vector<const char *> enabledExts(requiredExtensions.size());
170     for (size_t idx = 0; idx < requiredExtensions.size(); ++idx)
171     {
172         enabledExts[idx] = requiredExtensions[idx].c_str();
173     }
174 
175 #ifndef CTS_USES_VULKANSC
176     vk::VkPhysicalDevicePipelineProtectedAccessFeaturesEXT protectedAccessFeature = {
177         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT, DE_NULL, VK_FALSE};
178 #endif
179 
180     vk::VkPhysicalDeviceSamplerYcbcrConversionFeatures ycbcrFeature = {
181         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES,
182 #ifndef CTS_USES_VULKANSC
183         &protectedAccessFeature,
184 #else
185         DE_NULL,
186 #endif
187         VK_FALSE};
188     // Check if the protected memory can be enabled on the physical device.
189     vk::VkPhysicalDeviceProtectedMemoryFeatures protectedFeature = {
190         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES, // sType
191         &ycbcrFeature,                                                   // pNext
192         VK_FALSE                                                         // protectedMemory
193     };
194     vk::VkPhysicalDeviceFeatures features;
195     deMemset(&features, 0, sizeof(vk::VkPhysicalDeviceFeatures));
196 
197     vk::VkPhysicalDeviceFeatures2 featuresExt = {vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, // sType
198                                                  &protectedFeature,                                // pNext
199                                                  features};
200 
201     vkd.getPhysicalDeviceFeatures2(physicalDevice, &featuresExt);
202 
203 #ifndef NOT_PROTECTED
204     if (protectedFeature.protectedMemory == VK_FALSE)
205         TCU_THROW(NotSupportedError, "Protected Memory feature not supported by the device");
206 #endif
207 
208     if (useYCbCr && !ycbcrFeature.samplerYcbcrConversion)
209         TCU_THROW(NotSupportedError, "VK_KHR_sampler_ycbcr_conversion is not supported");
210 
211 #ifndef CTS_USES_VULKANSC
212     if (useProtectedAccess && !protectedAccessFeature.pipelineProtectedAccess)
213         TCU_THROW(NotSupportedError, "VK_EXT_pipeline_protected_access is not supported");
214 #endif
215 
216     const float queuePriorities[]                  = {1.0f};
217     const vk::VkDeviceQueueCreateInfo queueInfos[] = {
218         {vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, DE_NULL,
219 #ifndef NOT_PROTECTED
220          (vk::VkDeviceQueueCreateFlags)vk::VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT,
221 #else
222          (vk::VkDeviceQueueCreateFlags)0u,
223 #endif
224          queueFamilyIndex, DE_LENGTH_OF_ARRAY(queuePriorities), queuePriorities}};
225 
226     void *pNext = &featuresExt;
227 #ifdef CTS_USES_VULKANSC
228     VkDeviceObjectReservationCreateInfo memReservationInfo =
229         cmdLine.isSubProcess() ? resourceInterface->getStatMax() : resetDeviceObjectReservationCreateInfo();
230     memReservationInfo.pNext = pNext;
231     pNext                    = &memReservationInfo;
232 
233     VkPhysicalDeviceVulkanSC10Features sc10Features = createDefaultSC10Features();
234     sc10Features.pNext                              = pNext;
235     pNext                                           = &sc10Features;
236 
237     VkPipelineCacheCreateInfo pcCI;
238     std::vector<VkPipelinePoolSize> poolSizes;
239     if (cmdLine.isSubProcess())
240     {
241         if (resourceInterface->getCacheDataSize() > 0)
242         {
243             pcCI = {
244                 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
245                 DE_NULL,                                      // const void* pNext;
246                 VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
247                     VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT, // VkPipelineCacheCreateFlags flags;
248                 resourceInterface->getCacheDataSize(),                    // uintptr_t initialDataSize;
249                 resourceInterface->getCacheData()                         // const void* pInitialData;
250             };
251             memReservationInfo.pipelineCacheCreateInfoCount = 1;
252             memReservationInfo.pPipelineCacheCreateInfos    = &pcCI;
253         }
254 
255         poolSizes = resourceInterface->getPipelinePoolSizes();
256         if (!poolSizes.empty())
257         {
258             memReservationInfo.pipelinePoolSizeCount = uint32_t(poolSizes.size());
259             memReservationInfo.pPipelinePoolSizes    = poolSizes.data();
260         }
261     }
262 #endif // CTS_USES_VULKANSC
263 
264     const vk::VkDeviceCreateInfo deviceParams = {
265         vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,               // sType
266         pNext,                                                  // pNext
267         (vk::VkDeviceCreateFlags)0,                             // flags
268         DE_LENGTH_OF_ARRAY(queueInfos),                         // queueCreateInfosCount
269         &queueInfos[0],                                         // pQueueCreateInfos
270         0u,                                                     // enabledLayerCount
271         DE_NULL,                                                // pEnabledLayerNames
272         (uint32_t)requiredExtensions.size(),                    // enabledExtensionCount
273         requiredExtensions.empty() ? DE_NULL : &enabledExts[0], // pEnabledExtensionNames
274         DE_NULL                                                 // pEnabledFeatures
275     };
276 
277     return createCustomDevice(cmdLine.isValidationEnabled(), vkp, instance, vkd, physicalDevice, &deviceParams,
278                               DE_NULL);
279 }
280 
getProtectedQueue(const vk::DeviceInterface & vk,vk::VkDevice device,const uint32_t queueFamilyIndex,const uint32_t queueIdx)281 vk::VkQueue getProtectedQueue(const vk::DeviceInterface &vk, vk::VkDevice device, const uint32_t queueFamilyIndex,
282                               const uint32_t queueIdx)
283 {
284     const vk::VkDeviceQueueInfo2 queueInfo = {
285         vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, // sType
286         DE_NULL,                                   // pNext
287         vk::VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT,  // flags
288         queueFamilyIndex,                          // queueFamilyIndex
289         queueIdx,                                  // queueIndex
290     };
291 
292     (void)queueInfo;
293     vk::VkQueue queue =
294 #ifndef NOT_PROTECTED
295         vk::getDeviceQueue2(vk, device, &queueInfo);
296 #else
297         vk::getDeviceQueue(vk, device, queueFamilyIndex, 0);
298 #endif
299 
300     if (queue == DE_NULL)
301         TCU_THROW(TestError, "Unable to get a protected queue");
302 
303     return queue;
304 }
305 
createImage2D(ProtectedContext & context,ProtectionMode protectionMode,const uint32_t queueFamilyIdx,uint32_t width,uint32_t height,vk::VkFormat format,vk::VkImageUsageFlags usageFlags)306 de::MovePtr<vk::ImageWithMemory> createImage2D(ProtectedContext &context, ProtectionMode protectionMode,
307                                                const uint32_t queueFamilyIdx, uint32_t width, uint32_t height,
308                                                vk::VkFormat format, vk::VkImageUsageFlags usageFlags)
309 {
310     const vk::DeviceInterface &vk = context.getDeviceInterface();
311     const vk::VkDevice &device    = context.getDevice();
312     vk::Allocator &allocator      = context.getDefaultAllocator();
313 
314 #ifndef NOT_PROTECTED
315     uint32_t flags =
316         (protectionMode == PROTECTION_ENABLED) ? vk::VK_IMAGE_CREATE_PROTECTED_BIT : (vk::VkImageCreateFlagBits)0u;
317 #else
318     DE_UNREF(protectionMode);
319     uint32_t flags               = 0u;
320 #endif
321 
322     const vk::VkImageCreateInfo params = {
323         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType            stype
324         DE_NULL,                                 // const void*                pNext
325         (vk::VkImageCreateFlags)flags,           // VkImageCreateFlags        flags
326         vk::VK_IMAGE_TYPE_2D,                    // VkImageType                imageType
327         format,                                  // VkFormat                    format
328         {width, height, 1},                      // VkExtent3D                extent
329         1u,                                      // uint32_t                    mipLevels
330         1u,                                      // uint32_t                    arrayLayers
331         vk::VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits    samples
332         vk::VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling            tiling
333         usageFlags,                              // VkImageUsageFlags        usage
334         vk::VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode            sharingMode
335         1u,                                      // uint32_t                    queueFamilyIndexCount
336         &queueFamilyIdx,                         // const uint32_t*            pQueueFamilyIndices
337         vk::VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout            initialLayout
338     };
339 
340 #ifndef NOT_PROTECTED
341     vk::MemoryRequirement memReq =
342         (protectionMode == PROTECTION_ENABLED) ? vk::MemoryRequirement::Protected : vk::MemoryRequirement::Any;
343 #else
344     vk::MemoryRequirement memReq = vk::MemoryRequirement::Any;
345 #endif
346 
347     return de::MovePtr<vk::ImageWithMemory>(new vk::ImageWithMemory(vk, device, allocator, params, memReq));
348 }
349 
makeBuffer(ProtectedContext & context,ProtectionMode protectionMode,const uint32_t queueFamilyIdx,uint32_t size,vk::VkBufferUsageFlags usageFlags,vk::MemoryRequirement memReq)350 de::MovePtr<vk::BufferWithMemory> makeBuffer(ProtectedContext &context, ProtectionMode protectionMode,
351                                              const uint32_t queueFamilyIdx, uint32_t size,
352                                              vk::VkBufferUsageFlags usageFlags, vk::MemoryRequirement memReq)
353 {
354     const vk::DeviceInterface &vk = context.getDeviceInterface();
355     const vk::VkDevice &device    = context.getDevice();
356     vk::Allocator &allocator      = context.getDefaultAllocator();
357 
358 #ifndef NOT_PROTECTED
359     uint32_t flags =
360         (protectionMode == PROTECTION_ENABLED) ? vk::VK_BUFFER_CREATE_PROTECTED_BIT : (vk::VkBufferCreateFlagBits)0u;
361     vk::MemoryRequirement requirement = memReq;
362 #else
363     DE_UNREF(protectionMode);
364     uint32_t flags                    = 0u;
365     vk::MemoryRequirement requirement = memReq & (vk::MemoryRequirement::HostVisible | vk::MemoryRequirement::Coherent |
366                                                   vk::MemoryRequirement::LazilyAllocated);
367 #endif
368 
369     const vk::VkBufferCreateInfo params = {
370         vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
371         DE_NULL,                                  // pNext
372         (vk::VkBufferCreateFlags)flags,           // flags
373         (vk::VkDeviceSize)size,                   // size
374         usageFlags,                               // usage
375         vk::VK_SHARING_MODE_EXCLUSIVE,            // sharingMode
376         1u,                                       // queueFamilyCount
377         &queueFamilyIdx,                          // pQueueFamilyIndices
378     };
379 
380     return de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(vk, device, allocator, params, requirement));
381 }
382 
createImageView(ProtectedContext & context,vk::VkImage image,vk::VkFormat format)383 vk::Move<vk::VkImageView> createImageView(ProtectedContext &context, vk::VkImage image, vk::VkFormat format)
384 {
385     const vk::VkImageViewCreateInfo params = {
386         vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,    // sType
387         DE_NULL,                                         // pNext
388         0u,                                              // flags
389         image,                                           // image
390         vk::VK_IMAGE_VIEW_TYPE_2D,                       // viewType
391         format,                                          // format
392         vk::makeComponentMappingRGBA(),                  // components
393         {vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}, // subresourceRange
394     };
395 
396     return vk::createImageView(context.getDeviceInterface(), context.getDevice(), &params);
397 }
398 
createRenderPass(ProtectedContext & context,vk::VkFormat format)399 vk::Move<vk::VkRenderPass> createRenderPass(ProtectedContext &context, vk::VkFormat format)
400 {
401     const vk::VkDevice vkDevice   = context.getDevice();
402     const vk::DeviceInterface &vk = context.getDeviceInterface();
403 
404     return vk::makeRenderPass(vk, vkDevice, format);
405 }
406 
createFramebuffer(ProtectedContext & context,uint32_t width,uint32_t height,vk::VkRenderPass renderPass,vk::VkImageView colorImageView)407 vk::Move<vk::VkFramebuffer> createFramebuffer(ProtectedContext &context, uint32_t width, uint32_t height,
408                                               vk::VkRenderPass renderPass, vk::VkImageView colorImageView)
409 {
410     const vk::VkDevice vkDevice   = context.getDevice();
411     const vk::DeviceInterface &vk = context.getDeviceInterface();
412 
413     const vk::VkFramebufferCreateInfo framebufferParams = {
414         vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
415         DE_NULL,                                       // const void* pNext;
416         0u,                                            // VkFramebufferCreateFlags flags;
417         renderPass,                                    // VkRenderPass renderPass;
418         1u,                                            // uint32_t attachmentCount;
419         &colorImageView,                               // const VkImageView* pAttachments;
420         width,                                         // uint32_t width;
421         height,                                        // uint32_t height;
422         1u                                             // uint32_t layers;
423     };
424 
425     return vk::createFramebuffer(vk, vkDevice, &framebufferParams);
426 }
427 
createPipelineLayout(ProtectedContext & context,uint32_t layoutCount,vk::VkDescriptorSetLayout * setLayouts)428 vk::Move<vk::VkPipelineLayout> createPipelineLayout(ProtectedContext &context, uint32_t layoutCount,
429                                                     vk::VkDescriptorSetLayout *setLayouts)
430 {
431     const vk::VkPipelineLayoutCreateInfo params = {
432         vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
433         DE_NULL,                                           // pNext
434         0u,                                                // flags
435         layoutCount,                                       // setLayoutCount
436         setLayouts,                                        // pSetLayouts
437         0u,                                                // pushConstantRangeCount
438         DE_NULL,                                           // pPushContantRanges
439     };
440 
441     return vk::createPipelineLayout(context.getDeviceInterface(), context.getDevice(), &params);
442 }
443 
beginSecondaryCommandBuffer(const vk::DeviceInterface & vk,const vk::VkCommandBuffer secondaryCmdBuffer,const vk::VkCommandBufferInheritanceInfo bufferInheritanceInfo)444 void beginSecondaryCommandBuffer(const vk::DeviceInterface &vk, const vk::VkCommandBuffer secondaryCmdBuffer,
445                                  const vk::VkCommandBufferInheritanceInfo bufferInheritanceInfo)
446 {
447     const vk::VkCommandBufferUsageFlags flags =
448         bufferInheritanceInfo.renderPass != DE_NULL ?
449             (vk::VkCommandBufferUsageFlags)vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT :
450             (vk::VkCommandBufferUsageFlags)0u;
451     const vk::VkCommandBufferBeginInfo beginInfo = {
452         vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
453         DE_NULL,                                         // pNext
454         flags,                                           // flags
455         &bufferInheritanceInfo,                          // pInheritanceInfo
456     };
457     VK_CHECK(vk.beginCommandBuffer(secondaryCmdBuffer, &beginInfo));
458 }
459 
queueSubmit(ProtectedContext & context,ProtectionMode protectionMode,vk::VkQueue queue,vk::VkCommandBuffer cmdBuffer,vk::VkFence fence,uint64_t timeout)460 vk::VkResult queueSubmit(ProtectedContext &context, ProtectionMode protectionMode, vk::VkQueue queue,
461                          vk::VkCommandBuffer cmdBuffer, vk::VkFence fence, uint64_t timeout)
462 {
463     const vk::DeviceInterface &vk = context.getDeviceInterface();
464     const vk::VkDevice &device    = context.getDevice();
465 
466     // Basic submit info
467     vk::VkSubmitInfo submitInfo = {
468         vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,         // sType
469         DE_NULL,                                   // pNext
470         0u,                                        // waitSemaphoreCount
471         DE_NULL,                                   // pWaitSempahores
472         (const vk::VkPipelineStageFlags *)DE_NULL, // stageFlags
473         1u,                                        // commandBufferCount
474         &cmdBuffer,                                // pCommandBuffers
475         0u,                                        // signalSemaphoreCount
476         DE_NULL,                                   // pSignalSemaphores
477     };
478 
479 #ifndef NOT_PROTECTED
480     // Protected extension submit info
481     const vk::VkProtectedSubmitInfo protectedInfo = {
482         vk::VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO, // sType
483         DE_NULL,                                     // pNext
484         VK_TRUE,                                     // protectedSubmit
485     };
486     if (protectionMode == PROTECTION_ENABLED)
487     {
488         submitInfo.pNext = &protectedInfo;
489     }
490 #else
491     DE_UNREF(protectionMode);
492 #endif
493 
494     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence));
495     return vk.waitForFences(device, 1u, &fence, true, timeout);
496 }
497 
makeSampler(const vk::DeviceInterface & vk,const vk::VkDevice & device)498 vk::Move<vk::VkSampler> makeSampler(const vk::DeviceInterface &vk, const vk::VkDevice &device)
499 {
500     const vk::VkSamplerCreateInfo createInfo = {vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
501                                                 DE_NULL,
502                                                 0u,
503 
504                                                 vk::VK_FILTER_NEAREST,
505                                                 vk::VK_FILTER_NEAREST,
506 
507                                                 vk::VK_SAMPLER_MIPMAP_MODE_LINEAR,
508                                                 vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
509                                                 vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
510                                                 vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
511                                                 0.0f,
512                                                 VK_FALSE,
513                                                 1.0f,
514                                                 VK_FALSE,
515                                                 vk::VK_COMPARE_OP_ALWAYS,
516                                                 0.0f,
517                                                 0.0f,
518                                                 vk::VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
519                                                 VK_FALSE};
520 
521     return vk::createSampler(vk, device, &createInfo);
522 }
523 
makeCommandPool(const vk::DeviceInterface & vk,const vk::VkDevice & device,ProtectionMode protectionMode,const uint32_t queueFamilyIdx)524 vk::Move<vk::VkCommandPool> makeCommandPool(const vk::DeviceInterface &vk, const vk::VkDevice &device,
525                                             ProtectionMode protectionMode, const uint32_t queueFamilyIdx)
526 {
527     const uint32_t poolFlags = vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT
528 #ifndef NOT_PROTECTED
529                                |
530                                ((protectionMode == PROTECTION_ENABLED) ? vk::VK_COMMAND_POOL_CREATE_PROTECTED_BIT : 0x0)
531 #endif
532         ;
533 #ifdef NOT_PROTECTED
534     DE_UNREF(protectionMode);
535 #endif
536 
537     return vk::createCommandPool(vk, device, poolFlags, queueFamilyIdx);
538 }
539 
makeGraphicsPipeline(const vk::DeviceInterface & vk,const vk::VkDevice device,const vk::VkPipelineLayout pipelineLayout,const vk::VkRenderPass renderPass,const vk::VkShaderModule vertexShaderModule,const vk::VkShaderModule fragmentShaderModule,const VertexBindings & vertexBindings,const VertexAttribs & vertexAttribs,const tcu::UVec2 & renderSize,const vk::VkPrimitiveTopology topology,const vk::VkPipelineCreateFlags flags)540 vk::Move<vk::VkPipeline> makeGraphicsPipeline(const vk::DeviceInterface &vk, const vk::VkDevice device,
541                                               const vk::VkPipelineLayout pipelineLayout,
542                                               const vk::VkRenderPass renderPass,
543                                               const vk::VkShaderModule vertexShaderModule,
544                                               const vk::VkShaderModule fragmentShaderModule,
545                                               const VertexBindings &vertexBindings, const VertexAttribs &vertexAttribs,
546                                               const tcu::UVec2 &renderSize, const vk::VkPrimitiveTopology topology,
547                                               const vk::VkPipelineCreateFlags flags)
548 {
549     const std::vector<VkViewport> viewports(1, makeViewport(renderSize));
550     const std::vector<VkRect2D> scissors(1, makeRect2D(renderSize));
551 
552     const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
553         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType                             sType;
554         DE_NULL,                                                   // const void*                                 pNext;
555         (VkPipelineVertexInputStateCreateFlags)0,                  // VkPipelineVertexInputStateCreateFlags       flags;
556         (uint32_t)vertexBindings.size(), // uint32_t                                    vertexBindingDescriptionCount;
557         vertexBindings.data(),           // const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
558         (uint32_t)vertexAttribs.size(),  // uint32_t                                    vertexAttributeDescriptionCount;
559         vertexAttribs.data()             // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
560     };
561 
562     return vk::makeGraphicsPipeline(
563         vk,                          // const DeviceInterface&                        vk
564         device,                      // const VkDevice                                device
565         pipelineLayout,              // const VkPipelineLayout                        pipelineLayout
566         vertexShaderModule,          // const VkShaderModule                          vertexShaderModule
567         DE_NULL,                     // const VkShaderModule                          tessellationControlModule
568         DE_NULL,                     // const VkShaderModule                          tessellationEvalModule
569         DE_NULL,                     // const VkShaderModule                          geometryShaderModule
570         fragmentShaderModule,        // const VkShaderModule                          fragmentShaderModule
571         renderPass,                  // const VkRenderPass                            renderPass
572         viewports,                   // const std::vector<VkViewport>&                viewports
573         scissors,                    // const std::vector<VkRect2D>&                  scissors
574         topology,                    // const VkPrimitiveTopology                     topology
575         0u,                          // const uint32_t                                subpass
576         0u,                          // const uint32_t                                patchControlPoints
577         &vertexInputStateCreateInfo, // const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
578         DE_NULL,                     // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
579         DE_NULL,                     // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
580         DE_NULL,                     // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
581         DE_NULL,                     // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo
582         DE_NULL,                     // const VkPipelineDynamicStateCreateInfo* dynamicStateCreateInfo
583         DE_NULL,                     // const void* pNext
584         flags);
585 }
586 
getCmdBufferTypeStr(const CmdBufferType cmdBufferType)587 const char *getCmdBufferTypeStr(const CmdBufferType cmdBufferType)
588 {
589     switch (cmdBufferType)
590     {
591     case CMD_BUFFER_PRIMARY:
592         return "primary";
593     case CMD_BUFFER_SECONDARY:
594         return "secondary";
595 
596     default:
597         DE_FATAL("Invalid command buffer type");
598         return "";
599     }
600 }
601 
clearImage(ProtectedContext & ctx,vk::VkImage image)602 void clearImage(ProtectedContext &ctx, vk::VkImage image)
603 {
604     const vk::DeviceInterface &vk   = ctx.getDeviceInterface();
605     const vk::VkDevice device       = ctx.getDevice();
606     const vk::VkQueue queue         = ctx.getQueue();
607     const uint32_t queueFamilyIndex = ctx.getQueueFamilyIndex();
608 
609     vk::Unique<vk::VkCommandPool> cmdPool(makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
610     vk::Unique<vk::VkCommandBuffer> cmdBuffer(
611         vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
612 
613     const vk::VkClearColorValue clearColor = {{0.0f, 0.0f, 0.0f, 0.0f}};
614 
615     const vk::VkImageSubresourceRange subresourceRange = {
616         vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags    aspectMask
617         0u,                            // uint32_t                baseMipLevel
618         1u,                            // uint32_t                levelCount
619         0u,                            // uint32_t                baseArrayLayer
620         1u,                            // uint32_t                layerCount
621     };
622 
623     const vk::VkImageMemoryBarrier preImageBarrier = {
624         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
625         DE_NULL,                                    // const void* pNext;
626         0u,                                         // VkAccessFlags srcAccessMask;
627         vk::VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
628         vk::VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout oldLayout;
629         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout newLayout;
630         queueFamilyIndex,                           // uint32_t srcQueueFamilyIndex;
631         queueFamilyIndex,                           // uint32_t dstQueueFamilyIndex;
632         image,                                      // VkImage image;
633         subresourceRange                            // VkImageSubresourceRange subresourceRange;
634     };
635 
636     const vk::VkImageMemoryBarrier postImageBarrier = {
637         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
638         DE_NULL,                                    // const void* pNext;
639         vk::VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags srcAccessMask;
640         vk::VK_ACCESS_SHADER_WRITE_BIT,             // VkAccessFlags dstAccessMask;
641         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout oldLayout;
642         vk::VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout newLayout;
643         queueFamilyIndex,                           // uint32_t srcQueueFamilyIndex;
644         queueFamilyIndex,                           // uint32_t dstQueueFamilyIndex;
645         image,                                      // VkImage image;
646         subresourceRange                            // VkImageSubresourceRange subresourceRange;
647     };
648 
649     beginCommandBuffer(vk, *cmdBuffer);
650     vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
651                           (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier *)DE_NULL, 0,
652                           (const vk::VkBufferMemoryBarrier *)DE_NULL, 1, &preImageBarrier);
653     vk.cmdClearColorImage(*cmdBuffer, image, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1,
654                           &subresourceRange);
655     vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
656                           (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier *)DE_NULL, 0,
657                           (const vk::VkBufferMemoryBarrier *)DE_NULL, 1, &postImageBarrier);
658     endCommandBuffer(vk, *cmdBuffer);
659 
660     {
661         const vk::Unique<vk::VkFence> fence(createFence(vk, device));
662         VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
663     }
664 }
665 
uploadImage(ProtectedContext & ctx,vk::VkImage image,const tcu::Texture2D & texture2D)666 void uploadImage(ProtectedContext &ctx, vk::VkImage image, const tcu::Texture2D &texture2D)
667 {
668     const vk::DeviceInterface &vk   = ctx.getDeviceInterface();
669     const vk::VkDevice device       = ctx.getDevice();
670     const vk::VkQueue queue         = ctx.getQueue();
671     const uint32_t queueFamilyIndex = ctx.getQueueFamilyIndex();
672 
673     vk::Unique<vk::VkCommandPool> cmdPool(makeCommandPool(vk, device, PROTECTION_DISABLED, queueFamilyIndex));
674     vk::Unique<vk::VkCommandBuffer> cmdBuffer(
675         vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
676 
677     const uint32_t width             = (uint32_t)texture2D.getWidth();
678     const uint32_t height            = (uint32_t)texture2D.getHeight();
679     const uint32_t stagingBufferSize = width * height * tcu::getPixelSize(texture2D.getFormat());
680 
681     de::UniquePtr<vk::BufferWithMemory> stagingBuffer(
682         makeBuffer(ctx, PROTECTION_DISABLED, queueFamilyIndex, stagingBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
683                    vk::MemoryRequirement::HostVisible));
684 
685     {
686         const tcu::ConstPixelBufferAccess &access = texture2D.getLevel(0);
687         const tcu::PixelBufferAccess destAccess(access.getFormat(), access.getSize(),
688                                                 stagingBuffer->getAllocation().getHostPtr());
689 
690         tcu::copy(destAccess, access);
691 
692         flushAlloc(vk, device, stagingBuffer->getAllocation());
693     }
694 
695     const vk::VkImageSubresourceRange subresourceRange = {
696         vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags    aspectMask
697         0u,                            // uint32_t                baseMipLevel
698         1u,                            // uint32_t                levelCount
699         0u,                            // uint32_t                baseArrayLayer
700         1u,                            // uint32_t                layerCount
701     };
702 
703     const vk::VkImageMemoryBarrier preCopyBarrier = {
704         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
705         DE_NULL,                                    // const void* pNext;
706         0u,                                         // VkAccessFlags srcAccessMask;
707         vk::VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
708         vk::VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout oldLayout;
709         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout newLayout;
710         queueFamilyIndex,                           // uint32_t srcQueueFamilyIndex;
711         queueFamilyIndex,                           // uint32_t dstQueueFamilyIndex;
712         image,                                      // VkImage image;
713         subresourceRange                            // VkImageSubresourceRange subresourceRange;
714     };
715 
716     const vk::VkImageMemoryBarrier postCopyBarrier = {
717         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
718         DE_NULL,                                    // const void* pNext;
719         vk::VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags srcAccessMask;
720         vk::VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
721         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout oldLayout;
722         vk::VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout newLayout;
723         queueFamilyIndex,                           // uint32_t srcQueueFamilyIndex;
724         queueFamilyIndex,                           // uint32_t dstQueueFamilyIndex;
725         image,                                      // VkImage image;
726         subresourceRange                            // VkImageSubresourceRange subresourceRange;
727     };
728 
729     const vk::VkImageSubresourceLayers subresourceLayers = {
730         vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
731         0u,                            // uint32_t mipLevel;
732         0u,                            // uint32_t baseArrayLayer;
733         1u                             // uint32_t layerCount;
734     };
735 
736     const vk::VkBufferImageCopy copyRegion = {
737         0u,                 // VkDeviceSize bufferOffset;
738         width,              // uint32_t bufferRowLength;
739         height,             // uint32_t bufferImageHeight;
740         subresourceLayers,  // VkImageSubresourceLayers imageSubresource;
741         {0u, 0u, 0u},       // VkOffset3D imageOffset;
742         {width, height, 1u} // VkExtent3D imageExtent;
743     };
744 
745     beginCommandBuffer(vk, *cmdBuffer);
746     vk.cmdPipelineBarrier(*cmdBuffer, (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_HOST_BIT,
747                           (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u,
748                           (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
749                           &preCopyBarrier);
750     vk.cmdCopyBufferToImage(*cmdBuffer, **stagingBuffer, image, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u,
751                             &copyRegion);
752     vk.cmdPipelineBarrier(*cmdBuffer, (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
753                           (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u,
754                           (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
755                           &postCopyBarrier);
756     endCommandBuffer(vk, *cmdBuffer);
757 
758     {
759         const vk::Unique<vk::VkFence> fence(createFence(vk, device));
760         VK_CHECK(queueSubmit(ctx, PROTECTION_DISABLED, queue, *cmdBuffer, *fence, ~0ull));
761     }
762 }
763 
copyToProtectedImage(ProtectedContext & ctx,vk::VkImage srcImage,vk::VkImage dstImage,vk::VkImageLayout dstImageLayout,uint32_t width,uint32_t height,ProtectionMode protectionMode)764 void copyToProtectedImage(ProtectedContext &ctx, vk::VkImage srcImage, vk::VkImage dstImage,
765                           vk::VkImageLayout dstImageLayout, uint32_t width, uint32_t height,
766                           ProtectionMode protectionMode)
767 {
768     const vk::DeviceInterface &vk   = ctx.getDeviceInterface();
769     const vk::VkDevice device       = ctx.getDevice();
770     const vk::VkQueue queue         = ctx.getQueue();
771     const uint32_t queueFamilyIndex = ctx.getQueueFamilyIndex();
772 
773     vk::Unique<vk::VkCommandPool> cmdPool(makeCommandPool(vk, device, protectionMode, queueFamilyIndex));
774     vk::Unique<vk::VkCommandBuffer> cmdBuffer(
775         vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
776 
777     const vk::VkImageSubresourceRange subresourceRange = {
778         vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags    aspectMask
779         0u,                            // uint32_t                baseMipLevel
780         1u,                            // uint32_t                levelCount
781         0u,                            // uint32_t                baseArrayLayer
782         1u,                            // uint32_t                layerCount
783     };
784 
785     const vk::VkImageMemoryBarrier preImageBarriers[] = {
786         // source image
787         {
788             vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
789             DE_NULL,                                    // const void* pNext;
790             vk::VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags srcAccessMask;
791             vk::VK_ACCESS_TRANSFER_READ_BIT,            // VkAccessFlags dstAccessMask;
792             vk::VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout oldLayout;
793             vk::VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout newLayout;
794             queueFamilyIndex,                           // uint32_t srcQueueFamilyIndex;
795             queueFamilyIndex,                           // uint32_t dstQueueFamilyIndex;
796             srcImage,                                   // VkImage image;
797             subresourceRange                            // VkImageSubresourceRange subresourceRange;
798         },
799         // destination image
800         {
801             vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
802             DE_NULL,                                    // const void* pNext;
803             0,                                          // VkAccessFlags srcAccessMask;
804             vk::VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
805             vk::VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout oldLayout;
806             vk::VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout newLayout;
807             queueFamilyIndex,                           // uint32_t srcQueueFamilyIndex;
808             queueFamilyIndex,                           // uint32_t dstQueueFamilyIndex;
809             dstImage,                                   // VkImage image;
810             subresourceRange                            // VkImageSubresourceRange subresourceRange;
811         }};
812 
813     const vk::VkImageMemoryBarrier postImgBarrier = {
814         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
815         DE_NULL,                                    // const void* pNext;
816         vk::VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags srcAccessMask;
817         vk::VK_ACCESS_SHADER_READ_BIT,              // VkAccessFlags dstAccessMask;
818         vk::VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout oldLayout;
819         dstImageLayout,                             // VkImageLayout newLayout;
820         queueFamilyIndex,                           // uint32_t srcQueueFamilyIndex;
821         queueFamilyIndex,                           // uint32_t dstQueueFamilyIndex;
822         dstImage,                                   // VkImage image;
823         subresourceRange                            // VkImageSubresourceRange subresourceRange;
824     };
825 
826     const vk::VkImageSubresourceLayers subresourceLayers = {
827         vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
828         0u,                            // uint32_t mipLevel;
829         0u,                            // uint32_t baseArrayLayer;
830         1u                             // uint32_t layerCount;
831     };
832 
833     const vk::VkImageCopy copyImageRegion = {
834         subresourceLayers,   // VkImageSubresourceCopy srcSubresource;
835         {0, 0, 0},           // VkOffset3D srcOffset;
836         subresourceLayers,   // VkImageSubresourceCopy destSubresource;
837         {0, 0, 0},           // VkOffset3D destOffset;
838         {width, height, 1u}, // VkExtent3D extent;
839     };
840 
841     beginCommandBuffer(vk, *cmdBuffer);
842     vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
843                           (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier *)DE_NULL, 0,
844                           (const vk::VkBufferMemoryBarrier *)DE_NULL, DE_LENGTH_OF_ARRAY(preImageBarriers),
845                           preImageBarriers);
846     vk.cmdCopyImage(*cmdBuffer, srcImage, vk::VK_IMAGE_LAYOUT_GENERAL, dstImage, vk::VK_IMAGE_LAYOUT_GENERAL, 1u,
847                     &copyImageRegion);
848     vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
849                           (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier *)DE_NULL, 0,
850                           (const vk::VkBufferMemoryBarrier *)DE_NULL, 1, &postImgBarrier);
851     endCommandBuffer(vk, *cmdBuffer);
852 
853     {
854         const vk::Unique<vk::VkFence> fence(createFence(vk, device));
855         VK_CHECK(queueSubmit(ctx, protectionMode, queue, *cmdBuffer, *fence, ~0ull));
856     }
857 }
858 
fillWithRandomColorTiles(const tcu::PixelBufferAccess & dst,const tcu::Vec4 & minVal,const tcu::Vec4 & maxVal,uint32_t seed)859 void fillWithRandomColorTiles(const tcu::PixelBufferAccess &dst, const tcu::Vec4 &minVal, const tcu::Vec4 &maxVal,
860                               uint32_t seed)
861 {
862     const int numCols = dst.getWidth() >= 7 ? 7 : dst.getWidth();
863     const int numRows = dst.getHeight() >= 5 ? 5 : dst.getHeight();
864     de::Random rnd(seed);
865 
866     for (int slice = 0; slice < dst.getDepth(); slice++)
867         for (int row = 0; row < numRows; row++)
868             for (int col = 0; col < numCols; col++)
869             {
870                 const int yBegin = (row + 0) * dst.getHeight() / numRows;
871                 const int yEnd   = (row + 1) * dst.getHeight() / numRows;
872                 const int xBegin = (col + 0) * dst.getWidth() / numCols;
873                 const int xEnd   = (col + 1) * dst.getWidth() / numCols;
874                 tcu::Vec4 color;
875                 for (int i = 0; i < 4; i++)
876                     color[i] = rnd.getFloat(minVal[i], maxVal[i]);
877                 tcu::clear(tcu::getSubregion(dst, xBegin, yBegin, slice, xEnd - xBegin, yEnd - yBegin, 1), color);
878             }
879 }
880 
fillWithUniqueColors(const tcu::PixelBufferAccess & dst,uint32_t seed)881 void fillWithUniqueColors(const tcu::PixelBufferAccess &dst, uint32_t seed)
882 {
883     // This is an implementation of linear congruential generator.
884     // The A and M are prime numbers, thus allowing to generate unique number sequence of length genM-1.
885     // The generator uses C constant as 0, thus value of 0 is not allowed as a seed.
886     const uint64_t genA = 1573051ull;
887     const uint64_t genM = 2097023ull;
888     uint64_t genX       = seed % genM;
889 
890     DE_ASSERT(uint64_t(dst.getWidth()) * uint64_t(dst.getHeight()) * uint64_t(dst.getDepth()) < genM - 1);
891 
892     if (genX == 0)
893         genX = 1;
894 
895     const int numCols   = dst.getWidth();
896     const int numRows   = dst.getHeight();
897     const int numSlices = dst.getDepth();
898 
899     for (int z = 0; z < numSlices; z++)
900         for (int y = 0; y < numRows; y++)
901             for (int x = 0; x < numCols; x++)
902             {
903                 genX = (genA * genX) % genM;
904 
905                 DE_ASSERT(genX != seed);
906 
907                 const float r         = float(uint32_t((genX >> 0) & 0x7F)) / 127.0f;
908                 const float g         = float(uint32_t((genX >> 7) & 0x7F)) / 127.0f;
909                 const float b         = float(uint32_t((genX >> 14) & 0x7F)) / 127.0f;
910                 const tcu::Vec4 color = tcu::Vec4(r, g, b, 1.0f);
911 
912                 dst.setPixel(color, x, y, z);
913             }
914 }
915 
916 } // namespace ProtectedMem
917 } // namespace vkt
918