• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, nullptr));
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, nullptr);
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, nullptr);
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 != VK_NULL_HANDLE &&
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, nullptr));
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, nullptr, 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         nullptr,
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, nullptr,
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                 nullptr,                                      // 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         nullptr,                                                // pEnabledLayerNames
272         (uint32_t)requiredExtensions.size(),                    // enabledExtensionCount
273         requiredExtensions.empty() ? nullptr : &enabledExts[0], // pEnabledExtensionNames
274         nullptr                                                 // pEnabledFeatures
275     };
276 
277     return createCustomDevice(cmdLine.isValidationEnabled(), vkp, instance, vkd, physicalDevice, &deviceParams,
278                               nullptr);
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         nullptr,                                   // 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 == nullptr)
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         nullptr,                                 // 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         nullptr,                                  // 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         nullptr,                                         // 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         nullptr,                                       // 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         nullptr,                                           // pNext
434         0u,                                                // flags
435         layoutCount,                                       // setLayoutCount
436         setLayouts,                                        // pSetLayouts
437         0u,                                                // pushConstantRangeCount
438         nullptr,                                           // 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 != VK_NULL_HANDLE ?
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         nullptr,                                         // 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         nullptr,                           // pNext
470         0u,                                // waitSemaphoreCount
471         nullptr,                           // pWaitSempahores
472         nullptr,                           // stageFlags
473         1u,                                // commandBufferCount
474         &cmdBuffer,                        // pCommandBuffers
475         0u,                                // signalSemaphoreCount
476         nullptr,                           // 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         nullptr,                                     // 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                                                 nullptr,
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         nullptr,                                                   // 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         VK_NULL_HANDLE,              // const VkShaderModule                          tessellationControlModule
568         VK_NULL_HANDLE,              // const VkShaderModule                          tessellationEvalModule
569         VK_NULL_HANDLE,              // 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         nullptr,                     // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
579         nullptr,                     // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
580         nullptr,                     // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
581         nullptr,                     // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo
582         nullptr,                     // const VkPipelineDynamicStateCreateInfo* dynamicStateCreateInfo
583         nullptr,                     // 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         nullptr,                                    // 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         nullptr,                                    // 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, nullptr, 0, nullptr, 1, &preImageBarrier);
652     vk.cmdClearColorImage(*cmdBuffer, image, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1,
653                           &subresourceRange);
654     vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
655                           (vk::VkDependencyFlags)0, 0, nullptr, 0, nullptr, 1, &postImageBarrier);
656     endCommandBuffer(vk, *cmdBuffer);
657 
658     {
659         const vk::Unique<vk::VkFence> fence(createFence(vk, device));
660         VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
661     }
662 }
663 
uploadImage(ProtectedContext & ctx,vk::VkImage image,const tcu::Texture2D & texture2D)664 void uploadImage(ProtectedContext &ctx, vk::VkImage image, const tcu::Texture2D &texture2D)
665 {
666     const vk::DeviceInterface &vk   = ctx.getDeviceInterface();
667     const vk::VkDevice device       = ctx.getDevice();
668     const vk::VkQueue queue         = ctx.getQueue();
669     const uint32_t queueFamilyIndex = ctx.getQueueFamilyIndex();
670 
671     vk::Unique<vk::VkCommandPool> cmdPool(makeCommandPool(vk, device, PROTECTION_DISABLED, queueFamilyIndex));
672     vk::Unique<vk::VkCommandBuffer> cmdBuffer(
673         vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
674 
675     const uint32_t width             = (uint32_t)texture2D.getWidth();
676     const uint32_t height            = (uint32_t)texture2D.getHeight();
677     const uint32_t stagingBufferSize = width * height * tcu::getPixelSize(texture2D.getFormat());
678 
679     de::UniquePtr<vk::BufferWithMemory> stagingBuffer(
680         makeBuffer(ctx, PROTECTION_DISABLED, queueFamilyIndex, stagingBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
681                    vk::MemoryRequirement::HostVisible));
682 
683     {
684         const tcu::ConstPixelBufferAccess &access = texture2D.getLevel(0);
685         const tcu::PixelBufferAccess destAccess(access.getFormat(), access.getSize(),
686                                                 stagingBuffer->getAllocation().getHostPtr());
687 
688         tcu::copy(destAccess, access);
689 
690         flushAlloc(vk, device, stagingBuffer->getAllocation());
691     }
692 
693     const vk::VkImageSubresourceRange subresourceRange = {
694         vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags    aspectMask
695         0u,                            // uint32_t                baseMipLevel
696         1u,                            // uint32_t                levelCount
697         0u,                            // uint32_t                baseArrayLayer
698         1u,                            // uint32_t                layerCount
699     };
700 
701     const vk::VkImageMemoryBarrier preCopyBarrier = {
702         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
703         nullptr,                                    // const void* pNext;
704         0u,                                         // VkAccessFlags srcAccessMask;
705         vk::VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
706         vk::VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout oldLayout;
707         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout newLayout;
708         queueFamilyIndex,                           // uint32_t srcQueueFamilyIndex;
709         queueFamilyIndex,                           // uint32_t dstQueueFamilyIndex;
710         image,                                      // VkImage image;
711         subresourceRange                            // VkImageSubresourceRange subresourceRange;
712     };
713 
714     const vk::VkImageMemoryBarrier postCopyBarrier = {
715         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
716         nullptr,                                    // const void* pNext;
717         vk::VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags srcAccessMask;
718         vk::VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
719         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout oldLayout;
720         vk::VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout newLayout;
721         queueFamilyIndex,                           // uint32_t srcQueueFamilyIndex;
722         queueFamilyIndex,                           // uint32_t dstQueueFamilyIndex;
723         image,                                      // VkImage image;
724         subresourceRange                            // VkImageSubresourceRange subresourceRange;
725     };
726 
727     const vk::VkImageSubresourceLayers subresourceLayers = {
728         vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
729         0u,                            // uint32_t mipLevel;
730         0u,                            // uint32_t baseArrayLayer;
731         1u                             // uint32_t layerCount;
732     };
733 
734     const vk::VkBufferImageCopy copyRegion = {
735         0u,                 // VkDeviceSize bufferOffset;
736         width,              // uint32_t bufferRowLength;
737         height,             // uint32_t bufferImageHeight;
738         subresourceLayers,  // VkImageSubresourceLayers imageSubresource;
739         {0u, 0u, 0u},       // VkOffset3D imageOffset;
740         {width, height, 1u} // VkExtent3D imageExtent;
741     };
742 
743     beginCommandBuffer(vk, *cmdBuffer);
744     vk.cmdPipelineBarrier(*cmdBuffer, (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_HOST_BIT,
745                           (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u,
746                           nullptr, 0u, nullptr, 1u, &preCopyBarrier);
747     vk.cmdCopyBufferToImage(*cmdBuffer, **stagingBuffer, image, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u,
748                             &copyRegion);
749     vk.cmdPipelineBarrier(*cmdBuffer, (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
750                           (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u,
751                           nullptr, 0u, nullptr, 1u, &postCopyBarrier);
752     endCommandBuffer(vk, *cmdBuffer);
753 
754     {
755         const vk::Unique<vk::VkFence> fence(createFence(vk, device));
756         VK_CHECK(queueSubmit(ctx, PROTECTION_DISABLED, queue, *cmdBuffer, *fence, ~0ull));
757     }
758 }
759 
copyToProtectedImage(ProtectedContext & ctx,vk::VkImage srcImage,vk::VkImage dstImage,vk::VkImageLayout dstImageLayout,uint32_t width,uint32_t height,ProtectionMode protectionMode)760 void copyToProtectedImage(ProtectedContext &ctx, vk::VkImage srcImage, vk::VkImage dstImage,
761                           vk::VkImageLayout dstImageLayout, uint32_t width, uint32_t height,
762                           ProtectionMode protectionMode)
763 {
764     const vk::DeviceInterface &vk   = ctx.getDeviceInterface();
765     const vk::VkDevice device       = ctx.getDevice();
766     const vk::VkQueue queue         = ctx.getQueue();
767     const uint32_t queueFamilyIndex = ctx.getQueueFamilyIndex();
768 
769     vk::Unique<vk::VkCommandPool> cmdPool(makeCommandPool(vk, device, protectionMode, queueFamilyIndex));
770     vk::Unique<vk::VkCommandBuffer> cmdBuffer(
771         vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
772 
773     const vk::VkImageSubresourceRange subresourceRange = {
774         vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags    aspectMask
775         0u,                            // uint32_t                baseMipLevel
776         1u,                            // uint32_t                levelCount
777         0u,                            // uint32_t                baseArrayLayer
778         1u,                            // uint32_t                layerCount
779     };
780 
781     const vk::VkImageMemoryBarrier preImageBarriers[] = {
782         // source image
783         {
784             vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
785             nullptr,                                    // const void* pNext;
786             vk::VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags srcAccessMask;
787             vk::VK_ACCESS_TRANSFER_READ_BIT,            // VkAccessFlags dstAccessMask;
788             vk::VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout oldLayout;
789             vk::VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout newLayout;
790             queueFamilyIndex,                           // uint32_t srcQueueFamilyIndex;
791             queueFamilyIndex,                           // uint32_t dstQueueFamilyIndex;
792             srcImage,                                   // VkImage image;
793             subresourceRange                            // VkImageSubresourceRange subresourceRange;
794         },
795         // destination image
796         {
797             vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
798             nullptr,                                    // const void* pNext;
799             0,                                          // VkAccessFlags srcAccessMask;
800             vk::VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
801             vk::VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout oldLayout;
802             vk::VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout newLayout;
803             queueFamilyIndex,                           // uint32_t srcQueueFamilyIndex;
804             queueFamilyIndex,                           // uint32_t dstQueueFamilyIndex;
805             dstImage,                                   // VkImage image;
806             subresourceRange                            // VkImageSubresourceRange subresourceRange;
807         }};
808 
809     const vk::VkImageMemoryBarrier postImgBarrier = {
810         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
811         nullptr,                                    // const void* pNext;
812         vk::VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags srcAccessMask;
813         vk::VK_ACCESS_SHADER_READ_BIT,              // VkAccessFlags dstAccessMask;
814         vk::VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout oldLayout;
815         dstImageLayout,                             // VkImageLayout newLayout;
816         queueFamilyIndex,                           // uint32_t srcQueueFamilyIndex;
817         queueFamilyIndex,                           // uint32_t dstQueueFamilyIndex;
818         dstImage,                                   // VkImage image;
819         subresourceRange                            // VkImageSubresourceRange subresourceRange;
820     };
821 
822     const vk::VkImageSubresourceLayers subresourceLayers = {
823         vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
824         0u,                            // uint32_t mipLevel;
825         0u,                            // uint32_t baseArrayLayer;
826         1u                             // uint32_t layerCount;
827     };
828 
829     const vk::VkImageCopy copyImageRegion = {
830         subresourceLayers,   // VkImageSubresourceCopy srcSubresource;
831         {0, 0, 0},           // VkOffset3D srcOffset;
832         subresourceLayers,   // VkImageSubresourceCopy destSubresource;
833         {0, 0, 0},           // VkOffset3D destOffset;
834         {width, height, 1u}, // VkExtent3D extent;
835     };
836 
837     beginCommandBuffer(vk, *cmdBuffer);
838     vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
839                           (vk::VkDependencyFlags)0, 0, nullptr, 0, nullptr, DE_LENGTH_OF_ARRAY(preImageBarriers),
840                           preImageBarriers);
841     vk.cmdCopyImage(*cmdBuffer, srcImage, vk::VK_IMAGE_LAYOUT_GENERAL, dstImage, vk::VK_IMAGE_LAYOUT_GENERAL, 1u,
842                     &copyImageRegion);
843     vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
844                           (vk::VkDependencyFlags)0, 0, nullptr, 0, nullptr, 1, &postImgBarrier);
845     endCommandBuffer(vk, *cmdBuffer);
846 
847     {
848         const vk::Unique<vk::VkFence> fence(createFence(vk, device));
849         VK_CHECK(queueSubmit(ctx, protectionMode, queue, *cmdBuffer, *fence, ~0ull));
850     }
851 }
852 
fillWithRandomColorTiles(const tcu::PixelBufferAccess & dst,const tcu::Vec4 & minVal,const tcu::Vec4 & maxVal,uint32_t seed)853 void fillWithRandomColorTiles(const tcu::PixelBufferAccess &dst, const tcu::Vec4 &minVal, const tcu::Vec4 &maxVal,
854                               uint32_t seed)
855 {
856     const int numCols = dst.getWidth() >= 7 ? 7 : dst.getWidth();
857     const int numRows = dst.getHeight() >= 5 ? 5 : dst.getHeight();
858     de::Random rnd(seed);
859 
860     for (int slice = 0; slice < dst.getDepth(); slice++)
861         for (int row = 0; row < numRows; row++)
862             for (int col = 0; col < numCols; col++)
863             {
864                 const int yBegin = (row + 0) * dst.getHeight() / numRows;
865                 const int yEnd   = (row + 1) * dst.getHeight() / numRows;
866                 const int xBegin = (col + 0) * dst.getWidth() / numCols;
867                 const int xEnd   = (col + 1) * dst.getWidth() / numCols;
868                 tcu::Vec4 color;
869                 for (int i = 0; i < 4; i++)
870                     color[i] = rnd.getFloat(minVal[i], maxVal[i]);
871                 tcu::clear(tcu::getSubregion(dst, xBegin, yBegin, slice, xEnd - xBegin, yEnd - yBegin, 1), color);
872             }
873 }
874 
fillWithUniqueColors(const tcu::PixelBufferAccess & dst,uint32_t seed)875 void fillWithUniqueColors(const tcu::PixelBufferAccess &dst, uint32_t seed)
876 {
877     // This is an implementation of linear congruential generator.
878     // The A and M are prime numbers, thus allowing to generate unique number sequence of length genM-1.
879     // The generator uses C constant as 0, thus value of 0 is not allowed as a seed.
880     const uint64_t genA = 1573051ull;
881     const uint64_t genM = 2097023ull;
882     uint64_t genX       = seed % genM;
883 
884     DE_ASSERT(uint64_t(dst.getWidth()) * uint64_t(dst.getHeight()) * uint64_t(dst.getDepth()) < genM - 1);
885 
886     if (genX == 0)
887         genX = 1;
888 
889     const int numCols   = dst.getWidth();
890     const int numRows   = dst.getHeight();
891     const int numSlices = dst.getDepth();
892 
893     for (int z = 0; z < numSlices; z++)
894         for (int y = 0; y < numRows; y++)
895             for (int x = 0; x < numCols; x++)
896             {
897                 genX = (genA * genX) % genM;
898 
899                 DE_ASSERT(genX != seed);
900 
901                 const float r         = float(uint32_t((genX >> 0) & 0x7F)) / 127.0f;
902                 const float g         = float(uint32_t((genX >> 7) & 0x7F)) / 127.0f;
903                 const float b         = float(uint32_t((genX >> 14) & 0x7F)) / 127.0f;
904                 const tcu::Vec4 color = tcu::Vec4(r, g, b, 1.0f);
905 
906                 dst.setPixel(color, x, y, z);
907             }
908 }
909 
910 } // namespace ProtectedMem
911 } // namespace vkt
912