1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Platform Synchronization tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktSynchronizationSmokeTests.hpp"
25 #include "vktSynchronizationUtil.hpp"
26
27 #include "vktTestCaseUtil.hpp"
28 #include "vktCustomInstancesDevices.hpp"
29
30 #include "vkPlatform.hpp"
31 #include "vkStrUtil.hpp"
32 #include "vkRef.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkDeviceUtil.hpp"
35 #include "vkCmdUtil.hpp"
36
37 #include "tcuTestLog.hpp"
38 #include "tcuFormatUtil.hpp"
39 #include "tcuCommandLine.hpp"
40
41 #include "deUniquePtr.hpp"
42 #include "deThread.hpp"
43 #include "vkMemUtil.hpp"
44 #include "vkQueryUtil.hpp"
45 #include "vkPrograms.hpp"
46 #include "vkTypeUtil.hpp"
47 #include "vkCmdUtil.hpp"
48
49 #include <limits>
50
51 namespace vkt
52 {
53 namespace synchronization
54 {
55
56 using namespace vk;
57 using namespace tcu;
58
59 namespace
60 {
61
62 using std::vector;
63 using std::string;
64 using tcu::TestLog;
65 using de::UniquePtr;
66 using de::MovePtr;
67
68 static const deUint64 DEFAULT_TIMEOUT = 2ull*1000*1000*1000; //!< 2 seconds in nanoseconds
69
70 struct SemaphoreTestConfig
71 {
72 SynchronizationType synchronizationType;
73 VkSemaphoreType semaphoreType;
74 };
75
initShaders(SourceCollections & shaderCollection,SemaphoreTestConfig)76 void initShaders(SourceCollections& shaderCollection, SemaphoreTestConfig)
77 {
78 shaderCollection.glslSources.add("glslvert") <<
79 glu::VertexSource(
80 "#version 310 es\n"
81 "precision mediump float;\n"
82 "layout (location = 0) in vec4 vertexPosition;\n"
83 "void main()\n"
84 "{\n"
85 " gl_Position = vertexPosition;\n"
86 "}\n");
87
88 shaderCollection.glslSources.add("glslfrag") <<
89 glu::FragmentSource(
90 "#version 310 es\n"
91 "precision mediump float;\n"
92 "layout (location = 0) out vec4 outputColor;\n"
93 "void main()\n"
94 "{\n"
95 " outputColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
96 "}\n");
97 }
98
buildShaders(SourceCollections & shaderCollection)99 void buildShaders(SourceCollections& shaderCollection)
100 {
101 initShaders(shaderCollection, { SynchronizationType::LEGACY, VK_SEMAPHORE_TYPE_BINARY });
102 }
103
createTestDevice(Context & context,SemaphoreTestConfig & config,deUint32 * outQueueFamilyIndex)104 Move<VkDevice> createTestDevice (Context& context, SemaphoreTestConfig& config, deUint32* outQueueFamilyIndex)
105 {
106 const PlatformInterface& vkp = context.getPlatformInterface();
107 VkInstance instance = context.getInstance();
108 const InstanceInterface& vki = context.getInstanceInterface();
109 VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
110 bool validationEnabled = context.getTestContext().getCommandLine().isValidationEnabled();
111 VkDeviceQueueCreateInfo queueInfo;
112 VkDeviceCreateInfo deviceInfo;
113 size_t queueNdx;
114 const deUint32 queueCount = 2u;
115 const float queuePriority[queueCount] = { 1.0f, 1.0f };
116
117 const vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
118 const VkPhysicalDeviceFeatures physicalDeviceFeatures = getPhysicalDeviceFeatures(vki, physicalDevice);
119 VkPhysicalDeviceFeatures2 physicalDeviceFeatures2 { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, DE_NULL, physicalDeviceFeatures };
120 VkPhysicalDeviceSynchronization2FeaturesKHR synchronization2Features { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR, DE_NULL, DE_TRUE };
121 VkPhysicalDeviceTimelineSemaphoreFeatures timelineSemaphoreFeatures { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, DE_NULL, DE_TRUE };
122 void** nextPtr = &physicalDeviceFeatures2.pNext;
123
124 for (queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
125 {
126 if ((queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT) == VK_QUEUE_GRAPHICS_BIT && (queueProps[queueNdx].queueCount >= queueCount))
127 break;
128 }
129
130 if (queueNdx >= queueProps.size())
131 {
132 // No queue family index found
133 std::ostringstream msg;
134 msg << "Cannot create device with " << queueCount << " graphics queues";
135
136 throw tcu::NotSupportedError(msg.str());
137 }
138
139 deMemset(&queueInfo, 0, sizeof(queueInfo));
140 deMemset(&deviceInfo, 0, sizeof(deviceInfo));
141
142 deMemset(&queueInfo, 0xcd, sizeof(queueInfo));
143 queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
144 queueInfo.pNext = DE_NULL;
145 queueInfo.flags = (VkDeviceQueueCreateFlags)0u;
146 queueInfo.queueFamilyIndex = (deUint32)queueNdx;
147 queueInfo.queueCount = queueCount;
148 queueInfo.pQueuePriorities = queuePriority;
149
150 vector<const char*> deviceExtensions;
151 if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE)
152 {
153 deviceExtensions.push_back("VK_KHR_timeline_semaphore");
154 addToChainVulkanStructure(&nextPtr, timelineSemaphoreFeatures);
155 }
156 if (config.synchronizationType == SynchronizationType::SYNCHRONIZATION2)
157 {
158 deviceExtensions.push_back("VK_KHR_synchronization2");
159 addToChainVulkanStructure(&nextPtr, synchronization2Features);
160 }
161
162 deMemset(&deviceInfo, 0xcd, sizeof(deviceInfo));
163 deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
164 deviceInfo.pNext = deviceExtensions.empty() ? DE_NULL : &physicalDeviceFeatures2;
165 deviceInfo.flags = (VkDeviceCreateFlags)0u;
166 deviceInfo.queueCreateInfoCount = 1u;
167 deviceInfo.pQueueCreateInfos = &queueInfo;
168 deviceInfo.enabledExtensionCount = static_cast<deUint32>(deviceExtensions.size());
169 deviceInfo.ppEnabledExtensionNames = deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0];
170 deviceInfo.enabledLayerCount = 0u;
171 deviceInfo.ppEnabledLayerNames = DE_NULL;
172 deviceInfo.pEnabledFeatures = deviceExtensions.empty() ? &physicalDeviceFeatures : DE_NULL;
173
174 *outQueueFamilyIndex = queueInfo.queueFamilyIndex;
175
176 return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceInfo);
177 }
178
179 struct BufferParameters
180 {
181 const void* memory;
182 VkDeviceSize size;
183 VkBufferUsageFlags usage;
184 VkSharingMode sharingMode;
185 deUint32 queueFamilyCount;
186 const deUint32* queueFamilyIndex;
187 VkAccessFlags inputBarrierFlags;
188 };
189
190 struct Buffer
191 {
192 MovePtr<Allocation> allocation;
193 vector<VkMemoryBarrier> memoryBarrier;
194 vk::Move<VkBuffer> buffer;
195 };
196
createVulkanBuffer(const DeviceInterface & vkd,VkDevice device,Allocator & allocator,const BufferParameters & bufferParameters,Buffer & buffer,MemoryRequirement visibility)197 void createVulkanBuffer (const DeviceInterface& vkd, VkDevice device, Allocator& allocator, const BufferParameters& bufferParameters, Buffer& buffer, MemoryRequirement visibility)
198 {
199 VkBufferCreateInfo bufferCreateParams;
200
201 deMemset(&bufferCreateParams, 0xcd, sizeof(bufferCreateParams));
202 bufferCreateParams.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
203 bufferCreateParams.pNext = DE_NULL;
204 bufferCreateParams.flags = 0;
205 bufferCreateParams.size = bufferParameters.size;
206 bufferCreateParams.usage = bufferParameters.usage;
207 bufferCreateParams.sharingMode = bufferParameters.sharingMode;
208 bufferCreateParams.queueFamilyIndexCount = bufferParameters.queueFamilyCount;
209 bufferCreateParams.pQueueFamilyIndices = bufferParameters.queueFamilyIndex;
210
211 buffer.buffer = createBuffer(vkd, device, &bufferCreateParams);
212 buffer.allocation = allocator.allocate(getBufferMemoryRequirements(vkd, device, *buffer.buffer), visibility);
213
214 VK_CHECK(vkd.bindBufferMemory(device, *buffer.buffer, buffer.allocation->getMemory(), buffer.allocation->getOffset()));
215
216 // If caller provides a host memory buffer for the allocation, then go
217 // ahead and copy the provided data into the allocation and update the
218 // barrier list with the associated access
219 if (bufferParameters.memory != DE_NULL)
220 {
221 VkMemoryBarrier barrier;
222
223 deMemcpy(buffer.allocation->getHostPtr(), bufferParameters.memory, (size_t)bufferParameters.size);
224 flushAlloc(vkd, device, *buffer.allocation);
225
226 deMemset(&barrier, 0xcd, sizeof(barrier));
227 barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
228 barrier.pNext = DE_NULL;
229 barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
230 barrier.dstAccessMask = bufferParameters.inputBarrierFlags;
231
232 buffer.memoryBarrier.push_back(barrier);
233 }
234 }
235
236 struct ImageParameters
237 {
238 VkImageType imageType;
239 VkFormat format;
240 VkExtent3D extent3D;
241 deUint32 mipLevels;
242 VkSampleCountFlagBits samples;
243 VkImageTiling tiling;
244 VkBufferUsageFlags usage;
245 VkSharingMode sharingMode;
246 deUint32 queueFamilyCount;
247 const deUint32* queueFamilyNdxList;
248 VkImageLayout initialLayout;
249 VkImageLayout finalLayout;
250 VkAccessFlags barrierInputMask;
251 };
252
253 struct Image
254 {
255 vk::Move<VkImage> image;
256 vk::Move<VkImageView> imageView;
257 MovePtr<Allocation> allocation;
258 vector<VkImageMemoryBarrier> imageMemoryBarrier;
259 };
260
createVulkanImage(const DeviceInterface & vkd,VkDevice device,Allocator & allocator,const ImageParameters & imageParameters,Image & image,MemoryRequirement visibility)261 void createVulkanImage (const DeviceInterface& vkd, VkDevice device, Allocator& allocator, const ImageParameters& imageParameters, Image& image, MemoryRequirement visibility)
262 {
263 VkComponentMapping componentMap;
264 VkImageSubresourceRange subresourceRange;
265 VkImageViewCreateInfo imageViewCreateInfo;
266 VkImageCreateInfo imageCreateParams;
267 VkImageMemoryBarrier imageBarrier;
268
269 deMemset(&imageCreateParams, 0xcd, sizeof(imageCreateParams));
270 imageCreateParams.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
271 imageCreateParams.pNext = DE_NULL;
272 imageCreateParams.flags = 0;
273 imageCreateParams.imageType = imageParameters.imageType;
274 imageCreateParams.format = imageParameters.format;
275 imageCreateParams.extent = imageParameters.extent3D;
276 imageCreateParams.mipLevels = imageParameters.mipLevels;
277 imageCreateParams.arrayLayers = 1;
278 imageCreateParams.samples = imageParameters.samples;
279 imageCreateParams.tiling = imageParameters.tiling;
280 imageCreateParams.usage = imageParameters.usage;
281 imageCreateParams.sharingMode = imageParameters.sharingMode;
282 imageCreateParams.queueFamilyIndexCount = imageParameters.queueFamilyCount;
283 imageCreateParams.pQueueFamilyIndices = imageParameters.queueFamilyNdxList;
284 imageCreateParams.initialLayout = imageParameters.initialLayout;
285
286 image.image = createImage(vkd, device, &imageCreateParams);
287 image.allocation = allocator.allocate(getImageMemoryRequirements(vkd, device, *image.image), visibility);
288
289 VK_CHECK(vkd.bindImageMemory(device, *image.image, image.allocation->getMemory(), image.allocation->getOffset()));
290
291 componentMap.r = VK_COMPONENT_SWIZZLE_R;
292 componentMap.g = VK_COMPONENT_SWIZZLE_G;
293 componentMap.b = VK_COMPONENT_SWIZZLE_B;
294 componentMap.a = VK_COMPONENT_SWIZZLE_A;
295
296 subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
297 subresourceRange.baseMipLevel = 0;
298 subresourceRange.levelCount = imageParameters.mipLevels;
299 subresourceRange.baseArrayLayer = 0;
300 subresourceRange.layerCount = 1;
301
302 deMemset(&imageViewCreateInfo, 0xcd, sizeof(imageViewCreateInfo));
303 imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
304 imageViewCreateInfo.pNext = DE_NULL;
305 imageViewCreateInfo.flags = 0;
306 imageViewCreateInfo.image = image.image.get();
307 imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
308 imageViewCreateInfo.format = imageParameters.format;
309 imageViewCreateInfo.components = componentMap;
310 imageViewCreateInfo.subresourceRange = subresourceRange;
311
312 image.imageView = createImageView(vkd, device, &imageViewCreateInfo);
313
314 deMemset(&imageBarrier, 0xcd, sizeof(imageBarrier));
315 imageBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
316 imageBarrier.pNext = DE_NULL;
317 imageBarrier.srcAccessMask = 0;
318 imageBarrier.dstAccessMask = imageParameters.barrierInputMask;
319 imageBarrier.oldLayout = imageParameters.initialLayout;
320 imageBarrier.newLayout = imageParameters.finalLayout;
321 imageBarrier.srcQueueFamilyIndex = imageParameters.queueFamilyNdxList[0];
322 imageBarrier.dstQueueFamilyIndex = imageParameters.queueFamilyNdxList[imageParameters.queueFamilyCount-1];
323 imageBarrier.image = image.image.get();
324 imageBarrier.subresourceRange = subresourceRange;
325
326 image.imageMemoryBarrier.push_back(imageBarrier);
327 }
328
329 struct RenderPassParameters
330 {
331 VkFormat colorFormat;
332 VkSampleCountFlagBits colorSamples;
333 };
334
createColorOnlyRenderPass(const DeviceInterface & vkd,VkDevice device,const RenderPassParameters & renderPassParameters,vk::Move<VkRenderPass> & renderPass)335 void createColorOnlyRenderPass (const DeviceInterface& vkd, VkDevice device, const RenderPassParameters& renderPassParameters, vk::Move<VkRenderPass>& renderPass)
336 {
337 VkAttachmentDescription colorAttachmentDesc;
338 VkAttachmentReference colorAttachmentRef;
339 VkAttachmentReference stencilAttachmentRef;
340 VkSubpassDescription subpassDesc;
341 VkRenderPassCreateInfo renderPassParams;
342 VkRenderPass newRenderPass;
343
344 colorAttachmentDesc.flags = 0;
345 colorAttachmentDesc.format = renderPassParameters.colorFormat;
346 colorAttachmentDesc.samples = renderPassParameters.colorSamples;
347 colorAttachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
348 colorAttachmentDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
349 colorAttachmentDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
350 colorAttachmentDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
351 colorAttachmentDesc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
352 colorAttachmentDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
353
354 colorAttachmentRef.attachment = 0;
355 colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
356
357 stencilAttachmentRef.attachment = VK_ATTACHMENT_UNUSED;
358 stencilAttachmentRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
359
360 subpassDesc.flags = 0;
361 subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
362 subpassDesc.inputAttachmentCount = 0;
363 subpassDesc.pInputAttachments = DE_NULL;
364 subpassDesc.colorAttachmentCount = 1;
365 subpassDesc.pColorAttachments = &colorAttachmentRef;
366 subpassDesc.pResolveAttachments = DE_NULL;
367 subpassDesc.pDepthStencilAttachment = &stencilAttachmentRef;
368 subpassDesc.preserveAttachmentCount = 0;
369 subpassDesc.pPreserveAttachments = DE_NULL;
370
371 deMemset(&renderPassParams, 0xcd, sizeof(renderPassParams));
372 renderPassParams.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
373 renderPassParams.pNext = DE_NULL;
374 renderPassParams.flags = 0;
375 renderPassParams.attachmentCount = 1;
376 renderPassParams.pAttachments = &colorAttachmentDesc;
377 renderPassParams.subpassCount = 1;
378 renderPassParams.pSubpasses = &subpassDesc;
379 renderPassParams.dependencyCount = 0;
380 renderPassParams.pDependencies = DE_NULL;
381
382 renderPass = createRenderPass(vkd, device, &renderPassParams);
383 }
384
385 struct ShaderDescParams
386 {
387 VkShaderModule shaderModule;
388 VkShaderStageFlagBits stage;
389 };
390
391 struct VertexDesc
392 {
393 deUint32 location;
394 VkFormat format;
395 deUint32 stride;
396 deUint32 offset;
397 };
398
createVertexInfo(const vector<VertexDesc> & vertexDesc,vector<VkVertexInputBindingDescription> & bindingList,vector<VkVertexInputAttributeDescription> & attrList,VkPipelineVertexInputStateCreateInfo & vertexInputState)399 void createVertexInfo (const vector<VertexDesc>& vertexDesc, vector<VkVertexInputBindingDescription>& bindingList, vector<VkVertexInputAttributeDescription>& attrList, VkPipelineVertexInputStateCreateInfo& vertexInputState)
400 {
401 for (vector<VertexDesc>::const_iterator vertDescIter = vertexDesc.begin(); vertDescIter != vertexDesc.end(); vertDescIter++)
402 {
403 deUint32 bindingId = 0;
404 VkVertexInputBindingDescription bindingDesc;
405 VkVertexInputAttributeDescription attrDesc;
406
407 bindingDesc.binding = bindingId;
408 bindingDesc.stride = vertDescIter->stride;
409 bindingDesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
410 bindingList.push_back(bindingDesc);
411
412 attrDesc.location = vertDescIter->location;
413 attrDesc.binding = bindingId;
414 attrDesc.format = vertDescIter->format;
415 attrDesc.offset = vertDescIter->offset;
416 attrList.push_back(attrDesc);
417
418 bindingId++;
419 }
420
421 deMemset(&vertexInputState, 0xcd, sizeof(vertexInputState));
422 vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
423 vertexInputState.pNext = DE_NULL;
424 vertexInputState.flags = 0u;
425 vertexInputState.vertexBindingDescriptionCount = (deUint32)bindingList.size();
426 vertexInputState.pVertexBindingDescriptions = &bindingList[0];
427 vertexInputState.vertexAttributeDescriptionCount = (deUint32)attrList.size();
428 vertexInputState.pVertexAttributeDescriptions = &attrList[0];
429 }
430
createCommandBuffer(const DeviceInterface & deviceInterface,const VkDevice device,const deUint32 queueFamilyNdx,vk::Move<VkCommandBuffer> * commandBufferRef,vk::Move<VkCommandPool> * commandPoolRef)431 void createCommandBuffer (const DeviceInterface& deviceInterface, const VkDevice device, const deUint32 queueFamilyNdx, vk::Move<VkCommandBuffer>* commandBufferRef, vk::Move<VkCommandPool>* commandPoolRef)
432 {
433 vk::Move<VkCommandPool> commandPool;
434 VkCommandBufferAllocateInfo commandBufferInfo;
435 VkCommandBuffer commandBuffer;
436
437 commandPool = createCommandPool(deviceInterface, device, 0u, queueFamilyNdx);
438
439 deMemset(&commandBufferInfo, 0xcd, sizeof(commandBufferInfo));
440 commandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
441 commandBufferInfo.pNext = DE_NULL;
442 commandBufferInfo.commandPool = commandPool.get();
443 commandBufferInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
444 commandBufferInfo.commandBufferCount = 1;
445
446 VK_CHECK(deviceInterface.allocateCommandBuffers(device, &commandBufferInfo, &commandBuffer));
447 *commandBufferRef = vk::Move<VkCommandBuffer>(vk::check<VkCommandBuffer>(commandBuffer), Deleter<VkCommandBuffer>(deviceInterface, device, commandPool.get()));
448 *commandPoolRef = commandPool;
449 }
450
createFences(const DeviceInterface & deviceInterface,VkDevice device,bool signaled,deUint32 numFences,VkFence * fence)451 void createFences (const DeviceInterface& deviceInterface, VkDevice device, bool signaled, deUint32 numFences, VkFence* fence)
452 {
453 VkFenceCreateInfo fenceState;
454 VkFenceCreateFlags signalFlag = signaled ? VK_FENCE_CREATE_SIGNALED_BIT : 0;
455
456 deMemset(&fenceState, 0xcd, sizeof(fenceState));
457 fenceState.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
458 fenceState.pNext = DE_NULL;
459 fenceState.flags = signalFlag;
460
461 for (deUint32 ndx = 0; ndx < numFences; ndx++)
462 VK_CHECK(deviceInterface.createFence(device, &fenceState, DE_NULL, &fence[ndx]));
463 }
464
destroyFences(const DeviceInterface & deviceInterface,VkDevice device,deUint32 numFences,VkFence * fence)465 void destroyFences (const DeviceInterface& deviceInterface, VkDevice device, deUint32 numFences, VkFence* fence)
466 {
467 for (deUint32 ndx = 0; ndx < numFences; ndx++)
468 deviceInterface.destroyFence(device, fence[ndx], DE_NULL);
469 }
470
471 struct RenderInfo
472 {
473 deInt32 width;
474 deInt32 height;
475 deUint32 vertexBufferSize;
476 VkBuffer vertexBuffer;
477 VkImage image;
478 VkCommandBuffer commandBuffer;
479 VkRenderPass renderPass;
480 VkFramebuffer framebuffer;
481 VkPipeline pipeline;
482 deUint32 mipLevels;
483 const deUint32* queueFamilyNdxList;
484 deUint32 queueFamilyNdxCount;
485 bool waitEvent;
486 VkEvent event;
487 vector<VkImageMemoryBarrier>* barriers;
488 };
489
recordRenderPass(const DeviceInterface & deviceInterface,const RenderInfo & renderInfo)490 void recordRenderPass (const DeviceInterface& deviceInterface, const RenderInfo& renderInfo)
491 {
492 const VkDeviceSize bindingOffset = 0;
493 VkImageMemoryBarrier renderBarrier;
494
495 if (renderInfo.waitEvent)
496 deviceInterface.cmdWaitEvents(renderInfo.commandBuffer, 1, &renderInfo.event, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, DE_NULL, 0, DE_NULL, 0, DE_NULL);
497
498 beginRenderPass(deviceInterface, renderInfo.commandBuffer, renderInfo.renderPass, renderInfo.framebuffer, makeRect2D(0, 0, renderInfo.width, renderInfo.height), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
499 deviceInterface.cmdBindPipeline(renderInfo.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, renderInfo.pipeline);
500 deviceInterface.cmdBindVertexBuffers(renderInfo.commandBuffer, 0u, 1u, &renderInfo.vertexBuffer, &bindingOffset);
501 deviceInterface.cmdDraw(renderInfo.commandBuffer, renderInfo.vertexBufferSize, 1, 0, 0);
502 endRenderPass(deviceInterface, renderInfo.commandBuffer);
503
504 deMemset(&renderBarrier, 0xcd, sizeof(renderBarrier));
505 renderBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
506 renderBarrier.pNext = DE_NULL;
507 renderBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
508 renderBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
509 renderBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
510 renderBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
511 renderBarrier.srcQueueFamilyIndex = renderInfo.queueFamilyNdxList[0];
512 renderBarrier.dstQueueFamilyIndex = renderInfo.queueFamilyNdxList[renderInfo.queueFamilyNdxCount-1];
513 renderBarrier.image = renderInfo.image;
514 renderBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
515 renderBarrier.subresourceRange.baseMipLevel = 0;
516 renderBarrier.subresourceRange.levelCount = renderInfo.mipLevels;
517 renderBarrier.subresourceRange.baseArrayLayer = 0;
518 renderBarrier.subresourceRange.layerCount = 1;
519 renderInfo.barriers->push_back(renderBarrier);
520 }
521
522 struct TransferInfo
523 {
524 VkCommandBuffer commandBuffer;
525 deUint32 width;
526 deUint32 height;
527 VkImage image;
528 VkBuffer buffer;
529 VkDeviceSize size;
530 deUint32 mipLevel;
531 VkOffset3D imageOffset;
532 vector<VkBufferMemoryBarrier>* barriers;
533 };
534
copyToCPU(const DeviceInterface & vkd,TransferInfo * transferInfo)535 void copyToCPU (const DeviceInterface& vkd, TransferInfo* transferInfo)
536 {
537 VkBufferImageCopy copyState;
538
539 copyState.bufferOffset = 0;
540 copyState.bufferRowLength = transferInfo->width;
541 copyState.bufferImageHeight = transferInfo->height;
542 copyState.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
543 copyState.imageSubresource.mipLevel = transferInfo->mipLevel;
544 copyState.imageSubresource.baseArrayLayer = 0;
545 copyState.imageSubresource.layerCount = 1;
546 copyState.imageOffset = transferInfo->imageOffset;
547 copyState.imageExtent.width = (deInt32)(transferInfo->width);
548 copyState.imageExtent.height = (deInt32)(transferInfo->height);
549 copyState.imageExtent.depth = 1;
550
551 vkd.cmdCopyImageToBuffer(transferInfo->commandBuffer, transferInfo->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, transferInfo->buffer, 1, ©State);
552
553 {
554 VkBufferMemoryBarrier bufferBarrier;
555 deMemset(&bufferBarrier, 0xcd, sizeof(bufferBarrier));
556 bufferBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
557 bufferBarrier.pNext = DE_NULL;
558 bufferBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
559 bufferBarrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
560 bufferBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
561 bufferBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
562 bufferBarrier.buffer = transferInfo->buffer;
563 bufferBarrier.offset = 0;
564 bufferBarrier.size = transferInfo->size;
565 transferInfo->barriers->push_back(bufferBarrier);
566 }
567 }
568
569 struct TestContext
570 {
571 const DeviceInterface& vkd;
572 const VkDevice device;
573 const deUint32 queueFamilyIndex;
574 const BinaryCollection& binaryCollection;
575 Allocator& allocator;
576
577 const tcu::Vec4* vertices;
578 deUint32 numVertices;
579 tcu::IVec2 renderDimension;
580 VkFence fences[2];
581 VkDeviceSize renderSize;
582 MovePtr<Allocation> renderReadBuffer;
583 MovePtr<Allocation> vertexBufferAllocation;
584 vk::Move<VkBuffer> vertexBuffer;
585 vk::Move<VkBuffer> renderBuffer;
586 bool waitEvent;
587 VkEvent event;
588 vk::Move<VkImage> image;
589 vk::Move<VkImageView> imageView;
590 vk::Move<VkFramebuffer> framebuffer;
591 vk::Move<VkCommandPool> commandPool;
592 vk::Move<VkCommandBuffer> cmdBuffer;
593 vk::Move<VkRenderPass> renderPass;
594 vk::Move<VkPipelineCache> pipelineCache;
595 vk::Move<VkPipeline> pipeline;
596 MovePtr<Allocation> imageAllocation;
597
TestContextvkt::synchronization::__anon3ffe92790111::TestContext598 TestContext (const DeviceInterface& vkd_,
599 const VkDevice device_,
600 deUint32 queueFamilyIndex_,
601 const BinaryCollection& binaryCollection_,
602 Allocator& allocator_)
603 : vkd (vkd_)
604 , device (device_)
605 , queueFamilyIndex (queueFamilyIndex_)
606 , binaryCollection (binaryCollection_)
607 , allocator (allocator_)
608 , vertices (0)
609 , numVertices (0)
610 , renderSize (0)
611 , waitEvent (false)
612 {
613 createFences(vkd, device, false, DE_LENGTH_OF_ARRAY(fences), fences);
614 }
615
~TestContextvkt::synchronization::__anon3ffe92790111::TestContext616 ~TestContext()
617 {
618 destroyFences(vkd, device, DE_LENGTH_OF_ARRAY(fences), fences);
619 }
620 };
621
generateWork(TestContext & testContext)622 void generateWork (TestContext& testContext)
623 {
624 const DeviceInterface& deviceInterface = testContext.vkd;
625 const deUint32 queueFamilyNdx = testContext.queueFamilyIndex;
626
627 // \note VkShaderModule is consumed by vkCreate*Pipelines() so it can be deleted
628 // as pipeline has been constructed.
629 const vk::Unique<VkShaderModule> vertShaderModule (createShaderModule(deviceInterface,
630 testContext.device,
631 testContext.binaryCollection.get("glslvert"),
632 (VkShaderModuleCreateFlags)0));
633
634 const vk::Unique<VkShaderModule> fragShaderModule (createShaderModule(deviceInterface,
635 testContext.device,
636 testContext.binaryCollection.get("glslfrag"),
637 (VkShaderModuleCreateFlags)0));
638 const VkPipelineShaderStageCreateInfo shaderStageParams[] =
639 {
640 {
641 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
642 DE_NULL,
643 (VkPipelineShaderStageCreateFlags)0,
644 VK_SHADER_STAGE_VERTEX_BIT,
645 *vertShaderModule,
646 "main",
647 (const VkSpecializationInfo*)DE_NULL,
648 },
649 {
650 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
651 DE_NULL,
652 (VkPipelineShaderStageCreateFlags)0,
653 VK_SHADER_STAGE_FRAGMENT_BIT,
654 *fragShaderModule,
655 "main",
656 (const VkSpecializationInfo*)DE_NULL,
657 }
658 };
659
660 vk::Move<VkPipelineLayout> layout;
661 vector<ShaderDescParams> shaderDescParams;
662 VertexDesc vertexDesc;
663 vector<VertexDesc> vertexDescList;
664 vector<VkVertexInputAttributeDescription> attrList;
665 vector<VkBufferMemoryBarrier> bufferMemoryBarrier;
666 deUint32 memoryBarrierNdx;
667 deUint32 bufferMemoryBarrierNdx;
668 deUint32 imageMemoryBarrierNdx;
669 vector<VkVertexInputBindingDescription> bindingList;
670 VkPipelineVertexInputStateCreateInfo vertexInputState;
671 VkPipelineInputAssemblyStateCreateInfo inputAssemblyState;
672 VkPipelineDepthStencilStateCreateInfo depthStencilState;
673 VkPipelineColorBlendAttachmentState blendAttachment;
674 VkPipelineColorBlendStateCreateInfo blendState;
675 VkPipelineLayoutCreateInfo pipelineLayoutState;
676 VkGraphicsPipelineCreateInfo pipelineState;
677 VkPipelineCacheCreateInfo cacheState;
678 VkViewport viewport;
679 VkPipelineViewportStateCreateInfo viewportInfo;
680 VkRect2D scissor;
681 BufferParameters bufferParameters;
682 Buffer buffer;
683 RenderInfo renderInfo;
684 ImageParameters imageParameters;
685 Image image;
686 VkPipelineRasterizationStateCreateInfo rasterState;
687 VkPipelineMultisampleStateCreateInfo multisampleState;
688 VkFramebufferCreateInfo fbState;
689 VkCommandBufferBeginInfo commandBufRecordState;
690 VkCommandBufferInheritanceInfo inheritanceInfo;
691 RenderPassParameters renderPassParameters;
692 TransferInfo transferInfo;
693 vector<void*> barrierList;
694 VkExtent3D extent;
695 vector<VkMemoryBarrier> memoryBarriers;
696 vector<VkBufferMemoryBarrier> bufferBarriers;
697 vector<VkImageMemoryBarrier> imageBarriers;
698
699 memoryBarrierNdx = 0;
700 bufferMemoryBarrierNdx = 0;
701 imageMemoryBarrierNdx = 0;
702 buffer.memoryBarrier.resize(memoryBarrierNdx);
703 bufferMemoryBarrier.resize(bufferMemoryBarrierNdx);
704 image.imageMemoryBarrier.resize(imageMemoryBarrierNdx);
705
706 memoryBarriers.resize(0);
707 bufferBarriers.resize(0);
708 imageBarriers.resize(0);
709
710 bufferParameters.memory = testContext.vertices;
711 bufferParameters.size = testContext.numVertices * sizeof(tcu::Vec4);
712 bufferParameters.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
713 bufferParameters.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
714 bufferParameters.queueFamilyCount = 1;
715 bufferParameters.queueFamilyIndex = &queueFamilyNdx;
716 bufferParameters.inputBarrierFlags = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
717 createVulkanBuffer(deviceInterface, testContext.device, testContext.allocator, bufferParameters, buffer, MemoryRequirement::HostVisible);
718 testContext.vertexBufferAllocation = buffer.allocation;
719 testContext.vertexBuffer = buffer.buffer;
720
721 bufferParameters.memory = DE_NULL;
722 bufferParameters.size = testContext.renderSize;
723 bufferParameters.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
724 bufferParameters.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
725 bufferParameters.queueFamilyCount = 1;
726 bufferParameters.queueFamilyIndex = &queueFamilyNdx;
727 bufferParameters.inputBarrierFlags = 0;
728 createVulkanBuffer(deviceInterface, testContext.device, testContext.allocator, bufferParameters, buffer, MemoryRequirement::HostVisible);
729 testContext.renderReadBuffer = buffer.allocation;
730 testContext.renderBuffer = buffer.buffer;
731
732 extent.width = testContext.renderDimension.x();
733 extent.height = testContext.renderDimension.y();
734 extent.depth = 1;
735
736 imageParameters.imageType = VK_IMAGE_TYPE_2D;
737 imageParameters.format = VK_FORMAT_R8G8B8A8_UNORM;
738 imageParameters.extent3D = extent;
739 imageParameters.mipLevels = 1;
740 imageParameters.samples = VK_SAMPLE_COUNT_1_BIT;
741 imageParameters.tiling = VK_IMAGE_TILING_OPTIMAL;
742 imageParameters.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
743 imageParameters.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
744 imageParameters.queueFamilyCount = 1;
745 imageParameters.queueFamilyNdxList = &queueFamilyNdx;
746 imageParameters.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
747 imageParameters.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
748 imageParameters.barrierInputMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
749 createVulkanImage(deviceInterface, testContext.device, testContext.allocator, imageParameters, image, MemoryRequirement::Any);
750 testContext.imageAllocation = image.allocation;
751 testContext.image = image.image;
752
753 for (size_t ndx = 0; ndx < image.imageMemoryBarrier.size(); ++ndx)
754 imageBarriers.push_back(image.imageMemoryBarrier[ndx]);
755
756 renderPassParameters.colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
757 renderPassParameters.colorSamples = VK_SAMPLE_COUNT_1_BIT;
758 createColorOnlyRenderPass(deviceInterface, testContext.device, renderPassParameters, testContext.renderPass);
759
760 vertexDesc.location = 0;
761 vertexDesc.format = VK_FORMAT_R32G32B32A32_SFLOAT;
762 vertexDesc.stride = sizeof(tcu::Vec4);
763 vertexDesc.offset = 0;
764 vertexDescList.push_back(vertexDesc);
765
766 createVertexInfo(vertexDescList, bindingList, attrList, vertexInputState);
767
768 deMemset(&inputAssemblyState, 0xcd, sizeof(inputAssemblyState));
769 inputAssemblyState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
770 inputAssemblyState.pNext = DE_NULL;
771 inputAssemblyState.flags = 0u;
772 inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
773 inputAssemblyState.primitiveRestartEnable = false;
774
775 viewport.x = 0;
776 viewport.y = 0;
777 viewport.width = (float)testContext.renderDimension.x();
778 viewport.height = (float)testContext.renderDimension.y();
779 viewport.minDepth = 0;
780 viewport.maxDepth = 1;
781
782 scissor.offset.x = 0;
783 scissor.offset.y = 0;
784 scissor.extent.width = testContext.renderDimension.x();
785 scissor.extent.height = testContext.renderDimension.y();
786
787 deMemset(&viewportInfo, 0xcd, sizeof(viewportInfo));
788 viewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
789 viewportInfo.pNext = DE_NULL;
790 viewportInfo.flags = 0;
791 viewportInfo.viewportCount = 1;
792 viewportInfo.pViewports = &viewport;
793 viewportInfo.scissorCount = 1;
794 viewportInfo.pScissors = &scissor;
795
796 deMemset(&rasterState, 0xcd, sizeof(rasterState));
797 rasterState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
798 rasterState.pNext = DE_NULL;
799 rasterState.flags = 0;
800 rasterState.depthClampEnable = VK_FALSE;
801 rasterState.rasterizerDiscardEnable = VK_FALSE;
802 rasterState.polygonMode = VK_POLYGON_MODE_FILL;
803 rasterState.cullMode = VK_CULL_MODE_NONE;
804 rasterState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
805 rasterState.depthBiasEnable = VK_FALSE;
806 rasterState.lineWidth = 1;
807
808 deMemset(&multisampleState, 0xcd, sizeof(multisampleState));
809 multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
810 multisampleState.pNext = DE_NULL;
811 multisampleState.flags = 0;
812 multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
813 multisampleState.sampleShadingEnable = VK_FALSE;
814 multisampleState.pSampleMask = DE_NULL;
815 multisampleState.alphaToCoverageEnable = VK_FALSE;
816 multisampleState.alphaToOneEnable = VK_FALSE;
817
818 deMemset(&depthStencilState, 0xcd, sizeof(depthStencilState));
819 depthStencilState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
820 depthStencilState.pNext = DE_NULL;
821 depthStencilState.flags = 0;
822 depthStencilState.depthTestEnable = VK_FALSE;
823 depthStencilState.depthWriteEnable = VK_FALSE;
824 depthStencilState.depthCompareOp = VK_COMPARE_OP_ALWAYS;
825 depthStencilState.depthBoundsTestEnable = VK_FALSE;
826 depthStencilState.stencilTestEnable = VK_FALSE;
827 depthStencilState.front.failOp = VK_STENCIL_OP_KEEP;
828 depthStencilState.front.passOp = VK_STENCIL_OP_KEEP;
829 depthStencilState.front.depthFailOp = VK_STENCIL_OP_KEEP;
830 depthStencilState.front.compareOp = VK_COMPARE_OP_ALWAYS;
831 depthStencilState.front.compareMask = 0u;
832 depthStencilState.front.writeMask = 0u;
833 depthStencilState.front.reference = 0u;
834 depthStencilState.back = depthStencilState.front;
835
836 deMemset(&blendAttachment, 0xcd, sizeof(blendAttachment));
837 blendAttachment.blendEnable = VK_FALSE;
838 blendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ZERO;
839 blendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
840 blendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
841 blendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
842 blendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
843 blendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
844 blendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
845
846 deMemset(&blendState, 0xcd, sizeof(blendState));
847 blendState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
848 blendState.pNext = DE_NULL;
849 blendState.flags = 0;
850 blendState.logicOpEnable = VK_FALSE;
851 blendState.logicOp = VK_LOGIC_OP_COPY;
852 blendState.attachmentCount = 1;
853 blendState.pAttachments = &blendAttachment;
854
855 deMemset(&pipelineLayoutState, 0xcd, sizeof(pipelineLayoutState));
856 pipelineLayoutState.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
857 pipelineLayoutState.pNext = DE_NULL;
858 pipelineLayoutState.flags = 0;
859 pipelineLayoutState.setLayoutCount = 0;
860 pipelineLayoutState.pSetLayouts = DE_NULL;
861 pipelineLayoutState.pushConstantRangeCount = 0;
862 pipelineLayoutState.pPushConstantRanges = DE_NULL;
863 layout = createPipelineLayout(deviceInterface, testContext.device, &pipelineLayoutState, DE_NULL);
864
865 deMemset(&pipelineState, 0xcd, sizeof(pipelineState));
866 pipelineState.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
867 pipelineState.pNext = DE_NULL;
868 pipelineState.flags = 0;
869 pipelineState.stageCount = DE_LENGTH_OF_ARRAY(shaderStageParams);
870 pipelineState.pStages = &shaderStageParams[0];
871 pipelineState.pVertexInputState = &vertexInputState;
872 pipelineState.pInputAssemblyState = &inputAssemblyState;
873 pipelineState.pTessellationState = DE_NULL;
874 pipelineState.pViewportState = &viewportInfo;
875 pipelineState.pRasterizationState = &rasterState;
876 pipelineState.pMultisampleState = &multisampleState;
877 pipelineState.pDepthStencilState = &depthStencilState;
878 pipelineState.pColorBlendState = &blendState;
879 pipelineState.pDynamicState = (const VkPipelineDynamicStateCreateInfo*)DE_NULL;
880 pipelineState.layout = layout.get();
881 pipelineState.renderPass = testContext.renderPass.get();
882 pipelineState.subpass = 0;
883 pipelineState.basePipelineHandle = DE_NULL;
884 pipelineState.basePipelineIndex = 0;
885
886 deMemset(&cacheState, 0xcd, sizeof(cacheState));
887 cacheState.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
888 cacheState.pNext = DE_NULL;
889 cacheState.flags = 0;
890 cacheState.initialDataSize = 0;
891 cacheState.pInitialData = DE_NULL;
892
893 testContext.pipelineCache = createPipelineCache(deviceInterface, testContext.device, &cacheState);
894 testContext.pipeline = createGraphicsPipeline(deviceInterface, testContext.device, testContext.pipelineCache.get(), &pipelineState);
895
896 deMemset(&fbState, 0xcd, sizeof(fbState));
897 fbState.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
898 fbState.pNext = DE_NULL;
899 fbState.flags = 0;
900 fbState.renderPass = testContext.renderPass.get();
901 fbState.attachmentCount = 1;
902 fbState.pAttachments = &image.imageView.get();
903 fbState.width = (deUint32)testContext.renderDimension.x();
904 fbState.height = (deUint32)testContext.renderDimension.y();
905 fbState.layers = 1;
906
907 testContext.framebuffer = createFramebuffer(deviceInterface, testContext.device, &fbState);
908 testContext.imageView = image.imageView;
909
910 deMemset(&inheritanceInfo, 0xcd, sizeof(inheritanceInfo));
911 inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
912 inheritanceInfo.pNext = DE_NULL;
913 inheritanceInfo.renderPass = testContext.renderPass.get();
914 inheritanceInfo.subpass = 0;
915 inheritanceInfo.framebuffer = *testContext.framebuffer;
916 inheritanceInfo.occlusionQueryEnable = VK_FALSE;
917 inheritanceInfo.queryFlags = 0u;
918 inheritanceInfo.pipelineStatistics = 0u;
919
920 deMemset(&commandBufRecordState, 0xcd, sizeof(commandBufRecordState));
921 commandBufRecordState.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
922 commandBufRecordState.pNext = DE_NULL;
923 commandBufRecordState.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
924 commandBufRecordState.pInheritanceInfo = &inheritanceInfo;
925 VK_CHECK(deviceInterface.beginCommandBuffer(testContext.cmdBuffer.get(), &commandBufRecordState));
926
927 deviceInterface.cmdPipelineBarrier( testContext.cmdBuffer.get(),
928 VK_PIPELINE_STAGE_HOST_BIT,
929 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
930 false,
931 (deUint32)memoryBarriers.size(), (memoryBarriers.empty() ? DE_NULL : &memoryBarriers[0]),
932 (deUint32)bufferBarriers.size(), (bufferBarriers.empty() ? DE_NULL : &bufferBarriers[0]),
933 (deUint32)imageBarriers.size(), (imageBarriers.empty() ? DE_NULL : &imageBarriers[0]));
934
935 memoryBarriers.resize(0);
936 bufferBarriers.resize(0);
937 imageBarriers.resize(0);
938
939 renderInfo.width = testContext.renderDimension.x();
940 renderInfo.height = testContext.renderDimension.y();
941 renderInfo.vertexBufferSize = testContext.numVertices;
942 renderInfo.vertexBuffer = testContext.vertexBuffer.get();
943 renderInfo.image = testContext.image.get();
944 renderInfo.commandBuffer = testContext.cmdBuffer.get();
945 renderInfo.renderPass = testContext.renderPass.get();
946 renderInfo.framebuffer = *testContext.framebuffer;
947 renderInfo.pipeline = *testContext.pipeline;
948 renderInfo.mipLevels = 1;
949 renderInfo.queueFamilyNdxList = &queueFamilyNdx;
950 renderInfo.queueFamilyNdxCount = 1;
951 renderInfo.waitEvent = testContext.waitEvent;
952 renderInfo.event = testContext.event;
953 renderInfo.barriers = &imageBarriers;
954 recordRenderPass(deviceInterface, renderInfo);
955
956 deviceInterface.cmdPipelineBarrier( renderInfo.commandBuffer,
957 VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
958 VK_PIPELINE_STAGE_TRANSFER_BIT,
959 false,
960 (deUint32)memoryBarriers.size(), (memoryBarriers.empty() ? DE_NULL : &memoryBarriers[0]),
961 (deUint32)bufferBarriers.size(), (bufferBarriers.empty() ? DE_NULL : &bufferBarriers[0]),
962 (deUint32)imageBarriers.size(), (imageBarriers.empty() ? DE_NULL : &imageBarriers[0]));
963
964 memoryBarriers.resize(0);
965 bufferBarriers.resize(0);
966 imageBarriers.resize(0);
967
968 transferInfo.commandBuffer = renderInfo.commandBuffer;
969 transferInfo.width = testContext.renderDimension.x();
970 transferInfo.height = testContext.renderDimension.y();
971 transferInfo.image = renderInfo.image;
972 transferInfo.buffer = testContext.renderBuffer.get();
973 transferInfo.size = testContext.renderSize;
974 transferInfo.mipLevel = 0;
975 transferInfo.imageOffset.x = 0;
976 transferInfo.imageOffset.y = 0;
977 transferInfo.imageOffset.z = 0;
978 transferInfo.barriers = &bufferBarriers;
979 copyToCPU(deviceInterface, &transferInfo);
980
981 deviceInterface.cmdPipelineBarrier( transferInfo.commandBuffer,
982 VK_PIPELINE_STAGE_TRANSFER_BIT,
983 VK_PIPELINE_STAGE_HOST_BIT,
984 false,
985 (deUint32)memoryBarriers.size(), (memoryBarriers.empty() ? DE_NULL : &memoryBarriers[0]),
986 (deUint32)bufferBarriers.size(), (bufferBarriers.empty() ? DE_NULL : &bufferBarriers[0]),
987 (deUint32)imageBarriers.size(), (imageBarriers.empty() ? DE_NULL : &imageBarriers[0]));
988
989 memoryBarriers.resize(0);
990 bufferBarriers.resize(0);
991 imageBarriers.resize(0);
992
993 endCommandBuffer(deviceInterface, transferInfo.commandBuffer);
994 }
995
testFences(Context & context)996 tcu::TestStatus testFences (Context& context)
997 {
998 TestLog& log = context.getTestContext().getLog();
999 const DeviceInterface& deviceInterface = context.getDeviceInterface();
1000 const VkQueue queue = context.getUniversalQueue();
1001 const deUint32 queueFamilyIdx = context.getUniversalQueueFamilyIndex();
1002 VkDevice device = context.getDevice();
1003 VkResult waitStatus;
1004 VkResult fenceStatus;
1005 TestContext testContext (deviceInterface, device, queueFamilyIdx, context.getBinaryCollection(), context.getDefaultAllocator());
1006 void* resultImage;
1007
1008 const tcu::Vec4 vertices[] =
1009 {
1010 tcu::Vec4( 0.5f, 0.5f, 0.0f, 1.0f),
1011 tcu::Vec4(-0.5f, 0.5f, 0.0f, 1.0f),
1012 tcu::Vec4( 0.0f, -0.5f, 0.0f, 1.0f)
1013 };
1014
1015 testContext.vertices = vertices;
1016 testContext.numVertices = DE_LENGTH_OF_ARRAY(vertices);
1017 testContext.renderDimension = tcu::IVec2(256, 256);
1018 testContext.renderSize = sizeof(deUint32) * testContext.renderDimension.x() * testContext.renderDimension.y();
1019
1020 createCommandBuffer(deviceInterface, device, queueFamilyIdx, &testContext.cmdBuffer, &testContext.commandPool);
1021 generateWork(testContext);
1022
1023 // Default status is unsignaled
1024 fenceStatus = deviceInterface.getFenceStatus(device, testContext.fences[0]);
1025 if (fenceStatus != VK_NOT_READY)
1026 {
1027 log << TestLog::Message << "testSynchronizationPrimitives fence 0 should be reset but status is " << getResultName(fenceStatus) << TestLog::EndMessage;
1028 return tcu::TestStatus::fail("Fence in incorrect state");
1029 }
1030 fenceStatus = deviceInterface.getFenceStatus(device, testContext.fences[1]);
1031 if (fenceStatus != VK_NOT_READY)
1032 {
1033 log << TestLog::Message << "testSynchronizationPrimitives fence 1 should be reset but status is " << getResultName(fenceStatus) << TestLog::EndMessage;
1034 return tcu::TestStatus::fail("Fence in incorrect state");
1035 }
1036
1037 VkSubmitInfo submitInfo { VK_STRUCTURE_TYPE_SUBMIT_INFO, DE_NULL, 0u, DE_NULL, DE_NULL, 1u, &testContext.cmdBuffer.get(), 0, DE_NULL };
1038 VK_CHECK(deviceInterface.queueSubmit(queue, 1, &submitInfo, testContext.fences[0]));
1039
1040 // Wait with timeout = 0
1041 waitStatus = deviceInterface.waitForFences(device, 1, &testContext.fences[0], true, 0u);
1042 if (waitStatus != VK_SUCCESS && waitStatus != VK_TIMEOUT)
1043 {
1044 // Will most likely end with VK_TIMEOUT
1045 log << TestLog::Message << "testSynchPrimitives failed to wait for a single fence" << TestLog::EndMessage;
1046 return tcu::TestStatus::fail("Failed to wait for a single fence");
1047 }
1048
1049 // Wait with a reasonable timeout
1050 waitStatus = deviceInterface.waitForFences(device, 1, &testContext.fences[0], true, DEFAULT_TIMEOUT);
1051 if (waitStatus != VK_SUCCESS && waitStatus != VK_TIMEOUT)
1052 {
1053 // \note Wait can end with a timeout if DEFAULT_TIMEOUT is not sufficient
1054 log << TestLog::Message << "testSynchPrimitives failed to wait for a single fence" << TestLog::EndMessage;
1055 return tcu::TestStatus::fail("Failed to wait for a single fence");
1056 }
1057
1058 // Wait for work on fences[0] to actually complete
1059 waitStatus = deviceInterface.waitForFences(device, 1, &testContext.fences[0], true, std::numeric_limits<deUint64>::max());
1060 if (waitStatus != VK_SUCCESS)
1061 {
1062 log << TestLog::Message << "testSynchPrimitives failed to wait for a fence" << TestLog::EndMessage;
1063 return tcu::TestStatus::fail("failed to wait for a fence");
1064 }
1065
1066 // Wait until timeout on a fence that has not been submitted
1067 waitStatus = deviceInterface.waitForFences(device, 1, &testContext.fences[1], true, 1);
1068 if (waitStatus != VK_TIMEOUT)
1069 {
1070 log << TestLog::Message << "testSyncPrimitives failed to timeout on wait for single fence" << TestLog::EndMessage;
1071 return tcu::TestStatus::fail("failed to timeout on wait for single fence");
1072 }
1073
1074 // Check that the fence is signaled after the wait
1075 fenceStatus = deviceInterface.getFenceStatus(device, testContext.fences[0]);
1076 if (fenceStatus != VK_SUCCESS)
1077 {
1078 log << TestLog::Message << "testSynchronizationPrimitives fence should be signaled but status is " << getResultName(fenceStatus) << TestLog::EndMessage;
1079 return tcu::TestStatus::fail("Fence in incorrect state");
1080 }
1081
1082 invalidateAlloc(deviceInterface, device, *testContext.renderReadBuffer);
1083 resultImage = testContext.renderReadBuffer->getHostPtr();
1084
1085 log << TestLog::Image( "result",
1086 "result",
1087 tcu::ConstPixelBufferAccess(tcu::TextureFormat(
1088 tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
1089 testContext.renderDimension.x(),
1090 testContext.renderDimension.y(),
1091 1,
1092 resultImage));
1093
1094 return TestStatus::pass("synchronization-fences passed");
1095 }
1096
testSemaphores(Context & context,SemaphoreTestConfig config)1097 tcu::TestStatus testSemaphores (Context& context, SemaphoreTestConfig config)
1098 {
1099 if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR && !context.getTimelineSemaphoreFeatures().timelineSemaphore)
1100 TCU_THROW(NotSupportedError, "Timeline semaphore not supported");
1101
1102 TestLog& log = context.getTestContext().getLog();
1103 const PlatformInterface& platformInterface = context.getPlatformInterface();
1104 const InstanceInterface& instanceInterface = context.getInstanceInterface();
1105 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1106 deUint32 queueFamilyIdx;
1107 bool isTimelineSemaphore (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE);
1108 vk::Move<VkDevice> device (createTestDevice(context, config, &queueFamilyIdx));
1109 const DeviceDriver deviceInterface (platformInterface, context.getInstance(), *device);
1110 SimpleAllocator allocator (deviceInterface,
1111 *device,
1112 getPhysicalDeviceMemoryProperties(instanceInterface, physicalDevice));
1113 const VkQueue queue[2] =
1114 {
1115 getDeviceQueue(deviceInterface, *device, queueFamilyIdx, 0),
1116 getDeviceQueue(deviceInterface, *device, queueFamilyIdx, 1)
1117 };
1118 VkResult testStatus;
1119 TestContext testContext1 (deviceInterface, device.get(), queueFamilyIdx, context.getBinaryCollection(), allocator);
1120 TestContext testContext2 (deviceInterface, device.get(), queueFamilyIdx, context.getBinaryCollection(), allocator);
1121 Unique<VkSemaphore> semaphore (createSemaphoreType(deviceInterface, *device, config.semaphoreType));
1122 VkSemaphoreSubmitInfoKHR waitSemaphoreSubmitInfo = makeCommonSemaphoreSubmitInfo(*semaphore, 1u, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR);
1123 VkSemaphoreSubmitInfoKHR signalSemaphoreSubmitInfo = makeCommonSemaphoreSubmitInfo(*semaphore, 1u, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR);
1124
1125 const tcu::Vec4 vertices1[] =
1126 {
1127 tcu::Vec4( 0.5f, 0.5f, 0.0f, 1.0f),
1128 tcu::Vec4(-0.5f, 0.5f, 0.0f, 1.0f),
1129 tcu::Vec4( 0.0f, -0.5f, 0.0f, 1.0f)
1130 };
1131
1132 const tcu::Vec4 vertices2[] =
1133 {
1134 tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f),
1135 tcu::Vec4(+0.5f, -0.5f, 0.0f, 1.0f),
1136 tcu::Vec4( 0.0f, +0.5f, 0.0f, 1.0f)
1137 };
1138
1139 testContext1.vertices = vertices1;
1140 testContext1.numVertices = DE_LENGTH_OF_ARRAY(vertices1);
1141 testContext1.renderDimension = tcu::IVec2(256, 256);
1142 testContext1.renderSize = sizeof(deUint32) * testContext1.renderDimension.x() * testContext1.renderDimension.y();
1143
1144 testContext2.vertices = vertices2;
1145 testContext2.numVertices = DE_LENGTH_OF_ARRAY(vertices2);
1146 testContext2.renderDimension = tcu::IVec2(256, 256);
1147 testContext2.renderSize = sizeof(deUint32) * testContext2.renderDimension.x() * testContext2.renderDimension.y();
1148
1149 createCommandBuffer(deviceInterface, device.get(), queueFamilyIdx, &testContext1.cmdBuffer, &testContext1.commandPool);
1150 generateWork(testContext1);
1151
1152 createCommandBuffer(deviceInterface, device.get(), queueFamilyIdx, &testContext2.cmdBuffer, &testContext2.commandPool);
1153 generateWork(testContext2);
1154
1155 {
1156 VkCommandBufferSubmitInfoKHR commandBufferSubmitInfo = makeCommonCommandBufferSubmitInfo(testContext1.cmdBuffer.get());
1157 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.synchronizationType, deviceInterface, isTimelineSemaphore);
1158 synchronizationWrapper->addSubmitInfo(
1159 0u, // deUint32 waitSemaphoreInfoCount
1160 DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
1161 1u, // deUint32 commandBufferInfoCount
1162 &commandBufferSubmitInfo, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
1163 1u, // deUint32 signalSemaphoreInfoCount
1164 &signalSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
1165 DE_FALSE,
1166 isTimelineSemaphore
1167 );
1168
1169 VK_CHECK(synchronizationWrapper->queueSubmit(queue[0], testContext1.fences[0]));
1170 }
1171
1172 testStatus = deviceInterface.waitForFences(device.get(), 1, &testContext1.fences[0], true, std::numeric_limits<deUint64>::max());
1173 if (testStatus != VK_SUCCESS)
1174 {
1175 log << TestLog::Message << "testSynchPrimitives failed to wait for a set fence" << TestLog::EndMessage;
1176 return tcu::TestStatus::fail("failed to wait for a set fence");
1177 }
1178
1179 invalidateAlloc(deviceInterface, device.get(), *testContext1.renderReadBuffer);
1180 void* resultImage = testContext1.renderReadBuffer->getHostPtr();
1181
1182 log << TestLog::Image( "result",
1183 "result",
1184 tcu::ConstPixelBufferAccess(tcu::TextureFormat(
1185 tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
1186 testContext1.renderDimension.x(),
1187 testContext1.renderDimension.y(),
1188 1,
1189 resultImage));
1190
1191 // The difference between the second submit info is that it will use a unique cmd buffer.
1192 // First submit signals a semaphore but not wait on a semaphore, the other waits on the
1193 // semaphore but not signal it.
1194 {
1195 VkCommandBufferSubmitInfoKHR commandBufferSubmitInfo = makeCommonCommandBufferSubmitInfo(testContext2.cmdBuffer.get());
1196 SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.synchronizationType, deviceInterface, isTimelineSemaphore);
1197 synchronizationWrapper->addSubmitInfo(
1198 1u, // deUint32 waitSemaphoreInfoCount
1199 &waitSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
1200 1u, // deUint32 commandBufferInfoCount
1201 &commandBufferSubmitInfo, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
1202 0u, // deUint32 signalSemaphoreInfoCount
1203 DE_NULL, // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
1204 isTimelineSemaphore
1205 );
1206
1207 VK_CHECK(synchronizationWrapper->queueSubmit(queue[1], testContext2.fences[0]));
1208 }
1209
1210 testStatus = deviceInterface.waitForFences(device.get(), 1, &testContext2.fences[0], true, std::numeric_limits<deUint64>::max());
1211 if (testStatus != VK_SUCCESS)
1212 {
1213 log << TestLog::Message << "testSynchPrimitives failed to wait for a set fence" << TestLog::EndMessage;
1214 return tcu::TestStatus::fail("failed to wait for a set fence");
1215 }
1216
1217 invalidateAlloc(deviceInterface, device.get(), *testContext2.renderReadBuffer);
1218 resultImage = testContext2.renderReadBuffer->getHostPtr();
1219
1220 log << TestLog::Image( "result",
1221 "result",
1222 tcu::ConstPixelBufferAccess(tcu::TextureFormat(
1223 tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
1224 testContext2.renderDimension.x(),
1225 testContext2.renderDimension.y(),
1226 1,
1227 resultImage));
1228
1229 return tcu::TestStatus::pass("synchronization-semaphores passed");
1230 }
1231
checkSupport(Context & context,SemaphoreTestConfig config)1232 void checkSupport(Context& context, SemaphoreTestConfig config)
1233 {
1234 if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE)
1235 context.requireDeviceFunctionality("VK_KHR_timeline_semaphore");
1236 if (config.synchronizationType == SynchronizationType::SYNCHRONIZATION2)
1237 context.requireDeviceFunctionality("VK_KHR_synchronization2");
1238 }
1239
1240 } // anonymous
1241
createSmokeTests(tcu::TestContext & textCtx)1242 tcu::TestCaseGroup* createSmokeTests (tcu::TestContext& textCtx)
1243 {
1244 SynchronizationType type (SynchronizationType::LEGACY);
1245 de::MovePtr<tcu::TestCaseGroup> smokeTests (new tcu::TestCaseGroup(textCtx, "smoke", "Synchronization smoke tests"));
1246
1247 addFunctionCaseWithPrograms(smokeTests.get(), "fences", "", buildShaders, testFences);
1248 addFunctionCaseWithPrograms(smokeTests.get(), "binary_semaphores", "", checkSupport, initShaders, testSemaphores, SemaphoreTestConfig { type, VK_SEMAPHORE_TYPE_BINARY });
1249 addFunctionCaseWithPrograms(smokeTests.get(), "timeline_semaphores", "", checkSupport, initShaders, testSemaphores, SemaphoreTestConfig { type, VK_SEMAPHORE_TYPE_TIMELINE });
1250
1251 return smokeTests.release();
1252 }
1253
createSynchronization2SmokeTests(tcu::TestContext & textCtx)1254 tcu::TestCaseGroup* createSynchronization2SmokeTests(tcu::TestContext& textCtx)
1255 {
1256 SynchronizationType type (SynchronizationType::SYNCHRONIZATION2);
1257 de::MovePtr<tcu::TestCaseGroup> smokeTests (new tcu::TestCaseGroup(textCtx, "smoke", "Synchronization smoke tests"));
1258
1259 addFunctionCaseWithPrograms(smokeTests.get(), "binary_semaphores", "", checkSupport, initShaders, testSemaphores, SemaphoreTestConfig { type, VK_SEMAPHORE_TYPE_BINARY });
1260 addFunctionCaseWithPrograms(smokeTests.get(), "timeline_semaphores", "", checkSupport, initShaders, testSemaphores, SemaphoreTestConfig { type, VK_SEMAPHORE_TYPE_TIMELINE });
1261
1262 return smokeTests.release();
1263 }
1264
1265 } // synchronization
1266 } // vkt
1267