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