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(), ¶ms);
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(), ¶ms);
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 ©Region);
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 ©ImageRegion);
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