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