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