1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 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 Pipeline barrier tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktMemoryPipelineBarrierTests.hpp"
25 
26 #include "vktTestCaseUtil.hpp"
27 
28 #include "vkDefs.hpp"
29 #include "vkPlatform.hpp"
30 #include "vkRefUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkPrograms.hpp"
35 
36 #include "tcuMaybe.hpp"
37 #include "tcuTextureUtil.hpp"
38 #include "tcuTestLog.hpp"
39 #include "tcuResultCollector.hpp"
40 #include "tcuTexture.hpp"
41 #include "tcuImageCompare.hpp"
42 
43 #include "deUniquePtr.hpp"
44 #include "deStringUtil.hpp"
45 #include "deRandom.hpp"
46 
47 #include "deMemory.h"
48 #include "deMath.h"
49 
50 #include <map>
51 #include <set>
52 #include <sstream>
53 #include <string>
54 #include <vector>
55 
56 // \todo [2016-03-09 mika] Check bufferImageGranularity
57 
58 using tcu::TestLog;
59 using tcu::Maybe;
60 
61 using std::string;
62 using std::vector;
63 using std::map;
64 using std::set;
65 using std::pair;
66 
67 using tcu::IVec2;
68 using tcu::UVec4;
69 using tcu::Vec4;
70 using tcu::ConstPixelBufferAccess;
71 using tcu::PixelBufferAccess;
72 using tcu::TextureFormat;
73 using tcu::TextureLevel;
74 
75 namespace vkt
76 {
77 namespace memory
78 {
79 namespace
80 {
81 enum
82 {
83 	ALL_PIPELINE_STAGES = vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
84 						| vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
85 						| vk::VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
86 						| vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
87 						| vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
88 						| vk::VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
89 						| vk::VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
90 						| vk::VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
91 						| vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
92 						| vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
93 						| vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
94 						| vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
95 						| vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
96 						| vk::VK_PIPELINE_STAGE_TRANSFER_BIT
97 						| vk::VK_PIPELINE_STAGE_HOST_BIT
98 };
99 
100 enum
101 {
102 	ALL_ACCESSES = vk::VK_ACCESS_INDIRECT_COMMAND_READ_BIT
103 				 | vk::VK_ACCESS_INDEX_READ_BIT
104 				 | vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT
105 				 | vk::VK_ACCESS_UNIFORM_READ_BIT
106 				 | vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
107 				 | vk::VK_ACCESS_SHADER_READ_BIT
108 				 | vk::VK_ACCESS_SHADER_WRITE_BIT
109 				 | vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
110 				 | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
111 				 | vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
112 				 | vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
113 				 | vk::VK_ACCESS_TRANSFER_READ_BIT
114 				 | vk::VK_ACCESS_TRANSFER_WRITE_BIT
115 				 | vk::VK_ACCESS_HOST_READ_BIT
116 				 | vk::VK_ACCESS_HOST_WRITE_BIT
117 				 | vk::VK_ACCESS_MEMORY_READ_BIT
118 				 | vk::VK_ACCESS_MEMORY_WRITE_BIT
119 };
120 
121 enum Usage
122 {
123 	// Mapped host read and write
124 	USAGE_HOST_READ = (0x1u<<0),
125 	USAGE_HOST_WRITE = (0x1u<<1),
126 
127 	// Copy and other transfer operations
128 	USAGE_TRANSFER_SRC = (0x1u<<2),
129 	USAGE_TRANSFER_DST = (0x1u<<3),
130 
131 	// Buffer usage flags
132 	USAGE_INDEX_BUFFER = (0x1u<<4),
133 	USAGE_VERTEX_BUFFER = (0x1u<<5),
134 
135 	USAGE_UNIFORM_BUFFER = (0x1u<<6),
136 	USAGE_STORAGE_BUFFER = (0x1u<<7),
137 
138 	USAGE_UNIFORM_TEXEL_BUFFER = (0x1u<<8),
139 	USAGE_STORAGE_TEXEL_BUFFER = (0x1u<<9),
140 
141 	// \todo [2016-03-09 mika] This is probably almost impossible to do
142 	USAGE_INDIRECT_BUFFER = (0x1u<<10),
143 
144 	// Texture usage flags
145 	USAGE_TEXTURE_SAMPLED = (0x1u<<11),
146 	USAGE_TEXTURE_STORAGE = (0x1u<<12),
147 	USAGE_COLOR_ATTACHMENT = (0x1u<<13),
148 	USAGE_INPUT_ATTACHMENT = (0x1u<<14),
149 	USAGE_DEPTH_STENCIL_ATTACHMENT = (0x1u<<15),
150 };
151 
supportsDeviceBufferWrites(Usage usage)152 bool supportsDeviceBufferWrites (Usage usage)
153 {
154 	if (usage & USAGE_TRANSFER_DST)
155 		return true;
156 
157 	if (usage & USAGE_STORAGE_BUFFER)
158 		return true;
159 
160 	if (usage & USAGE_STORAGE_TEXEL_BUFFER)
161 		return true;
162 
163 	return false;
164 }
165 
supportsDeviceImageWrites(Usage usage)166 bool supportsDeviceImageWrites (Usage usage)
167 {
168 	if (usage & USAGE_TRANSFER_DST)
169 		return true;
170 
171 	if (usage & USAGE_TEXTURE_STORAGE)
172 		return true;
173 
174 	if (usage & USAGE_COLOR_ATTACHMENT)
175 		return true;
176 
177 	return false;
178 }
179 
180 // Sequential access enums
181 enum Access
182 {
183     ACCESS_INDIRECT_COMMAND_READ_BIT = 0,
184     ACCESS_INDEX_READ_BIT,
185     ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
186     ACCESS_UNIFORM_READ_BIT,
187     ACCESS_INPUT_ATTACHMENT_READ_BIT,
188     ACCESS_SHADER_READ_BIT,
189     ACCESS_SHADER_WRITE_BIT,
190     ACCESS_COLOR_ATTACHMENT_READ_BIT,
191     ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
192     ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
193     ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
194     ACCESS_TRANSFER_READ_BIT,
195     ACCESS_TRANSFER_WRITE_BIT,
196     ACCESS_HOST_READ_BIT,
197     ACCESS_HOST_WRITE_BIT,
198     ACCESS_MEMORY_READ_BIT,
199     ACCESS_MEMORY_WRITE_BIT,
200 
201     ACCESS_LAST
202 };
203 
204 // Sequential stage enums
205 enum PipelineStage
206 {
207 	PIPELINESTAGE_TOP_OF_PIPE_BIT = 0,
208 	PIPELINESTAGE_BOTTOM_OF_PIPE_BIT,
209 	PIPELINESTAGE_DRAW_INDIRECT_BIT,
210 	PIPELINESTAGE_VERTEX_INPUT_BIT,
211 	PIPELINESTAGE_VERTEX_SHADER_BIT,
212 	PIPELINESTAGE_TESSELLATION_CONTROL_SHADER_BIT,
213 	PIPELINESTAGE_TESSELLATION_EVALUATION_SHADER_BIT,
214 	PIPELINESTAGE_GEOMETRY_SHADER_BIT,
215 	PIPELINESTAGE_FRAGMENT_SHADER_BIT,
216 	PIPELINESTAGE_EARLY_FRAGMENT_TESTS_BIT,
217 	PIPELINESTAGE_LATE_FRAGMENT_TESTS_BIT,
218 	PIPELINESTAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
219 	PIPELINESTAGE_COMPUTE_SHADER_BIT,
220 	PIPELINESTAGE_TRANSFER_BIT,
221 	PIPELINESTAGE_HOST_BIT,
222 
223 	PIPELINESTAGE_LAST
224 };
225 
pipelineStageFlagToPipelineStage(vk::VkPipelineStageFlagBits flags)226 PipelineStage pipelineStageFlagToPipelineStage (vk::VkPipelineStageFlagBits flags)
227 {
228 	switch (flags)
229 	{
230 		case vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT:						return PIPELINESTAGE_TOP_OF_PIPE_BIT;
231 		case vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT:					return PIPELINESTAGE_BOTTOM_OF_PIPE_BIT;
232 		case vk::VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT:					return PIPELINESTAGE_DRAW_INDIRECT_BIT;
233 		case vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT:					return PIPELINESTAGE_VERTEX_INPUT_BIT;
234 		case vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT:					return PIPELINESTAGE_VERTEX_SHADER_BIT;
235 		case vk::VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT:		return PIPELINESTAGE_TESSELLATION_CONTROL_SHADER_BIT;
236 		case vk::VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT:	return PIPELINESTAGE_TESSELLATION_EVALUATION_SHADER_BIT;
237 		case vk::VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT:					return PIPELINESTAGE_GEOMETRY_SHADER_BIT;
238 		case vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT:					return PIPELINESTAGE_FRAGMENT_SHADER_BIT;
239 		case vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT:			return PIPELINESTAGE_EARLY_FRAGMENT_TESTS_BIT;
240 		case vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT:				return PIPELINESTAGE_LATE_FRAGMENT_TESTS_BIT;
241 		case vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT:			return PIPELINESTAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
242 		case vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT:					return PIPELINESTAGE_COMPUTE_SHADER_BIT;
243 		case vk::VK_PIPELINE_STAGE_TRANSFER_BIT:						return PIPELINESTAGE_TRANSFER_BIT;
244 		case vk::VK_PIPELINE_STAGE_HOST_BIT:							return PIPELINESTAGE_HOST_BIT;
245 
246 		default:
247 			DE_FATAL("Unknown pipeline stage flags");
248 			return PIPELINESTAGE_LAST;
249 	}
250 }
251 
operator |(Usage a,Usage b)252 Usage operator| (Usage a, Usage b)
253 {
254 	return (Usage)((deUint32)a | (deUint32)b);
255 }
256 
operator &(Usage a,Usage b)257 Usage operator& (Usage a, Usage b)
258 {
259 	return (Usage)((deUint32)a & (deUint32)b);
260 }
261 
usageToName(Usage usage)262 string usageToName (Usage usage)
263 {
264 	const struct
265 	{
266 		Usage				usage;
267 		const char* const	name;
268 	} usageNames[] =
269 	{
270 		{ USAGE_HOST_READ,					"host_read" },
271 		{ USAGE_HOST_WRITE,					"host_write" },
272 
273 		{ USAGE_TRANSFER_SRC,				"transfer_src" },
274 		{ USAGE_TRANSFER_DST,				"transfer_dst" },
275 
276 		{ USAGE_INDEX_BUFFER,				"index_buffer" },
277 		{ USAGE_VERTEX_BUFFER,				"vertex_buffer" },
278 		{ USAGE_UNIFORM_BUFFER,				"uniform_buffer" },
279 		{ USAGE_STORAGE_BUFFER,				"storage_buffer" },
280 		{ USAGE_UNIFORM_TEXEL_BUFFER,		"uniform_texel_buffer" },
281 		{ USAGE_STORAGE_TEXEL_BUFFER,		"storage_texel_buffer" },
282 		{ USAGE_INDIRECT_BUFFER,			"indirect_buffer" },
283 		{ USAGE_TEXTURE_SAMPLED,			"sampled_texture" },
284 		{ USAGE_TEXTURE_STORAGE,			"texture_storage" },
285 		{ USAGE_COLOR_ATTACHMENT,			"color_attachment" },
286 		{ USAGE_INPUT_ATTACHMENT,			"input_attachment" },
287 		{ USAGE_DEPTH_STENCIL_ATTACHMENT,	"depth_stencil_attachment" },
288 	};
289 
290 	std::ostringstream	stream;
291 	bool				first = true;
292 
293 	for (size_t usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usageNames); usageNdx++)
294 	{
295 		if (usage & usageNames[usageNdx].usage)
296 		{
297 			if (!first)
298 				stream << "_";
299 			else
300 				first = false;
301 
302 			stream << usageNames[usageNdx].name;
303 		}
304 	}
305 
306 	return stream.str();
307 }
308 
usageToBufferUsageFlags(Usage usage)309 vk::VkBufferUsageFlags usageToBufferUsageFlags (Usage usage)
310 {
311 	vk::VkBufferUsageFlags flags = 0;
312 
313 	if (usage & USAGE_TRANSFER_SRC)
314 		flags |= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
315 
316 	if (usage & USAGE_TRANSFER_DST)
317 		flags |= vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
318 
319 	if (usage & USAGE_INDEX_BUFFER)
320 		flags |= vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
321 
322 	if (usage & USAGE_VERTEX_BUFFER)
323 		flags |= vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
324 
325 	if (usage & USAGE_INDIRECT_BUFFER)
326 		flags |= vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
327 
328 	if (usage & USAGE_UNIFORM_BUFFER)
329 		flags |= vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
330 
331 	if (usage & USAGE_STORAGE_BUFFER)
332 		flags |= vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
333 
334 	if (usage & USAGE_UNIFORM_TEXEL_BUFFER)
335 		flags |= vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
336 
337 	if (usage & USAGE_STORAGE_TEXEL_BUFFER)
338 		flags |= vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
339 
340 	return flags;
341 }
342 
usageToImageUsageFlags(Usage usage)343 vk::VkImageUsageFlags usageToImageUsageFlags (Usage usage)
344 {
345 	vk::VkImageUsageFlags flags = 0;
346 
347 	if (usage & USAGE_TRANSFER_SRC)
348 		flags |= vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
349 
350 	if (usage & USAGE_TRANSFER_DST)
351 		flags |= vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT;
352 
353 	if (usage & USAGE_TEXTURE_SAMPLED)
354 		flags |= vk::VK_IMAGE_USAGE_SAMPLED_BIT;
355 
356 	if (usage & USAGE_TEXTURE_STORAGE)
357 		flags |= vk::VK_IMAGE_USAGE_STORAGE_BIT;
358 
359 	if (usage & USAGE_COLOR_ATTACHMENT)
360 		flags |= vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
361 
362 	if (usage & USAGE_INPUT_ATTACHMENT)
363 		flags |= vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
364 
365 	if (usage & USAGE_DEPTH_STENCIL_ATTACHMENT)
366 		flags |= vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
367 
368 	return flags;
369 }
370 
usageToStageFlags(Usage usage)371 vk::VkPipelineStageFlags usageToStageFlags (Usage usage)
372 {
373 	vk::VkPipelineStageFlags flags = 0;
374 
375 	if (usage & (USAGE_HOST_READ|USAGE_HOST_WRITE))
376 		flags |= vk::VK_PIPELINE_STAGE_HOST_BIT;
377 
378 	if (usage & (USAGE_TRANSFER_SRC|USAGE_TRANSFER_DST))
379 		flags |= vk::VK_PIPELINE_STAGE_TRANSFER_BIT;
380 
381 	if (usage & (USAGE_VERTEX_BUFFER|USAGE_INDEX_BUFFER))
382 		flags |= vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
383 
384 	if (usage & USAGE_INDIRECT_BUFFER)
385 		flags |= vk::VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
386 
387 	if (usage &
388 			(USAGE_UNIFORM_BUFFER
389 			| USAGE_STORAGE_BUFFER
390 			| USAGE_UNIFORM_TEXEL_BUFFER
391 			| USAGE_STORAGE_TEXEL_BUFFER
392 			| USAGE_TEXTURE_SAMPLED
393 			| USAGE_TEXTURE_STORAGE))
394 	{
395 		flags |= (vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
396 				| vk::VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
397 				| vk::VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
398 				| vk::VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
399 				| vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
400 				| vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
401 	}
402 
403 	if (usage & USAGE_INPUT_ATTACHMENT)
404 		flags |= vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
405 
406 	if (usage & USAGE_COLOR_ATTACHMENT)
407 		flags |= vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
408 
409 	if (usage & USAGE_DEPTH_STENCIL_ATTACHMENT)
410 	{
411 		flags |= vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
412 				| vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
413 	}
414 
415 	return flags;
416 }
417 
usageToAccessFlags(Usage usage)418 vk::VkAccessFlags usageToAccessFlags (Usage usage)
419 {
420 	vk::VkAccessFlags flags = 0;
421 
422 	if (usage & USAGE_HOST_READ)
423 		flags |= vk::VK_ACCESS_HOST_READ_BIT;
424 
425 	if (usage & USAGE_HOST_WRITE)
426 		flags |= vk::VK_ACCESS_HOST_WRITE_BIT;
427 
428 	if (usage & USAGE_TRANSFER_SRC)
429 		flags |= vk::VK_ACCESS_TRANSFER_READ_BIT;
430 
431 	if (usage & USAGE_TRANSFER_DST)
432 		flags |= vk::VK_ACCESS_TRANSFER_WRITE_BIT;
433 
434 	if (usage & USAGE_INDEX_BUFFER)
435 		flags |= vk::VK_ACCESS_INDEX_READ_BIT;
436 
437 	if (usage & USAGE_VERTEX_BUFFER)
438 		flags |= vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
439 
440 	if (usage & (USAGE_UNIFORM_BUFFER | USAGE_UNIFORM_TEXEL_BUFFER))
441 		flags |= vk::VK_ACCESS_UNIFORM_READ_BIT;
442 
443 	if (usage & (USAGE_STORAGE_BUFFER
444 				| USAGE_STORAGE_TEXEL_BUFFER
445 				| USAGE_TEXTURE_SAMPLED
446 				| USAGE_TEXTURE_STORAGE))
447 		flags |= vk::VK_ACCESS_SHADER_READ_BIT | vk::VK_ACCESS_SHADER_WRITE_BIT;
448 
449 	if (usage & USAGE_INDIRECT_BUFFER)
450 		flags |= vk::VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
451 
452 	if (usage & USAGE_COLOR_ATTACHMENT)
453 		flags |= vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
454 
455 	if (usage & USAGE_INPUT_ATTACHMENT)
456 		flags |= vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
457 
458 	if (usage & USAGE_DEPTH_STENCIL_ATTACHMENT)
459 		flags |= vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
460 			| vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
461 
462 	return flags;
463 }
464 
465 struct TestConfig
466 {
467 	Usage					usage;
468 	vk::VkDeviceSize		size;
469 	vk::VkSharingMode		sharing;
470 };
471 
createCommandBuffer(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkCommandPool pool,vk::VkCommandBufferLevel level)472 vk::Move<vk::VkCommandBuffer> createCommandBuffer (const vk::DeviceInterface&	vkd,
473 												   vk::VkDevice					device,
474 												   vk::VkCommandPool			pool,
475 												   vk::VkCommandBufferLevel		level)
476 {
477 	const vk::VkCommandBufferAllocateInfo bufferInfo =
478 	{
479 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
480 		DE_NULL,
481 
482 		pool,
483 		level,
484 		1u
485 	};
486 
487 	return vk::allocateCommandBuffer(vkd, device, &bufferInfo);
488 }
489 
createBeginCommandBuffer(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkCommandPool pool,vk::VkCommandBufferLevel level)490 vk::Move<vk::VkCommandBuffer> createBeginCommandBuffer (const vk::DeviceInterface&	vkd,
491 														vk::VkDevice				device,
492 														vk::VkCommandPool			pool,
493 														vk::VkCommandBufferLevel	level)
494 {
495 	const vk::VkCommandBufferInheritanceInfo	inheritInfo	=
496 	{
497 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
498 		DE_NULL,
499 		0,
500 		0,
501 		0,
502 		vk::VK_FALSE,
503 		0u,
504 		0u
505 	};
506 	const vk::VkCommandBufferBeginInfo			beginInfo =
507 	{
508 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
509 		DE_NULL,
510 		0u,
511 		(level == vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY ? &inheritInfo : (const vk::VkCommandBufferInheritanceInfo*)DE_NULL),
512 	};
513 
514 	vk::Move<vk::VkCommandBuffer> commandBuffer (createCommandBuffer(vkd, device, pool, level));
515 
516 	vkd.beginCommandBuffer(*commandBuffer, &beginInfo);
517 
518 	return commandBuffer;
519 }
520 
createCommandPool(const vk::DeviceInterface & vkd,vk::VkDevice device,deUint32 queueFamilyIndex)521 vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface&	vkd,
522 											   vk::VkDevice					device,
523 											   deUint32						queueFamilyIndex)
524 {
525 	const vk::VkCommandPoolCreateInfo poolInfo =
526 	{
527 		vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
528 		DE_NULL,
529 
530 		vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
531 		queueFamilyIndex,
532 	};
533 
534 	return vk::createCommandPool(vkd, device, &poolInfo);
535 }
536 
createBuffer(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDeviceSize size,vk::VkBufferUsageFlags usage,vk::VkSharingMode sharingMode,const vector<deUint32> & queueFamilies)537 vk::Move<vk::VkBuffer> createBuffer (const vk::DeviceInterface&	vkd,
538 									 vk::VkDevice				device,
539 									 vk::VkDeviceSize			size,
540 									 vk::VkBufferUsageFlags		usage,
541 									 vk::VkSharingMode			sharingMode,
542 									 const vector<deUint32>&	queueFamilies)
543 {
544 	const vk::VkBufferCreateInfo	createInfo =
545 	{
546 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
547 		DE_NULL,
548 
549 		0,	// flags
550 		size,
551 		usage,
552 		sharingMode,
553 		(deUint32)queueFamilies.size(),
554 		&queueFamilies[0]
555 	};
556 
557 	return vk::createBuffer(vkd, device, &createInfo);
558 }
559 
allocMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDeviceSize size,deUint32 memoryTypeIndex)560 vk::Move<vk::VkDeviceMemory> allocMemory (const vk::DeviceInterface&	vkd,
561 										  vk::VkDevice					device,
562 										  vk::VkDeviceSize				size,
563 										  deUint32						memoryTypeIndex)
564 {
565 	const vk::VkMemoryAllocateInfo alloc =
566 	{
567 		vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,	// sType
568 		DE_NULL,									// pNext
569 
570 		size,
571 		memoryTypeIndex
572 	};
573 
574 	return vk::allocateMemory(vkd, device, &alloc);
575 }
576 
bindBufferMemory(const vk::InstanceInterface & vki,const vk::DeviceInterface & vkd,vk::VkPhysicalDevice physicalDevice,vk::VkDevice device,vk::VkBuffer buffer,vk::VkMemoryPropertyFlags properties)577 vk::Move<vk::VkDeviceMemory> bindBufferMemory (const vk::InstanceInterface&	vki,
578 											   const vk::DeviceInterface&	vkd,
579 											   vk::VkPhysicalDevice			physicalDevice,
580 											   vk::VkDevice					device,
581 											   vk::VkBuffer					buffer,
582 											   vk::VkMemoryPropertyFlags	properties)
583 {
584 	const vk::VkMemoryRequirements				memoryRequirements	= vk::getBufferMemoryRequirements(vkd, device, buffer);
585 	const vk::VkPhysicalDeviceMemoryProperties	memoryProperties	= vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice);
586 	deUint32									memoryTypeIndex;
587 
588 	for (memoryTypeIndex = 0; memoryTypeIndex < memoryProperties.memoryTypeCount; memoryTypeIndex++)
589 	{
590 		if ((memoryRequirements.memoryTypeBits & (0x1u << memoryTypeIndex))
591 			&& (memoryProperties.memoryTypes[memoryTypeIndex].propertyFlags & properties) == properties)
592 		{
593 			try
594 			{
595 				const vk::VkMemoryAllocateInfo	allocationInfo	=
596 				{
597 					vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
598 					DE_NULL,
599 					memoryRequirements.size,
600 					memoryTypeIndex
601 				};
602 				vk::Move<vk::VkDeviceMemory>	memory			(vk::allocateMemory(vkd, device, &allocationInfo));
603 
604 				VK_CHECK(vkd.bindBufferMemory(device, buffer, *memory, 0));
605 
606 				return memory;
607 			}
608 			catch (const vk::Error& error)
609 			{
610 				if (error.getError() == vk::VK_ERROR_OUT_OF_DEVICE_MEMORY
611 					|| error.getError() == vk::VK_ERROR_OUT_OF_HOST_MEMORY)
612 				{
613 					// Try next memory type/heap if out of memory
614 				}
615 				else
616 				{
617 					// Throw all other errors forward
618 					throw;
619 				}
620 			}
621 		}
622 	}
623 
624 	TCU_FAIL("Failed to allocate memory for buffer");
625 }
626 
bindImageMemory(const vk::InstanceInterface & vki,const vk::DeviceInterface & vkd,vk::VkPhysicalDevice physicalDevice,vk::VkDevice device,vk::VkImage image,vk::VkMemoryPropertyFlags properties)627 vk::Move<vk::VkDeviceMemory> bindImageMemory (const vk::InstanceInterface&	vki,
628 											   const vk::DeviceInterface&	vkd,
629 											   vk::VkPhysicalDevice			physicalDevice,
630 											   vk::VkDevice					device,
631 											   vk::VkImage					image,
632 											   vk::VkMemoryPropertyFlags	properties)
633 {
634 	const vk::VkMemoryRequirements				memoryRequirements	= vk::getImageMemoryRequirements(vkd, device, image);
635 	const vk::VkPhysicalDeviceMemoryProperties	memoryProperties	= vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice);
636 	deUint32									memoryTypeIndex;
637 
638 	for (memoryTypeIndex = 0; memoryTypeIndex < memoryProperties.memoryTypeCount; memoryTypeIndex++)
639 	{
640 		if ((memoryRequirements.memoryTypeBits & (0x1u << memoryTypeIndex))
641 			&& (memoryProperties.memoryTypes[memoryTypeIndex].propertyFlags & properties) == properties)
642 		{
643 			try
644 			{
645 				const vk::VkMemoryAllocateInfo	allocationInfo	=
646 				{
647 					vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
648 					DE_NULL,
649 					memoryRequirements.size,
650 					memoryTypeIndex
651 				};
652 				vk::Move<vk::VkDeviceMemory>	memory			(vk::allocateMemory(vkd, device, &allocationInfo));
653 
654 				VK_CHECK(vkd.bindImageMemory(device, image, *memory, 0));
655 
656 				return memory;
657 			}
658 			catch (const vk::Error& error)
659 			{
660 				if (error.getError() == vk::VK_ERROR_OUT_OF_DEVICE_MEMORY
661 					|| error.getError() == vk::VK_ERROR_OUT_OF_HOST_MEMORY)
662 				{
663 					// Try next memory type/heap if out of memory
664 				}
665 				else
666 				{
667 					// Throw all other errors forward
668 					throw;
669 				}
670 			}
671 		}
672 	}
673 
674 	TCU_FAIL("Failed to allocate memory for image");
675 }
676 
queueRun(const vk::DeviceInterface & vkd,vk::VkQueue queue,vk::VkCommandBuffer commandBuffer)677 void queueRun (const vk::DeviceInterface&	vkd,
678 			   vk::VkQueue					queue,
679 			   vk::VkCommandBuffer			commandBuffer)
680 {
681 	const vk::VkSubmitInfo	submitInfo	=
682 	{
683 		vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
684 		DE_NULL,
685 
686 		0,
687 		DE_NULL,
688 		(const vk::VkPipelineStageFlags*)DE_NULL,
689 
690 		1,
691 		&commandBuffer,
692 
693 		0,
694 		DE_NULL
695 	};
696 
697 	VK_CHECK(vkd.queueSubmit(queue, 1, &submitInfo, 0));
698 	VK_CHECK(vkd.queueWaitIdle(queue));
699 }
700 
mapMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDeviceMemory memory,vk::VkDeviceSize size)701 void* mapMemory (const vk::DeviceInterface&	vkd,
702 				 vk::VkDevice				device,
703 				 vk::VkDeviceMemory			memory,
704 				 vk::VkDeviceSize			size)
705 {
706 	void* ptr;
707 
708 	VK_CHECK(vkd.mapMemory(device, memory, 0, size, 0, &ptr));
709 
710 	return ptr;
711 }
712 
713 class ReferenceMemory
714 {
715 public:
716 			ReferenceMemory	(size_t size);
717 
718 	void	set				(size_t pos, deUint8 val);
719 	deUint8	get				(size_t pos) const;
720 	bool	isDefined		(size_t pos) const;
721 
722 	void	setDefined		(size_t offset, size_t size, const void* data);
723 	void	setUndefined	(size_t offset, size_t size);
724 	void	setData			(size_t offset, size_t size, const void* data);
725 
getSize(void) const726 	size_t	getSize			(void) const { return m_data.size(); }
727 
728 private:
729 	vector<deUint8>		m_data;
730 	vector<deUint64>	m_defined;
731 };
732 
ReferenceMemory(size_t size)733 ReferenceMemory::ReferenceMemory (size_t size)
734 	: m_data	(size, 0)
735 	, m_defined	(size / 64 + (size % 64 == 0 ? 0 : 1), 0ull)
736 {
737 }
738 
set(size_t pos,deUint8 val)739 void ReferenceMemory::set (size_t pos, deUint8 val)
740 {
741 	m_data[pos] = val;
742 	m_defined[pos / 64] |= 0x1ull << (pos % 64);
743 }
744 
setData(size_t offset,size_t size,const void * data_)745 void ReferenceMemory::setData (size_t offset, size_t size, const void* data_)
746 {
747 	const deUint8* data = (const deUint8*)data_;
748 
749 	// \todo [2016-03-09 mika] Optimize
750 	for (size_t pos = 0; pos < size; pos++)
751 	{
752 		m_data[offset + pos] = data[pos];
753 		m_defined[(offset + pos) / 64] |= 0x1ull << ((offset + pos) % 64);
754 	}
755 }
756 
setUndefined(size_t offset,size_t size)757 void ReferenceMemory::setUndefined	(size_t offset, size_t size)
758 {
759 	// \todo [2016-03-09 mika] Optimize
760 	for (size_t pos = 0; pos < size; pos++)
761 		m_defined[(offset + pos) / 64] |= 0x1ull << ((offset + pos) % 64);
762 }
763 
get(size_t pos) const764 deUint8 ReferenceMemory::get (size_t pos) const
765 {
766 	DE_ASSERT(isDefined(pos));
767 	return m_data[pos];
768 }
769 
isDefined(size_t pos) const770 bool ReferenceMemory::isDefined (size_t pos) const
771 {
772 	return (m_defined[pos / 64] & (0x1ull << (pos % 64))) != 0;
773 }
774 
775 class Memory
776 {
777 public:
778 							Memory				(const vk::InstanceInterface&	vki,
779 												 const vk::DeviceInterface&		vkd,
780 												 vk::VkPhysicalDevice			physicalDevice,
781 												 vk::VkDevice					device,
782 												 vk::VkDeviceSize				size,
783 												 deUint32						memoryTypeIndex,
784 												 vk::VkDeviceSize				maxBufferSize,
785 												 deInt32						maxImageWidth,
786 												 deInt32						maxImageHeight);
787 
getSize(void) const788 	vk::VkDeviceSize		getSize				(void) const { return m_size; }
getMaxBufferSize(void) const789 	vk::VkDeviceSize		getMaxBufferSize	(void) const { return m_maxBufferSize; }
getSupportBuffers(void) const790 	bool					getSupportBuffers	(void) const { return m_maxBufferSize > 0; }
791 
getMaxImageWidth(void) const792 	deInt32					getMaxImageWidth	(void) const { return m_maxImageWidth; }
getMaxImageHeight(void) const793 	deInt32					getMaxImageHeight	(void) const { return m_maxImageHeight; }
getSupportImages(void) const794 	bool					getSupportImages	(void) const { return m_maxImageWidth > 0; }
795 
getMemoryType(void) const796 	const vk::VkMemoryType&	getMemoryType		(void) const { return m_memoryType; }
getMemoryTypeIndex(void) const797 	deUint32				getMemoryTypeIndex	(void) const { return m_memoryTypeIndex; }
getMemory(void) const798 	vk::VkDeviceMemory		getMemory			(void) const { return *m_memory; }
799 
800 private:
801 	const vk::VkDeviceSize					m_size;
802 	const deUint32							m_memoryTypeIndex;
803 	const vk::VkMemoryType					m_memoryType;
804 	const vk::Unique<vk::VkDeviceMemory>	m_memory;
805 	const vk::VkDeviceSize					m_maxBufferSize;
806 	const deInt32							m_maxImageWidth;
807 	const deInt32							m_maxImageHeight;
808 };
809 
getMemoryTypeInfo(const vk::InstanceInterface & vki,vk::VkPhysicalDevice device,deUint32 memoryTypeIndex)810 vk::VkMemoryType getMemoryTypeInfo (const vk::InstanceInterface&	vki,
811 									vk::VkPhysicalDevice			device,
812 									deUint32						memoryTypeIndex)
813 {
814 	const vk::VkPhysicalDeviceMemoryProperties memoryProperties = vk::getPhysicalDeviceMemoryProperties(vki, device);
815 
816 	DE_ASSERT(memoryTypeIndex < memoryProperties.memoryTypeCount);
817 
818 	return memoryProperties.memoryTypes[memoryTypeIndex];
819 }
820 
findMaxBufferSize(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkBufferUsageFlags usage,vk::VkSharingMode sharingMode,const vector<deUint32> & queueFamilies,vk::VkDeviceSize memorySize,deUint32 memoryTypeIndex)821 vk::VkDeviceSize findMaxBufferSize (const vk::DeviceInterface&		vkd,
822 									vk::VkDevice					device,
823 
824 									vk::VkBufferUsageFlags			usage,
825 									vk::VkSharingMode				sharingMode,
826 									const vector<deUint32>&			queueFamilies,
827 
828 									vk::VkDeviceSize				memorySize,
829 									deUint32						memoryTypeIndex)
830 {
831 	vk::VkDeviceSize lastSuccess = 0;
832 	vk::VkDeviceSize currentSize = memorySize / 2;
833 
834 	{
835 		const vk::Unique<vk::VkBuffer>  buffer			(createBuffer(vkd, device, memorySize, usage, sharingMode, queueFamilies));
836 		const vk::VkMemoryRequirements  requirements	(vk::getBufferMemoryRequirements(vkd, device, *buffer));
837 
838 		if (requirements.size == memorySize && requirements.memoryTypeBits & (0x1u << memoryTypeIndex))
839 			return memorySize;
840 	}
841 
842 	for (vk::VkDeviceSize stepSize = memorySize / 4; currentSize > 0; stepSize /= 2)
843 	{
844 		const vk::Unique<vk::VkBuffer>	buffer			(createBuffer(vkd, device, currentSize, usage, sharingMode, queueFamilies));
845 		const vk::VkMemoryRequirements	requirements	(vk::getBufferMemoryRequirements(vkd, device, *buffer));
846 
847 		if (requirements.size <= memorySize && requirements.memoryTypeBits & (0x1u << memoryTypeIndex))
848 		{
849 			lastSuccess = currentSize;
850 			currentSize += stepSize;
851 		}
852 		else
853 			currentSize -= stepSize;
854 
855 		if (stepSize == 0)
856 			break;
857 	}
858 
859 	return lastSuccess;
860 }
861 
862 // Round size down maximum W * H * 4, where W and H < 4096
roundBufferSizeToWxHx4(vk::VkDeviceSize size)863 vk::VkDeviceSize roundBufferSizeToWxHx4 (vk::VkDeviceSize size)
864 {
865 	const vk::VkDeviceSize	maxTextureSize	= 4096;
866 	vk::VkDeviceSize		maxTexelCount	= size / 4;
867 	vk::VkDeviceSize		bestW			= de::max(maxTexelCount, maxTextureSize);
868 	vk::VkDeviceSize		bestH			= maxTexelCount / bestW;
869 
870 	// \todo [2016-03-09 mika] Could probably be faster?
871 	for (vk::VkDeviceSize w = 1; w * w < maxTexelCount && w < maxTextureSize && bestW * bestH * 4 < size; w++)
872 	{
873 		const vk::VkDeviceSize h = maxTexelCount / w;
874 
875 		if (bestW * bestH < w * h)
876 		{
877 			bestW = w;
878 			bestH = h;
879 		}
880 	}
881 
882 	return bestW * bestH * 4;
883 }
884 
885 // Find RGBA8 image size that has exactly "size" of number of bytes.
886 // "size" must be W * H * 4 where W and H < 4096
findImageSizeWxHx4(vk::VkDeviceSize size)887 IVec2 findImageSizeWxHx4 (vk::VkDeviceSize size)
888 {
889 	const vk::VkDeviceSize	maxTextureSize	= 4096;
890 	vk::VkDeviceSize		texelCount		= size / 4;
891 
892 	DE_ASSERT((size % 4) == 0);
893 
894 	// \todo [2016-03-09 mika] Could probably be faster?
895 	for (vk::VkDeviceSize w = 1; w < maxTextureSize && w < texelCount; w++)
896 	{
897 		const vk::VkDeviceSize	h	= texelCount / w;
898 
899 		if ((texelCount  % w) == 0 && h < maxTextureSize)
900 			return IVec2((int)w, (int)h);
901 	}
902 
903 	DE_FATAL("Invalid size");
904 	return IVec2(-1, -1);
905 }
906 
findMaxRGBA8ImageSize(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkImageUsageFlags usage,vk::VkSharingMode sharingMode,const vector<deUint32> & queueFamilies,vk::VkDeviceSize memorySize,deUint32 memoryTypeIndex)907 IVec2 findMaxRGBA8ImageSize (const vk::DeviceInterface&	vkd,
908 							 vk::VkDevice				device,
909 
910 							 vk::VkImageUsageFlags		usage,
911 							 vk::VkSharingMode			sharingMode,
912 							 const vector<deUint32>&	queueFamilies,
913 
914 							 vk::VkDeviceSize			memorySize,
915 							 deUint32					memoryTypeIndex)
916 {
917 	IVec2		lastSuccess		(0);
918 	IVec2		currentSize;
919 
920 	{
921 		const deUint32	texelCount	= (deUint32)(memorySize / 4);
922 		const deUint32	width		= (deUint32)deFloatSqrt((float)texelCount);
923 		const deUint32	height		= texelCount / width;
924 
925 		currentSize[0] = deMaxu32(width, height);
926 		currentSize[1] = deMinu32(width, height);
927 	}
928 
929 	for (deInt32 stepSize = currentSize[0] / 2; currentSize[0] > 0; stepSize /= 2)
930 	{
931 		const vk::VkImageCreateInfo	createInfo		=
932 		{
933 			vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
934 			DE_NULL,
935 
936 			0u,
937 			vk::VK_IMAGE_TYPE_2D,
938 			vk::VK_FORMAT_R8G8B8A8_UNORM,
939 			{
940 				(deUint32)currentSize[0],
941 				(deUint32)currentSize[1],
942 				1u,
943 			},
944 			1u, 1u,
945 			vk::VK_SAMPLE_COUNT_1_BIT,
946 			vk::VK_IMAGE_TILING_OPTIMAL,
947 			usage,
948 			sharingMode,
949 			(deUint32)queueFamilies.size(),
950 			&queueFamilies[0],
951 			vk::VK_IMAGE_LAYOUT_UNDEFINED
952 		};
953 		const vk::Unique<vk::VkImage>	image			(vk::createImage(vkd, device, &createInfo));
954 		const vk::VkMemoryRequirements	requirements	(vk::getImageMemoryRequirements(vkd, device, *image));
955 
956 		if (requirements.size <= memorySize && requirements.memoryTypeBits & (0x1u << memoryTypeIndex))
957 		{
958 			lastSuccess = currentSize;
959 			currentSize[0] += stepSize;
960 			currentSize[1] += stepSize;
961 		}
962 		else
963 		{
964 			currentSize[0] -= stepSize;
965 			currentSize[1] -= stepSize;
966 		}
967 
968 		if (stepSize == 0)
969 			break;
970 	}
971 
972 	return lastSuccess;
973 }
974 
Memory(const vk::InstanceInterface & vki,const vk::DeviceInterface & vkd,vk::VkPhysicalDevice physicalDevice,vk::VkDevice device,vk::VkDeviceSize size,deUint32 memoryTypeIndex,vk::VkDeviceSize maxBufferSize,deInt32 maxImageWidth,deInt32 maxImageHeight)975 Memory::Memory (const vk::InstanceInterface&	vki,
976 				const vk::DeviceInterface&		vkd,
977 				vk::VkPhysicalDevice			physicalDevice,
978 				vk::VkDevice					device,
979 				vk::VkDeviceSize				size,
980 				deUint32						memoryTypeIndex,
981 				vk::VkDeviceSize				maxBufferSize,
982 				deInt32							maxImageWidth,
983 				deInt32							maxImageHeight)
984 	: m_size			(size)
985 	, m_memoryTypeIndex	(memoryTypeIndex)
986 	, m_memoryType		(getMemoryTypeInfo(vki, physicalDevice, memoryTypeIndex))
987 	, m_memory			(allocMemory(vkd, device, size, memoryTypeIndex))
988 	, m_maxBufferSize	(maxBufferSize)
989 	, m_maxImageWidth	(maxImageWidth)
990 	, m_maxImageHeight	(maxImageHeight)
991 {
992 }
993 
994 class Context
995 {
996 public:
Context(const vk::InstanceInterface & vki,const vk::DeviceInterface & vkd,vk::VkPhysicalDevice physicalDevice,vk::VkDevice device,vk::VkQueue queue,deUint32 queueFamilyIndex,const vector<pair<deUint32,vk::VkQueue>> & queues,const vk::ProgramCollection<vk::ProgramBinary> & binaryCollection)997 												Context					(const vk::InstanceInterface&						vki,
998 																		 const vk::DeviceInterface&							vkd,
999 																		 vk::VkPhysicalDevice								physicalDevice,
1000 																		 vk::VkDevice										device,
1001 																		 vk::VkQueue										queue,
1002 																		 deUint32											queueFamilyIndex,
1003 																		 const vector<pair<deUint32, vk::VkQueue> >&		queues,
1004 																		 const vk::ProgramCollection<vk::ProgramBinary>&	binaryCollection)
1005 		: m_vki					(vki)
1006 		, m_vkd					(vkd)
1007 		, m_physicalDevice		(physicalDevice)
1008 		, m_device				(device)
1009 		, m_queue				(queue)
1010 		, m_queueFamilyIndex	(queueFamilyIndex)
1011 		, m_queues				(queues)
1012 		, m_commandPool			(createCommandPool(vkd, device, queueFamilyIndex))
1013 		, m_binaryCollection	(binaryCollection)
1014 	{
1015 		for (size_t queueNdx = 0; queueNdx < m_queues.size(); queueNdx++)
1016 			m_queueFamilies.push_back(m_queues[queueNdx].first);
1017 	}
1018 
getInstanceInterface(void) const1019 	const vk::InstanceInterface&					getInstanceInterface	(void) const { return m_vki; }
getPhysicalDevice(void) const1020 	vk::VkPhysicalDevice							getPhysicalDevice		(void) const { return m_physicalDevice; }
getDevice(void) const1021 	vk::VkDevice									getDevice				(void) const { return m_device; }
getDeviceInterface(void) const1022 	const vk::DeviceInterface&						getDeviceInterface		(void) const { return m_vkd; }
getQueue(void) const1023 	vk::VkQueue										getQueue				(void) const { return m_queue; }
getQueueFamily(void) const1024 	deUint32										getQueueFamily			(void) const { return m_queueFamilyIndex; }
getQueues(void) const1025 	const vector<pair<deUint32, vk::VkQueue> >&		getQueues				(void) const { return m_queues; }
getQueueFamilies(void) const1026 	const vector<deUint32>							getQueueFamilies		(void) const { return m_queueFamilies; }
getCommandPool(void) const1027 	vk::VkCommandPool								getCommandPool			(void) const { return *m_commandPool; }
getBinaryCollection(void) const1028 	const vk::ProgramCollection<vk::ProgramBinary>&	getBinaryCollection		(void) const { return m_binaryCollection; }
1029 
1030 private:
1031 	const vk::InstanceInterface&					m_vki;
1032 	const vk::DeviceInterface&						m_vkd;
1033 	const vk::VkPhysicalDevice						m_physicalDevice;
1034 	const vk::VkDevice								m_device;
1035 	const vk::VkQueue								m_queue;
1036 	const deUint32									m_queueFamilyIndex;
1037 	const vector<pair<deUint32, vk::VkQueue> >&		m_queues;
1038 	const vk::Unique<vk::VkCommandPool>				m_commandPool;
1039 	const vk::ProgramCollection<vk::ProgramBinary>&	m_binaryCollection;
1040 	vector<deUint32>								m_queueFamilies;
1041 };
1042 
1043 class PrepareContext
1044 {
1045 public:
PrepareContext(const Context & context,const Memory & memory)1046 							PrepareContext	(const Context&	context,
1047 											 const Memory&	memory)
1048 		: m_context	(context)
1049 		, m_memory	(memory)
1050 	{
1051 	}
1052 
getMemory(void) const1053 	const Memory&									getMemory				(void) const { return m_memory; }
getContext(void) const1054 	const Context&									getContext				(void) const { return m_context; }
getBinaryCollection(void) const1055 	const vk::ProgramCollection<vk::ProgramBinary>&	getBinaryCollection		(void) const { return m_context.getBinaryCollection(); }
1056 
setBuffer(vk::Move<vk::VkBuffer> buffer,vk::VkDeviceSize size)1057 	void					setBuffer		(vk::Move<vk::VkBuffer>	buffer,
1058 											 vk::VkDeviceSize		size)
1059 	{
1060 		DE_ASSERT(!m_currentImage);
1061 		DE_ASSERT(!m_currentBuffer);
1062 
1063 		m_currentBuffer		= buffer;
1064 		m_currentBufferSize	= size;
1065 	}
1066 
getBuffer(void) const1067 	vk::VkBuffer			getBuffer		(void) const { return *m_currentBuffer; }
getBufferSize(void) const1068 	vk::VkDeviceSize		getBufferSize	(void) const
1069 	{
1070 		DE_ASSERT(m_currentBuffer);
1071 		return m_currentBufferSize;
1072 	}
1073 
releaseBuffer(void)1074 	void					releaseBuffer	(void) { m_currentBuffer.disown(); }
1075 
setImage(vk::Move<vk::VkImage> image,vk::VkImageLayout layout,vk::VkDeviceSize memorySize,deInt32 width,deInt32 height)1076 	void					setImage		(vk::Move<vk::VkImage>	image,
1077 											 vk::VkImageLayout		layout,
1078 											 vk::VkDeviceSize		memorySize,
1079 											 deInt32				width,
1080 											 deInt32				height)
1081 	{
1082 		DE_ASSERT(!m_currentImage);
1083 		DE_ASSERT(!m_currentBuffer);
1084 
1085 		m_currentImage				= image;
1086 		m_currentImageMemorySize	= memorySize;
1087 		m_currentImageLayout		= layout;
1088 		m_currentImageWidth			= width;
1089 		m_currentImageHeight		= height;
1090 	}
1091 
setImageLayout(vk::VkImageLayout layout)1092 	void				setImageLayout	(vk::VkImageLayout layout)
1093 	{
1094 		DE_ASSERT(m_currentImage);
1095 		m_currentImageLayout = layout;
1096 	}
1097 
getImage(void) const1098 	vk::VkImage			getImage		(void) const { return *m_currentImage; }
getImageWidth(void) const1099 	deInt32				getImageWidth	(void) const
1100 	{
1101 		DE_ASSERT(m_currentImage);
1102 		return m_currentImageWidth;
1103 	}
getImageHeight(void) const1104 	deInt32				getImageHeight	(void) const
1105 	{
1106 		DE_ASSERT(m_currentImage);
1107 		return m_currentImageHeight;
1108 	}
getImageMemorySize(void) const1109 	vk::VkDeviceSize	getImageMemorySize	(void) const
1110 	{
1111 		DE_ASSERT(m_currentImage);
1112 		return m_currentImageMemorySize;
1113 	}
1114 
releaseImage(void)1115 	void					releaseImage	(void) { m_currentImage.disown(); }
1116 
getImageLayout(void) const1117 	vk::VkImageLayout		getImageLayout	(void) const
1118 	{
1119 		DE_ASSERT(m_currentImage);
1120 		return m_currentImageLayout;
1121 	}
1122 
1123 private:
1124 	const Context&			m_context;
1125 	const Memory&			m_memory;
1126 
1127 	vk::Move<vk::VkBuffer>	m_currentBuffer;
1128 	vk::VkDeviceSize		m_currentBufferSize;
1129 
1130 	vk::Move<vk::VkImage>	m_currentImage;
1131 	vk::VkDeviceSize		m_currentImageMemorySize;
1132 	vk::VkImageLayout		m_currentImageLayout;
1133 	deInt32					m_currentImageWidth;
1134 	deInt32					m_currentImageHeight;
1135 };
1136 
1137 class ExecuteContext
1138 {
1139 public:
ExecuteContext(const Context & context)1140 					ExecuteContext	(const Context&	context)
1141 		: m_context	(context)
1142 	{
1143 	}
1144 
getContext(void) const1145 	const Context&	getContext		(void) const { return m_context; }
setMapping(void * ptr)1146 	void			setMapping		(void* ptr) { m_mapping = ptr; }
getMapping(void) const1147 	void*			getMapping		(void) const { return m_mapping; }
1148 
1149 private:
1150 	const Context&	m_context;
1151 	void*			m_mapping;
1152 };
1153 
1154 class VerifyContext
1155 {
1156 public:
VerifyContext(TestLog & log,tcu::ResultCollector & resultCollector,const Context & context,vk::VkDeviceSize size)1157 							VerifyContext		(TestLog&				log,
1158 												 tcu::ResultCollector&	resultCollector,
1159 												 const Context&			context,
1160 												 vk::VkDeviceSize		size)
1161 		: m_log				(log)
1162 		, m_resultCollector	(resultCollector)
1163 		, m_context			(context)
1164 		, m_reference		((size_t)size)
1165 	{
1166 	}
1167 
getContext(void) const1168 	const Context&			getContext			(void) const { return m_context; }
getLog(void) const1169 	TestLog&				getLog				(void) const { return m_log; }
getResultCollector(void) const1170 	tcu::ResultCollector&	getResultCollector	(void) const { return m_resultCollector; }
1171 
getReference(void)1172 	ReferenceMemory&		getReference		(void) { return m_reference; }
getReferenceImage(void)1173 	TextureLevel&			getReferenceImage	(void) { return m_referenceImage;}
1174 
1175 private:
1176 	TestLog&				m_log;
1177 	tcu::ResultCollector&	m_resultCollector;
1178 	const Context&			m_context;
1179 	ReferenceMemory			m_reference;
1180 	TextureLevel			m_referenceImage;
1181 };
1182 
1183 class Command
1184 {
1185 public:
1186 	// Constructor should allocate all non-vulkan resources.
~Command(void)1187 	virtual				~Command	(void) {}
1188 
1189 	// Get name of the command
1190 	virtual const char*	getName		(void) const = 0;
1191 
1192 	// Log prepare operations
logPrepare(TestLog &,size_t) const1193 	virtual void		logPrepare	(TestLog&, size_t) const {}
1194 	// Log executed operations
logExecute(TestLog &,size_t) const1195 	virtual void		logExecute	(TestLog&, size_t) const {}
1196 
1197 	// Prepare should allocate all vulkan resources and resources that require
1198 	// that buffer or memory has been already allocated. This should build all
1199 	// command buffers etc.
prepare(PrepareContext &)1200 	virtual void		prepare		(PrepareContext&) {}
1201 
1202 	// Execute command. Write or read mapped memory, submit commands to queue
1203 	// etc.
execute(ExecuteContext &)1204 	virtual void		execute		(ExecuteContext&) {}
1205 
1206 	// Verify that results are correct.
verify(VerifyContext &,size_t)1207 	virtual void		verify		(VerifyContext&, size_t) {}
1208 
1209 protected:
1210 	// Allow only inheritance
Command(void)1211 						Command		(void) {}
1212 
1213 private:
1214 	// Disallow copying
1215 						Command		(const Command&);
1216 	Command&			operator&	(const Command&);
1217 };
1218 
1219 class Map : public Command
1220 {
1221 public:
Map(void)1222 						Map			(void) {}
~Map(void)1223 						~Map		(void) {}
getName(void) const1224 	const char*			getName		(void) const { return "Map"; }
1225 
1226 
logExecute(TestLog & log,size_t commandIndex) const1227 	void				logExecute	(TestLog& log, size_t commandIndex) const
1228 	{
1229 		log << TestLog::Message << commandIndex << ":" << getName() << " Map memory" << TestLog::EndMessage;
1230 	}
1231 
prepare(PrepareContext & context)1232 	void				prepare		(PrepareContext& context)
1233 	{
1234 		m_memory	= context.getMemory().getMemory();
1235 		m_size		= context.getMemory().getSize();
1236 	}
1237 
execute(ExecuteContext & context)1238 	void				execute		(ExecuteContext& context)
1239 	{
1240 		const vk::DeviceInterface&	vkd		= context.getContext().getDeviceInterface();
1241 		const vk::VkDevice			device	= context.getContext().getDevice();
1242 
1243 		context.setMapping(mapMemory(vkd, device, m_memory, m_size));
1244 	}
1245 
1246 private:
1247 	vk::VkDeviceMemory	m_memory;
1248 	vk::VkDeviceSize	m_size;
1249 };
1250 
1251 class UnMap : public Command
1252 {
1253 public:
UnMap(void)1254 						UnMap		(void) {}
~UnMap(void)1255 						~UnMap		(void) {}
getName(void) const1256 	const char*			getName		(void) const { return "UnMap"; }
1257 
logExecute(TestLog & log,size_t commandIndex) const1258 	void				logExecute	(TestLog& log, size_t commandIndex) const
1259 	{
1260 		log << TestLog::Message << commandIndex << ": Unmap memory" << TestLog::EndMessage;
1261 	}
1262 
prepare(PrepareContext & context)1263 	void				prepare		(PrepareContext& context)
1264 	{
1265 		m_memory	= context.getMemory().getMemory();
1266 	}
1267 
execute(ExecuteContext & context)1268 	void				execute		(ExecuteContext& context)
1269 	{
1270 		const vk::DeviceInterface&	vkd		= context.getContext().getDeviceInterface();
1271 		const vk::VkDevice			device	= context.getContext().getDevice();
1272 
1273 		vkd.unmapMemory(device, m_memory);
1274 		context.setMapping(DE_NULL);
1275 	}
1276 
1277 private:
1278 	vk::VkDeviceMemory	m_memory;
1279 };
1280 
1281 class Invalidate : public Command
1282 {
1283 public:
Invalidate(void)1284 						Invalidate	(void) {}
~Invalidate(void)1285 						~Invalidate	(void) {}
getName(void) const1286 	const char*			getName		(void) const { return "Invalidate"; }
1287 
logExecute(TestLog & log,size_t commandIndex) const1288 	void				logExecute	(TestLog& log, size_t commandIndex) const
1289 	{
1290 		log << TestLog::Message << commandIndex << ": Invalidate mapped memory" << TestLog::EndMessage;
1291 	}
1292 
prepare(PrepareContext & context)1293 	void				prepare		(PrepareContext& context)
1294 	{
1295 		m_memory	= context.getMemory().getMemory();
1296 		m_size		= context.getMemory().getSize();
1297 	}
1298 
execute(ExecuteContext & context)1299 	void				execute		(ExecuteContext& context)
1300 	{
1301 		const vk::DeviceInterface&	vkd		= context.getContext().getDeviceInterface();
1302 		const vk::VkDevice			device	= context.getContext().getDevice();
1303 
1304 		vk::invalidateMappedMemoryRange(vkd, device, m_memory, 0, m_size);
1305 	}
1306 
1307 private:
1308 	vk::VkDeviceMemory	m_memory;
1309 	vk::VkDeviceSize	m_size;
1310 };
1311 
1312 class Flush : public Command
1313 {
1314 public:
Flush(void)1315 						Flush		(void) {}
~Flush(void)1316 						~Flush		(void) {}
getName(void) const1317 	const char*			getName		(void) const { return "Flush"; }
1318 
logExecute(TestLog & log,size_t commandIndex) const1319 	void				logExecute	(TestLog& log, size_t commandIndex) const
1320 	{
1321 		log << TestLog::Message << commandIndex << ": Flush mapped memory" << TestLog::EndMessage;
1322 	}
1323 
prepare(PrepareContext & context)1324 	void				prepare		(PrepareContext& context)
1325 	{
1326 		m_memory	= context.getMemory().getMemory();
1327 		m_size		= context.getMemory().getSize();
1328 	}
1329 
execute(ExecuteContext & context)1330 	void				execute		(ExecuteContext& context)
1331 	{
1332 		const vk::DeviceInterface&	vkd		= context.getContext().getDeviceInterface();
1333 		const vk::VkDevice			device	= context.getContext().getDevice();
1334 
1335 		vk::flushMappedMemoryRange(vkd, device, m_memory, 0, m_size);
1336 	}
1337 
1338 private:
1339 	vk::VkDeviceMemory	m_memory;
1340 	vk::VkDeviceSize	m_size;
1341 };
1342 
1343 // Host memory reads and writes
1344 class HostMemoryAccess : public Command
1345 {
1346 public:
1347 					HostMemoryAccess	(bool read, bool write, deUint32 seed);
~HostMemoryAccess(void)1348 					~HostMemoryAccess	(void) {}
getName(void) const1349 	const char*		getName				(void) const { return "HostMemoryAccess"; }
1350 
1351 	void			logExecute			(TestLog& log, size_t commandIndex) const;
1352 	void			prepare				(PrepareContext& context);
1353 	void			execute				(ExecuteContext& context);
1354 
1355 	void			verify				(VerifyContext& context, size_t commandIndex);
1356 
1357 private:
1358 	const bool		m_read;
1359 	const bool		m_write;
1360 	const deUint32	m_seed;
1361 
1362 	size_t			m_size;
1363 	vector<deUint8>	m_readData;
1364 };
1365 
HostMemoryAccess(bool read,bool write,deUint32 seed)1366 HostMemoryAccess::HostMemoryAccess (bool read, bool write, deUint32 seed)
1367 	: m_read	(read)
1368 	, m_write	(write)
1369 	, m_seed	(seed)
1370 {
1371 }
1372 
logExecute(TestLog & log,size_t commandIndex) const1373 void HostMemoryAccess::logExecute (TestLog& log, size_t commandIndex) const
1374 {
1375 	log << TestLog::Message << commandIndex << ": Host memory access:" << (m_read ? " read" : "") << (m_write ? " write" : "")  << ", seed: " << m_seed << TestLog::EndMessage;
1376 }
1377 
prepare(PrepareContext & context)1378 void HostMemoryAccess::prepare (PrepareContext& context)
1379 {
1380 	m_size = (size_t)context.getMemory().getSize();
1381 
1382 	if (m_read)
1383 		m_readData.resize(m_size, 0);
1384 }
1385 
execute(ExecuteContext & context)1386 void HostMemoryAccess::execute (ExecuteContext& context)
1387 {
1388 	de::Random		rng	(m_seed);
1389 	deUint8* const	ptr	= (deUint8*)context.getMapping();
1390 
1391 	if (m_read && m_write)
1392 	{
1393 		for (size_t pos = 0; pos < m_size; pos++)
1394 		{
1395 			const deUint8	mask	= rng.getUint8();
1396 			const deUint8	value	= ptr[pos];
1397 
1398 			m_readData[pos] = value;
1399 			ptr[pos] = value ^ mask;
1400 		}
1401 	}
1402 	else if (m_read)
1403 	{
1404 		for (size_t pos = 0; pos < m_size; pos++)
1405 		{
1406 			const deUint8	value	= ptr[pos];
1407 
1408 			m_readData[pos] = value;
1409 		}
1410 	}
1411 	else if (m_write)
1412 	{
1413 		for (size_t pos = 0; pos < m_size; pos++)
1414 		{
1415 			const deUint8	value	= rng.getUint8();
1416 
1417 			ptr[pos] = value;
1418 		}
1419 	}
1420 	else
1421 		DE_FATAL("Host memory access without read or write.");
1422 }
1423 
verify(VerifyContext & context,size_t commandIndex)1424 void HostMemoryAccess::verify (VerifyContext& context, size_t commandIndex)
1425 {
1426 	tcu::ResultCollector&	resultCollector	= context.getResultCollector();
1427 	ReferenceMemory&		reference		= context.getReference();
1428 	de::Random				rng				(m_seed);
1429 
1430 	if (m_read && m_write)
1431 	{
1432 		for (size_t pos = 0; pos < m_size; pos++)
1433 		{
1434 			const deUint8	mask	= rng.getUint8();
1435 			const deUint8	value	= m_readData[pos];
1436 
1437 			if (reference.isDefined(pos))
1438 			{
1439 				if (value != reference.get(pos))
1440 				{
1441 					resultCollector.fail(
1442 							de::toString(commandIndex) + ":" + getName()
1443 							+ " Result differs from reference, Expected: "
1444 							+ de::toString(tcu::toHex<8>(reference.get(pos)))
1445 							+ ", Got: "
1446 							+ de::toString(tcu::toHex<8>(value))
1447 							+ ", At offset: "
1448 							+ de::toString(pos));
1449 					break;
1450 				}
1451 
1452 				reference.set(pos, reference.get(pos) ^ mask);
1453 			}
1454 		}
1455 	}
1456 	else if (m_read)
1457 	{
1458 		for (size_t pos = 0; pos < m_size; pos++)
1459 		{
1460 			const deUint8	value	= m_readData[pos];
1461 
1462 			if (reference.isDefined(pos))
1463 			{
1464 				if (value != reference.get(pos))
1465 				{
1466 					resultCollector.fail(
1467 							de::toString(commandIndex) + ":" + getName()
1468 							+ " Result differs from reference, Expected: "
1469 							+ de::toString(tcu::toHex<8>(reference.get(pos)))
1470 							+ ", Got: "
1471 							+ de::toString(tcu::toHex<8>(value))
1472 							+ ", At offset: "
1473 							+ de::toString(pos));
1474 					break;
1475 				}
1476 			}
1477 		}
1478 	}
1479 	else if (m_write)
1480 	{
1481 		for (size_t pos = 0; pos < m_size; pos++)
1482 		{
1483 			const deUint8	value	= rng.getUint8();
1484 
1485 			reference.set(pos, value);
1486 		}
1487 	}
1488 	else
1489 		DE_FATAL("Host memory access without read or write.");
1490 }
1491 
1492 class CreateBuffer : public Command
1493 {
1494 public:
1495 									CreateBuffer	(vk::VkBufferUsageFlags	usage,
1496 													 vk::VkSharingMode		sharing);
~CreateBuffer(void)1497 									~CreateBuffer	(void) {}
getName(void) const1498 	const char*						getName			(void) const { return "CreateBuffer"; }
1499 
1500 	void							logPrepare		(TestLog& log, size_t commandIndex) const;
1501 	void							prepare			(PrepareContext& context);
1502 
1503 private:
1504 	const vk::VkBufferUsageFlags	m_usage;
1505 	const vk::VkSharingMode			m_sharing;
1506 };
1507 
CreateBuffer(vk::VkBufferUsageFlags usage,vk::VkSharingMode sharing)1508 CreateBuffer::CreateBuffer (vk::VkBufferUsageFlags	usage,
1509 							vk::VkSharingMode		sharing)
1510 	: m_usage	(usage)
1511 	, m_sharing	(sharing)
1512 {
1513 }
1514 
logPrepare(TestLog & log,size_t commandIndex) const1515 void CreateBuffer::logPrepare (TestLog& log, size_t commandIndex) const
1516 {
1517 	log << TestLog::Message << commandIndex << ":" << getName() << " Create buffer, Sharing mode: " << m_sharing << ", Usage: " << vk::getBufferUsageFlagsStr(m_usage) << TestLog::EndMessage;
1518 }
1519 
prepare(PrepareContext & context)1520 void CreateBuffer::prepare (PrepareContext& context)
1521 {
1522 	const vk::DeviceInterface&	vkd				= context.getContext().getDeviceInterface();
1523 	const vk::VkDevice			device			= context.getContext().getDevice();
1524 	const vk::VkDeviceSize		bufferSize		= context.getMemory().getMaxBufferSize();
1525 	const vector<deUint32>&		queueFamilies	= context.getContext().getQueueFamilies();
1526 
1527 	context.setBuffer(createBuffer(vkd, device, bufferSize, m_usage, m_sharing, queueFamilies), bufferSize);
1528 }
1529 
1530 class DestroyBuffer : public Command
1531 {
1532 public:
1533 							DestroyBuffer	(void);
~DestroyBuffer(void)1534 							~DestroyBuffer	(void) {}
getName(void) const1535 	const char*				getName			(void) const { return "DestroyBuffer"; }
1536 
1537 	void					logExecute		(TestLog& log, size_t commandIndex) const;
1538 	void					prepare			(PrepareContext& context);
1539 	void					execute			(ExecuteContext& context);
1540 
1541 private:
1542 	vk::Move<vk::VkBuffer>	m_buffer;
1543 };
1544 
DestroyBuffer(void)1545 DestroyBuffer::DestroyBuffer (void)
1546 {
1547 }
1548 
prepare(PrepareContext & context)1549 void DestroyBuffer::prepare (PrepareContext& context)
1550 {
1551 	m_buffer = vk::Move<vk::VkBuffer>(vk::check(context.getBuffer()), vk::Deleter<vk::VkBuffer>(context.getContext().getDeviceInterface(), context.getContext().getDevice(), DE_NULL));
1552 	context.releaseBuffer();
1553 }
1554 
logExecute(TestLog & log,size_t commandIndex) const1555 void DestroyBuffer::logExecute (TestLog& log, size_t commandIndex) const
1556 {
1557 	log << TestLog::Message << commandIndex << ":" << getName() << " Destroy buffer" << TestLog::EndMessage;
1558 }
1559 
execute(ExecuteContext & context)1560 void DestroyBuffer::execute (ExecuteContext& context)
1561 {
1562 	const vk::DeviceInterface&	vkd				= context.getContext().getDeviceInterface();
1563 	const vk::VkDevice			device			= context.getContext().getDevice();
1564 
1565 	vkd.destroyBuffer(device, m_buffer.disown(), DE_NULL);
1566 }
1567 
1568 class BindBufferMemory : public Command
1569 {
1570 public:
BindBufferMemory(void)1571 				BindBufferMemory	(void) {}
~BindBufferMemory(void)1572 				~BindBufferMemory	(void) {}
getName(void) const1573 	const char*	getName				(void) const { return "BindBufferMemory"; }
1574 
1575 	void		logPrepare			(TestLog& log, size_t commandIndex) const;
1576 	void		prepare				(PrepareContext& context);
1577 };
1578 
logPrepare(TestLog & log,size_t commandIndex) const1579 void BindBufferMemory::logPrepare (TestLog& log, size_t commandIndex) const
1580 {
1581 	log << TestLog::Message << commandIndex << ":" << getName() << " Bind memory to buffer" << TestLog::EndMessage;
1582 }
1583 
prepare(PrepareContext & context)1584 void BindBufferMemory::prepare (PrepareContext& context)
1585 {
1586 	const vk::DeviceInterface&	vkd				= context.getContext().getDeviceInterface();
1587 	const vk::VkDevice			device			= context.getContext().getDevice();
1588 
1589 	VK_CHECK(vkd.bindBufferMemory(device, context.getBuffer(), context.getMemory().getMemory(), 0));
1590 }
1591 
1592 class CreateImage : public Command
1593 {
1594 public:
1595 									CreateImage		(vk::VkImageUsageFlags	usage,
1596 													 vk::VkSharingMode		sharing);
~CreateImage(void)1597 									~CreateImage	(void) {}
getName(void) const1598 	const char*						getName			(void) const { return "CreateImage"; }
1599 
1600 	void							logPrepare		(TestLog& log, size_t commandIndex) const;
1601 	void							prepare			(PrepareContext& context);
1602 	void							verify			(VerifyContext& context, size_t commandIndex);
1603 
1604 private:
1605 	const vk::VkImageUsageFlags	m_usage;
1606 	const vk::VkSharingMode		m_sharing;
1607 	deInt32						m_imageWidth;
1608 	deInt32						m_imageHeight;
1609 };
1610 
CreateImage(vk::VkImageUsageFlags usage,vk::VkSharingMode sharing)1611 CreateImage::CreateImage (vk::VkImageUsageFlags	usage,
1612 						  vk::VkSharingMode		sharing)
1613 	: m_usage	(usage)
1614 	, m_sharing	(sharing)
1615 {
1616 }
1617 
logPrepare(TestLog & log,size_t commandIndex) const1618 void CreateImage::logPrepare (TestLog& log, size_t commandIndex) const
1619 {
1620 	log << TestLog::Message << commandIndex << ":" << getName() << " Create image, sharing: " << m_sharing << ", usage: " << vk::getImageUsageFlagsStr(m_usage)  << TestLog::EndMessage;
1621 }
1622 
prepare(PrepareContext & context)1623 void CreateImage::prepare (PrepareContext& context)
1624 {
1625 	const vk::DeviceInterface&	vkd				= context.getContext().getDeviceInterface();
1626 	const vk::VkDevice			device			= context.getContext().getDevice();
1627 	const vector<deUint32>&		queueFamilies	= context.getContext().getQueueFamilies();
1628 
1629 	m_imageWidth	= context.getMemory().getMaxImageWidth();
1630 	m_imageHeight	= context.getMemory().getMaxImageHeight();
1631 
1632 	{
1633 		const vk::VkImageCreateInfo	createInfo		=
1634 		{
1635 			vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
1636 			DE_NULL,
1637 
1638 			0u,
1639 			vk::VK_IMAGE_TYPE_2D,
1640 			vk::VK_FORMAT_R8G8B8A8_UNORM,
1641 			{
1642 				(deUint32)m_imageWidth,
1643 				(deUint32)m_imageHeight,
1644 				1u,
1645 			},
1646 			1u, 1u,
1647 			vk::VK_SAMPLE_COUNT_1_BIT,
1648 			vk::VK_IMAGE_TILING_OPTIMAL,
1649 			m_usage,
1650 			m_sharing,
1651 			(deUint32)queueFamilies.size(),
1652 			&queueFamilies[0],
1653 			vk::VK_IMAGE_LAYOUT_UNDEFINED
1654 		};
1655 		vk::Move<vk::VkImage>			image			(createImage(vkd, device, &createInfo));
1656 		const vk::VkMemoryRequirements	requirements	= vk::getImageMemoryRequirements(vkd, device, *image);
1657 
1658 		context.setImage(image, vk::VK_IMAGE_LAYOUT_UNDEFINED, requirements.size, m_imageWidth, m_imageHeight);
1659 	}
1660 }
1661 
verify(VerifyContext & context,size_t)1662 void CreateImage::verify (VerifyContext& context, size_t)
1663 {
1664 	context.getReferenceImage() = TextureLevel(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_imageWidth, m_imageHeight);
1665 }
1666 
1667 class DestroyImage : public Command
1668 {
1669 public:
1670 							DestroyImage	(void);
~DestroyImage(void)1671 							~DestroyImage	(void) {}
getName(void) const1672 	const char*				getName			(void) const { return "DestroyImage"; }
1673 
1674 	void					logExecute		(TestLog& log, size_t commandIndex) const;
1675 	void					prepare			(PrepareContext& context);
1676 	void					execute			(ExecuteContext& context);
1677 
1678 private:
1679 	vk::Move<vk::VkImage>	m_image;
1680 };
1681 
DestroyImage(void)1682 DestroyImage::DestroyImage (void)
1683 {
1684 }
1685 
prepare(PrepareContext & context)1686 void DestroyImage::prepare (PrepareContext& context)
1687 {
1688 	m_image = vk::Move<vk::VkImage>(vk::check(context.getImage()), vk::Deleter<vk::VkImage>(context.getContext().getDeviceInterface(), context.getContext().getDevice(), DE_NULL));
1689 	context.releaseImage();
1690 }
1691 
1692 
logExecute(TestLog & log,size_t commandIndex) const1693 void DestroyImage::logExecute (TestLog& log, size_t commandIndex) const
1694 {
1695 	log << TestLog::Message << commandIndex << ":" << getName() << " Destroy image" << TestLog::EndMessage;
1696 }
1697 
execute(ExecuteContext & context)1698 void DestroyImage::execute (ExecuteContext& context)
1699 {
1700 	const vk::DeviceInterface&	vkd				= context.getContext().getDeviceInterface();
1701 	const vk::VkDevice			device			= context.getContext().getDevice();
1702 
1703 	vkd.destroyImage(device, m_image.disown(), DE_NULL);
1704 }
1705 
1706 class BindImageMemory : public Command
1707 {
1708 public:
BindImageMemory(void)1709 				BindImageMemory		(void) {}
~BindImageMemory(void)1710 				~BindImageMemory	(void) {}
getName(void) const1711 	const char*	getName				(void) const { return "BindImageMemory"; }
1712 
1713 	void		logPrepare			(TestLog& log, size_t commandIndex) const;
1714 	void		prepare				(PrepareContext& context);
1715 };
1716 
logPrepare(TestLog & log,size_t commandIndex) const1717 void BindImageMemory::logPrepare (TestLog& log, size_t commandIndex) const
1718 {
1719 	log << TestLog::Message << commandIndex << ":" << getName() << " Bind memory to image" << TestLog::EndMessage;
1720 }
1721 
prepare(PrepareContext & context)1722 void BindImageMemory::prepare (PrepareContext& context)
1723 {
1724 	const vk::DeviceInterface&		vkd				= context.getContext().getDeviceInterface();
1725 	const vk::VkDevice				device			= context.getContext().getDevice();
1726 
1727 	VK_CHECK(vkd.bindImageMemory(device, context.getImage(), context.getMemory().getMemory(), 0));
1728 }
1729 
1730 class QueueWaitIdle : public Command
1731 {
1732 public:
QueueWaitIdle(void)1733 				QueueWaitIdle	(void) {}
~QueueWaitIdle(void)1734 				~QueueWaitIdle	(void) {}
getName(void) const1735 	const char*	getName			(void) const { return "QueuetWaitIdle"; }
1736 
1737 	void		logExecute		(TestLog& log, size_t commandIndex) const;
1738 	void		execute			(ExecuteContext& context);
1739 };
1740 
logExecute(TestLog & log,size_t commandIndex) const1741 void QueueWaitIdle::logExecute (TestLog& log, size_t commandIndex) const
1742 {
1743 	log << TestLog::Message << commandIndex << ":" << getName() << " Queue wait idle" << TestLog::EndMessage;
1744 }
1745 
execute(ExecuteContext & context)1746 void QueueWaitIdle::execute (ExecuteContext& context)
1747 {
1748 	const vk::DeviceInterface&	vkd		= context.getContext().getDeviceInterface();
1749 	const vk::VkQueue			queue	= context.getContext().getQueue();
1750 
1751 	VK_CHECK(vkd.queueWaitIdle(queue));
1752 }
1753 
1754 class DeviceWaitIdle : public Command
1755 {
1756 public:
DeviceWaitIdle(void)1757 				DeviceWaitIdle	(void) {}
~DeviceWaitIdle(void)1758 				~DeviceWaitIdle	(void) {}
getName(void) const1759 	const char*	getName			(void) const { return "DeviceWaitIdle"; }
1760 
1761 	void		logExecute		(TestLog& log, size_t commandIndex) const;
1762 	void		execute			(ExecuteContext& context);
1763 };
1764 
logExecute(TestLog & log,size_t commandIndex) const1765 void DeviceWaitIdle::logExecute (TestLog& log, size_t commandIndex) const
1766 {
1767 	log << TestLog::Message << commandIndex << ":" << getName() << " Device wait idle" << TestLog::EndMessage;
1768 }
1769 
execute(ExecuteContext & context)1770 void DeviceWaitIdle::execute (ExecuteContext& context)
1771 {
1772 	const vk::DeviceInterface&	vkd		= context.getContext().getDeviceInterface();
1773 	const vk::VkDevice			device	= context.getContext().getDevice();
1774 
1775 	VK_CHECK(vkd.deviceWaitIdle(device));
1776 }
1777 
1778 class SubmitContext
1779 {
1780 public:
SubmitContext(const PrepareContext & context,const vk::VkCommandBuffer commandBuffer)1781 								SubmitContext		(const PrepareContext&		context,
1782 													 const vk::VkCommandBuffer	commandBuffer)
1783 		: m_context			(context)
1784 		, m_commandBuffer	(commandBuffer)
1785 	{
1786 	}
1787 
getMemory(void) const1788 	const Memory&				getMemory			(void) const { return m_context.getMemory(); }
getContext(void) const1789 	const Context&				getContext			(void) const { return m_context.getContext(); }
getCommandBuffer(void) const1790 	vk::VkCommandBuffer			getCommandBuffer	(void) const { return m_commandBuffer; }
1791 
getBuffer(void) const1792 	vk::VkBuffer				getBuffer			(void) const { return m_context.getBuffer(); }
getBufferSize(void) const1793 	vk::VkDeviceSize			getBufferSize		(void) const { return m_context.getBufferSize(); }
1794 
getImage(void) const1795 	vk::VkImage					getImage			(void) const { return m_context.getImage(); }
getImageWidth(void) const1796 	deInt32						getImageWidth		(void) const { return m_context.getImageWidth(); }
getImageHeight(void) const1797 	deInt32						getImageHeight		(void) const { return m_context.getImageHeight(); }
1798 
1799 private:
1800 	const PrepareContext&		m_context;
1801 	const vk::VkCommandBuffer	m_commandBuffer;
1802 };
1803 
1804 class CmdCommand
1805 {
1806 public:
~CmdCommand(void)1807 	virtual				~CmdCommand	(void) {}
1808 	virtual const char*	getName		(void) const = 0;
1809 
1810 	// Log things that are done during prepare
logPrepare(TestLog &,size_t) const1811 	virtual void		logPrepare	(TestLog&, size_t) const {}
1812 	// Log submitted calls etc.
logSubmit(TestLog &,size_t) const1813 	virtual void		logSubmit	(TestLog&, size_t) const {}
1814 
1815 	// Allocate vulkan resources and prepare for submit.
prepare(PrepareContext &)1816 	virtual void		prepare		(PrepareContext&) {}
1817 
1818 	// Submit commands to command buffer.
submit(SubmitContext &)1819 	virtual void		submit		(SubmitContext&) {}
1820 
1821 	// Verify results
verify(VerifyContext &,size_t)1822 	virtual void		verify		(VerifyContext&, size_t) {}
1823 };
1824 
1825 class SubmitCommandBuffer : public Command
1826 {
1827 public:
1828 					SubmitCommandBuffer		(const vector<CmdCommand*>& commands);
1829 					~SubmitCommandBuffer	(void);
1830 
getName(void) const1831 	const char*		getName					(void) const { return "SubmitCommandBuffer"; }
1832 	void			logExecute				(TestLog& log, size_t commandIndex) const;
1833 	void			logPrepare				(TestLog& log, size_t commandIndex) const;
1834 
1835 	// Allocate command buffer and submit commands to command buffer
1836 	void			prepare					(PrepareContext& context);
1837 	void			execute					(ExecuteContext& context);
1838 
1839 	// Verify that results are correct.
1840 	void			verify					(VerifyContext& context, size_t commandIndex);
1841 
1842 private:
1843 	vector<CmdCommand*>				m_commands;
1844 	vk::Move<vk::VkCommandBuffer>	m_commandBuffer;
1845 };
1846 
SubmitCommandBuffer(const vector<CmdCommand * > & commands)1847 SubmitCommandBuffer::SubmitCommandBuffer (const vector<CmdCommand*>& commands)
1848 	: m_commands	(commands)
1849 {
1850 }
1851 
~SubmitCommandBuffer(void)1852 SubmitCommandBuffer::~SubmitCommandBuffer (void)
1853 {
1854 	for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
1855 		delete m_commands[cmdNdx];
1856 }
1857 
prepare(PrepareContext & context)1858 void SubmitCommandBuffer::prepare (PrepareContext& context)
1859 {
1860 	const vk::DeviceInterface&	vkd			= context.getContext().getDeviceInterface();
1861 	const vk::VkDevice			device		= context.getContext().getDevice();
1862 	const vk::VkCommandPool		commandPool	= context.getContext().getCommandPool();
1863 
1864 	m_commandBuffer = createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1865 
1866 	for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
1867 	{
1868 		CmdCommand& command = *m_commands[cmdNdx];
1869 
1870 		command.prepare(context);
1871 	}
1872 
1873 	{
1874 		SubmitContext submitContext (context, *m_commandBuffer);
1875 
1876 		for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
1877 		{
1878 			CmdCommand& command = *m_commands[cmdNdx];
1879 
1880 			command.submit(submitContext);
1881 		}
1882 
1883 		VK_CHECK(vkd.endCommandBuffer(*m_commandBuffer));
1884 	}
1885 }
1886 
execute(ExecuteContext & context)1887 void SubmitCommandBuffer::execute (ExecuteContext& context)
1888 {
1889 	const vk::DeviceInterface&	vkd		= context.getContext().getDeviceInterface();
1890 	const vk::VkCommandBuffer	cmd		= *m_commandBuffer;
1891 	const vk::VkQueue			queue	= context.getContext().getQueue();
1892 	const vk::VkSubmitInfo		submit	=
1893 	{
1894 		vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1895 		DE_NULL,
1896 
1897 		0,
1898 		DE_NULL,
1899 		(const vk::VkPipelineStageFlags*)DE_NULL,
1900 
1901 		1,
1902 		&cmd,
1903 
1904 		0,
1905 		DE_NULL
1906 	};
1907 
1908 	vkd.queueSubmit(queue, 1, &submit, 0);
1909 }
1910 
verify(VerifyContext & context,size_t commandIndex)1911 void SubmitCommandBuffer::verify (VerifyContext& context, size_t commandIndex)
1912 {
1913 	const string				sectionName	(de::toString(commandIndex) + ":" + getName());
1914 	const tcu::ScopedLogSection	section		(context.getLog(), sectionName, sectionName);
1915 
1916 	for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
1917 		m_commands[cmdNdx]->verify(context, cmdNdx);
1918 }
1919 
logPrepare(TestLog & log,size_t commandIndex) const1920 void SubmitCommandBuffer::logPrepare (TestLog& log, size_t commandIndex) const
1921 {
1922 	const string				sectionName	(de::toString(commandIndex) + ":" + getName());
1923 	const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
1924 
1925 	for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
1926 		m_commands[cmdNdx]->logPrepare(log, cmdNdx);
1927 }
1928 
logExecute(TestLog & log,size_t commandIndex) const1929 void SubmitCommandBuffer::logExecute (TestLog& log, size_t commandIndex) const
1930 {
1931 	const string				sectionName	(de::toString(commandIndex) + ":" + getName());
1932 	const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
1933 
1934 	for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
1935 		m_commands[cmdNdx]->logSubmit(log, cmdNdx);
1936 }
1937 
1938 class PipelineBarrier : public CmdCommand
1939 {
1940 public:
1941 	enum Type
1942 	{
1943 		TYPE_GLOBAL = 0,
1944 		TYPE_BUFFER,
1945 		TYPE_IMAGE,
1946 		TYPE_LAST
1947 	};
1948 									PipelineBarrier		(const vk::VkPipelineStageFlags			srcStages,
1949 														 const vk::VkAccessFlags				srcAccesses,
1950 														 const vk::VkPipelineStageFlags			dstStages,
1951 														 const vk::VkAccessFlags				dstAccesses,
1952 														 Type									type,
1953 														 const tcu::Maybe<vk::VkImageLayout>	imageLayout);
~PipelineBarrier(void)1954 									~PipelineBarrier	(void) {}
getName(void) const1955 	const char*						getName				(void) const { return "PipelineBarrier"; }
1956 
1957 	void							logSubmit			(TestLog& log, size_t commandIndex) const;
1958 	void							submit				(SubmitContext& context);
1959 
1960 private:
1961 	const vk::VkPipelineStageFlags		m_srcStages;
1962 	const vk::VkAccessFlags				m_srcAccesses;
1963 	const vk::VkPipelineStageFlags		m_dstStages;
1964 	const vk::VkAccessFlags				m_dstAccesses;
1965 	const Type							m_type;
1966 	const tcu::Maybe<vk::VkImageLayout>	m_imageLayout;
1967 };
1968 
PipelineBarrier(const vk::VkPipelineStageFlags srcStages,const vk::VkAccessFlags srcAccesses,const vk::VkPipelineStageFlags dstStages,const vk::VkAccessFlags dstAccesses,Type type,const tcu::Maybe<vk::VkImageLayout> imageLayout)1969 PipelineBarrier::PipelineBarrier (const vk::VkPipelineStageFlags		srcStages,
1970 								  const vk::VkAccessFlags				srcAccesses,
1971 								  const vk::VkPipelineStageFlags		dstStages,
1972 								  const vk::VkAccessFlags				dstAccesses,
1973 								  Type									type,
1974 								  const tcu::Maybe<vk::VkImageLayout>	imageLayout)
1975 	: m_srcStages	(srcStages)
1976 	, m_srcAccesses	(srcAccesses)
1977 	, m_dstStages	(dstStages)
1978 	, m_dstAccesses	(dstAccesses)
1979 	, m_type		(type)
1980 	, m_imageLayout	(imageLayout)
1981 {
1982 }
1983 
logSubmit(TestLog & log,size_t commandIndex) const1984 void PipelineBarrier::logSubmit (TestLog& log, size_t commandIndex) const
1985 {
1986 	log << TestLog::Message << commandIndex << ":" << getName()
1987 		<< " " << (m_type == TYPE_GLOBAL ? "Global pipeline barrier"
1988 					: m_type == TYPE_BUFFER ? "Buffer pipeline barrier"
1989 					: "Image pipeline barrier")
1990 		<< ", srcStages: " << vk::getPipelineStageFlagsStr(m_srcStages) << ", srcAccesses: " << vk::getAccessFlagsStr(m_srcAccesses)
1991 		<< ", dstStages: " << vk::getPipelineStageFlagsStr(m_dstStages) << ", dstAccesses: " << vk::getAccessFlagsStr(m_dstAccesses) << TestLog::EndMessage;
1992 }
1993 
submit(SubmitContext & context)1994 void PipelineBarrier::submit (SubmitContext& context)
1995 {
1996 	const vk::DeviceInterface&	vkd	= context.getContext().getDeviceInterface();
1997 	const vk::VkCommandBuffer	cmd	= context.getCommandBuffer();
1998 
1999 	// \todo [2016-01-08 pyry] This could be cleaned up thanks to latest API changes
2000 
2001 	switch (m_type)
2002 	{
2003 		case TYPE_GLOBAL:
2004 		{
2005 			const vk::VkMemoryBarrier	barrier		=
2006 			{
2007 				vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,
2008 				DE_NULL,
2009 
2010 				m_srcAccesses,
2011 				m_dstAccesses
2012 			};
2013 
2014 			vkd.cmdPipelineBarrier(cmd, m_srcStages, m_dstStages, (vk::VkDependencyFlags)0, 1, &barrier, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
2015 			break;
2016 		}
2017 
2018 		case TYPE_BUFFER:
2019 		{
2020 			const vk::VkBufferMemoryBarrier	barrier		=
2021 			{
2022 				vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2023 				DE_NULL,
2024 
2025 				m_srcAccesses,
2026 				m_dstAccesses,
2027 
2028 				vk::VK_QUEUE_FAMILY_IGNORED,
2029 				vk::VK_QUEUE_FAMILY_IGNORED,
2030 
2031 				context.getBuffer(),
2032 				0,
2033 				vk::VK_WHOLE_SIZE
2034 			};
2035 
2036 			vkd.cmdPipelineBarrier(cmd, m_srcStages, m_dstStages, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 1, &barrier, 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
2037 			break;
2038 		}
2039 
2040 		case TYPE_IMAGE:
2041 		{
2042 			const vk::VkImageMemoryBarrier	barrier		=
2043 			{
2044 				vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2045 				DE_NULL,
2046 
2047 				m_srcAccesses,
2048 				m_dstAccesses,
2049 
2050 				*m_imageLayout,
2051 				*m_imageLayout,
2052 
2053 				vk::VK_QUEUE_FAMILY_IGNORED,
2054 				vk::VK_QUEUE_FAMILY_IGNORED,
2055 
2056 				context.getImage(),
2057 				{
2058 					vk::VK_IMAGE_ASPECT_COLOR_BIT,
2059 					0, 1,
2060 					0, 1
2061 				}
2062 			};
2063 
2064 			vkd.cmdPipelineBarrier(cmd, m_srcStages, m_dstStages, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
2065 			break;
2066 		}
2067 
2068 		default:
2069 			DE_FATAL("Unknown pipeline barrier type");
2070 	}
2071 }
2072 
2073 class ImageTransition : public CmdCommand
2074 {
2075 public:
2076 						ImageTransition		(vk::VkPipelineStageFlags	srcStages,
2077 											 vk::VkAccessFlags			srcAccesses,
2078 
2079 											 vk::VkPipelineStageFlags	dstStages,
2080 											 vk::VkAccessFlags			dstAccesses,
2081 
2082 											 vk::VkImageLayout			srcLayout,
2083 											 vk::VkImageLayout			dstLayout);
2084 
~ImageTransition(void)2085 						~ImageTransition	(void) {}
getName(void) const2086 	const char*			getName				(void) const { return "ImageTransition"; }
2087 
2088 	void				prepare				(PrepareContext& context);
2089 	void				logSubmit			(TestLog& log, size_t commandIndex) const;
2090 	void				submit				(SubmitContext& context);
2091 	void				verify				(VerifyContext& context, size_t);
2092 
2093 private:
2094 	const vk::VkPipelineStageFlags	m_srcStages;
2095 	const vk::VkAccessFlags			m_srcAccesses;
2096 	const vk::VkPipelineStageFlags	m_dstStages;
2097 	const vk::VkAccessFlags			m_dstAccesses;
2098 	const vk::VkImageLayout			m_srcLayout;
2099 	const vk::VkImageLayout			m_dstLayout;
2100 
2101 	vk::VkDeviceSize				m_imageMemorySize;
2102 };
2103 
ImageTransition(vk::VkPipelineStageFlags srcStages,vk::VkAccessFlags srcAccesses,vk::VkPipelineStageFlags dstStages,vk::VkAccessFlags dstAccesses,vk::VkImageLayout srcLayout,vk::VkImageLayout dstLayout)2104 ImageTransition::ImageTransition (vk::VkPipelineStageFlags	srcStages,
2105 								  vk::VkAccessFlags			srcAccesses,
2106 
2107 								  vk::VkPipelineStageFlags	dstStages,
2108 								  vk::VkAccessFlags			dstAccesses,
2109 
2110 								  vk::VkImageLayout			srcLayout,
2111 								  vk::VkImageLayout			dstLayout)
2112 	: m_srcStages		(srcStages)
2113 	, m_srcAccesses		(srcAccesses)
2114 	, m_dstStages		(dstStages)
2115 	, m_dstAccesses		(dstAccesses)
2116 	, m_srcLayout		(srcLayout)
2117 	, m_dstLayout		(dstLayout)
2118 {
2119 }
2120 
logSubmit(TestLog & log,size_t commandIndex) const2121 void ImageTransition::logSubmit (TestLog& log, size_t commandIndex) const
2122 {
2123 	log << TestLog::Message << commandIndex << ":" << getName()
2124 		<< " Image transition pipeline barrier"
2125 		<< ", srcStages: " << vk::getPipelineStageFlagsStr(m_srcStages) << ", srcAccesses: " << vk::getAccessFlagsStr(m_srcAccesses)
2126 		<< ", dstStages: " << vk::getPipelineStageFlagsStr(m_dstStages) << ", dstAccesses: " << vk::getAccessFlagsStr(m_dstAccesses)
2127 		<< ", srcLayout: " << m_srcLayout << ", dstLayout: " << m_dstLayout << TestLog::EndMessage;
2128 }
2129 
prepare(PrepareContext & context)2130 void ImageTransition::prepare (PrepareContext& context)
2131 {
2132 	DE_ASSERT(context.getImageLayout() == vk::VK_IMAGE_LAYOUT_UNDEFINED || m_srcLayout == vk::VK_IMAGE_LAYOUT_UNDEFINED || context.getImageLayout() == m_srcLayout);
2133 
2134 	context.setImageLayout(m_dstLayout);
2135 	m_imageMemorySize = context.getImageMemorySize();
2136 }
2137 
submit(SubmitContext & context)2138 void ImageTransition::submit (SubmitContext& context)
2139 {
2140 	const vk::DeviceInterface&		vkd			= context.getContext().getDeviceInterface();
2141 	const vk::VkCommandBuffer		cmd			= context.getCommandBuffer();
2142 	const vk::VkImageMemoryBarrier	barrier		=
2143 	{
2144 		vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2145 		DE_NULL,
2146 
2147 		m_srcAccesses,
2148 		m_dstAccesses,
2149 
2150 		m_srcLayout,
2151 		m_dstLayout,
2152 
2153 		vk::VK_QUEUE_FAMILY_IGNORED,
2154 		vk::VK_QUEUE_FAMILY_IGNORED,
2155 
2156 		context.getImage(),
2157 		{
2158 			vk::VK_IMAGE_ASPECT_COLOR_BIT,
2159 			0u, 1u,
2160 			0u, 1u
2161 		}
2162 	};
2163 
2164 	vkd.cmdPipelineBarrier(cmd, m_srcStages, m_dstStages, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
2165 }
2166 
verify(VerifyContext & context,size_t)2167 void ImageTransition::verify (VerifyContext& context, size_t)
2168 {
2169 	context.getReference().setUndefined(0, (size_t)m_imageMemorySize);
2170 }
2171 
2172 class FillBuffer : public CmdCommand
2173 {
2174 public:
FillBuffer(deUint32 value)2175 						FillBuffer	(deUint32 value) : m_value(value) {}
~FillBuffer(void)2176 						~FillBuffer	(void) {}
getName(void) const2177 	const char*			getName		(void) const { return "FillBuffer"; }
2178 
2179 	void				logSubmit	(TestLog& log, size_t commandIndex) const;
2180 	void				submit		(SubmitContext& context);
2181 	void				verify		(VerifyContext& context, size_t commandIndex);
2182 
2183 private:
2184 	const deUint32		m_value;
2185 	vk::VkDeviceSize	m_bufferSize;
2186 };
2187 
logSubmit(TestLog & log,size_t commandIndex) const2188 void FillBuffer::logSubmit (TestLog& log, size_t commandIndex) const
2189 {
2190 	log << TestLog::Message << commandIndex << ":" << getName() << " Fill value: " << m_value << TestLog::EndMessage;
2191 }
2192 
submit(SubmitContext & context)2193 void FillBuffer::submit (SubmitContext& context)
2194 {
2195 	const vk::DeviceInterface&	vkd			= context.getContext().getDeviceInterface();
2196 	const vk::VkCommandBuffer	cmd			= context.getCommandBuffer();
2197 	const vk::VkBuffer			buffer		= context.getBuffer();
2198 	const vk::VkDeviceSize		sizeMask	= ~(0x3ull); // \note Round down to multiple of 4
2199 
2200 	m_bufferSize = sizeMask & context.getBufferSize();
2201 	vkd.cmdFillBuffer(cmd, buffer, 0, m_bufferSize, m_value);
2202 }
2203 
verify(VerifyContext & context,size_t)2204 void FillBuffer::verify (VerifyContext& context, size_t)
2205 {
2206 	ReferenceMemory&	reference	= context.getReference();
2207 
2208 	for (size_t ndx = 0; ndx < m_bufferSize; ndx++)
2209 	{
2210 #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
2211 		reference.set(ndx, (deUint8)(0xffu & (m_value >> (8*(ndx % 4)))));
2212 #else
2213 		reference.set(ndx, (deUint8)(0xffu & (m_value >> (8*(3 - (ndx % 4))))));
2214 #endif
2215 	}
2216 }
2217 
2218 class UpdateBuffer : public CmdCommand
2219 {
2220 public:
UpdateBuffer(deUint32 seed)2221 						UpdateBuffer	(deUint32 seed) : m_seed(seed) {}
~UpdateBuffer(void)2222 						~UpdateBuffer	(void) {}
getName(void) const2223 	const char*			getName			(void) const { return "UpdateBuffer"; }
2224 
2225 	void				logSubmit		(TestLog& log, size_t commandIndex) const;
2226 	void				submit			(SubmitContext& context);
2227 	void				verify			(VerifyContext& context, size_t commandIndex);
2228 
2229 private:
2230 	const deUint32		m_seed;
2231 	vk::VkDeviceSize	m_bufferSize;
2232 };
2233 
logSubmit(TestLog & log,size_t commandIndex) const2234 void UpdateBuffer::logSubmit (TestLog& log, size_t commandIndex) const
2235 {
2236 	log << TestLog::Message << commandIndex << ":" << getName() << " Update buffer, seed: " << m_seed << TestLog::EndMessage;
2237 }
2238 
submit(SubmitContext & context)2239 void UpdateBuffer::submit (SubmitContext& context)
2240 {
2241 	const vk::DeviceInterface&	vkd			= context.getContext().getDeviceInterface();
2242 	const vk::VkCommandBuffer	cmd			= context.getCommandBuffer();
2243 	const vk::VkBuffer			buffer		= context.getBuffer();
2244 	const size_t				blockSize	= 65536;
2245 	std::vector<deUint8>		data		(blockSize, 0);
2246 	de::Random					rng			(m_seed);
2247 
2248 	m_bufferSize = context.getBufferSize();
2249 
2250 	for (size_t updated = 0; updated < m_bufferSize; updated += blockSize)
2251 	{
2252 		for (size_t ndx = 0; ndx < data.size(); ndx++)
2253 			data[ndx] = rng.getUint8();
2254 
2255 		if (m_bufferSize - updated > blockSize)
2256 			vkd.cmdUpdateBuffer(cmd, buffer, updated, blockSize, (const deUint32*)(&data[0]));
2257 		else
2258 			vkd.cmdUpdateBuffer(cmd, buffer, updated, m_bufferSize - updated, (const deUint32*)(&data[0]));
2259 	}
2260 }
2261 
verify(VerifyContext & context,size_t)2262 void UpdateBuffer::verify (VerifyContext& context, size_t)
2263 {
2264 	ReferenceMemory&	reference	= context.getReference();
2265 	const size_t		blockSize	= 65536;
2266 	vector<deUint8>		data		(blockSize, 0);
2267 	de::Random			rng			(m_seed);
2268 
2269 	for (size_t updated = 0; updated < m_bufferSize; updated += blockSize)
2270 	{
2271 		for (size_t ndx = 0; ndx < data.size(); ndx++)
2272 			data[ndx] = rng.getUint8();
2273 
2274 		if (m_bufferSize - updated > blockSize)
2275 			reference.setData(updated, blockSize, &data[0]);
2276 		else
2277 			reference.setData(updated, (size_t)(m_bufferSize - updated), &data[0]);
2278 	}
2279 }
2280 
2281 class BufferCopyToBuffer : public CmdCommand
2282 {
2283 public:
BufferCopyToBuffer(void)2284 									BufferCopyToBuffer	(void) {}
~BufferCopyToBuffer(void)2285 									~BufferCopyToBuffer	(void) {}
getName(void) const2286 	const char*						getName				(void) const { return "BufferCopyToBuffer"; }
2287 
2288 	void							logPrepare			(TestLog& log, size_t commandIndex) const;
2289 	void							prepare				(PrepareContext& context);
2290 	void							logSubmit			(TestLog& log, size_t commandIndex) const;
2291 	void							submit				(SubmitContext& context);
2292 	void							verify				(VerifyContext& context, size_t commandIndex);
2293 
2294 private:
2295 	vk::VkDeviceSize				m_bufferSize;
2296 	vk::Move<vk::VkBuffer>			m_dstBuffer;
2297 	vk::Move<vk::VkDeviceMemory>	m_memory;
2298 };
2299 
logPrepare(TestLog & log,size_t commandIndex) const2300 void BufferCopyToBuffer::logPrepare (TestLog& log, size_t commandIndex) const
2301 {
2302 	log << TestLog::Message << commandIndex << ":" << getName() << " Allocate destination buffer for buffer to buffer copy." << TestLog::EndMessage;
2303 }
2304 
prepare(PrepareContext & context)2305 void BufferCopyToBuffer::prepare (PrepareContext& context)
2306 {
2307 	const vk::InstanceInterface&	vki				= context.getContext().getInstanceInterface();
2308 	const vk::DeviceInterface&		vkd				= context.getContext().getDeviceInterface();
2309 	const vk::VkPhysicalDevice		physicalDevice	= context.getContext().getPhysicalDevice();
2310 	const vk::VkDevice				device			= context.getContext().getDevice();
2311 	const vector<deUint32>&			queueFamilies	= context.getContext().getQueueFamilies();
2312 
2313 	m_bufferSize = context.getBufferSize();
2314 
2315 	m_dstBuffer	= createBuffer(vkd, device, m_bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies);
2316 	m_memory	= bindBufferMemory(vki, vkd, physicalDevice, device, *m_dstBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
2317 }
2318 
logSubmit(TestLog & log,size_t commandIndex) const2319 void BufferCopyToBuffer::logSubmit (TestLog& log, size_t commandIndex) const
2320 {
2321 	log << TestLog::Message << commandIndex << ":" << getName() << " Copy buffer to another buffer" << TestLog::EndMessage;
2322 }
2323 
submit(SubmitContext & context)2324 void BufferCopyToBuffer::submit (SubmitContext& context)
2325 {
2326 	const vk::DeviceInterface&	vkd				= context.getContext().getDeviceInterface();
2327 	const vk::VkCommandBuffer	commandBuffer	= context.getCommandBuffer();
2328 	const vk::VkBufferCopy		range			=
2329 	{
2330 		0, 0, // Offsets
2331 		m_bufferSize
2332 	};
2333 
2334 	vkd.cmdCopyBuffer(commandBuffer, context.getBuffer(), *m_dstBuffer, 1, &range);
2335 }
2336 
verify(VerifyContext & context,size_t commandIndex)2337 void BufferCopyToBuffer::verify (VerifyContext& context, size_t commandIndex)
2338 {
2339 	tcu::ResultCollector&					resultCollector	(context.getResultCollector());
2340 	ReferenceMemory&						reference		(context.getReference());
2341 	const vk::DeviceInterface&				vkd				= context.getContext().getDeviceInterface();
2342 	const vk::VkDevice						device			= context.getContext().getDevice();
2343 	const vk::VkQueue						queue			= context.getContext().getQueue();
2344 	const vk::VkCommandPool					commandPool		= context.getContext().getCommandPool();
2345 	const vk::Unique<vk::VkCommandBuffer>	commandBuffer	(createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2346 	const vk::VkBufferMemoryBarrier			barrier			=
2347 	{
2348 		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2349 		DE_NULL,
2350 
2351 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2352 		vk::VK_ACCESS_HOST_READ_BIT,
2353 
2354 		vk::VK_QUEUE_FAMILY_IGNORED,
2355 		vk::VK_QUEUE_FAMILY_IGNORED,
2356 		*m_dstBuffer,
2357 		0,
2358 		vk::VK_WHOLE_SIZE
2359 	};
2360 
2361 	vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 1, &barrier, 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
2362 
2363 	VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
2364 	queueRun(vkd, queue, *commandBuffer);
2365 
2366 	{
2367 		void* const	ptr		= mapMemory(vkd, device, *m_memory, m_bufferSize);
2368 		bool		isOk	= true;
2369 
2370 		vk::invalidateMappedMemoryRange(vkd, device, *m_memory, 0, m_bufferSize);
2371 
2372 		{
2373 			const deUint8* const data = (const deUint8*)ptr;
2374 
2375 			for (size_t pos = 0; pos < (size_t)m_bufferSize; pos++)
2376 			{
2377 				if (reference.isDefined(pos))
2378 				{
2379 					if (data[pos] != reference.get(pos))
2380 					{
2381 						resultCollector.fail(
2382 								de::toString(commandIndex) + ":" + getName()
2383 								+ " Result differs from reference, Expected: "
2384 								+ de::toString(tcu::toHex<8>(reference.get(pos)))
2385 								+ ", Got: "
2386 								+ de::toString(tcu::toHex<8>(data[pos]))
2387 								+ ", At offset: "
2388 								+ de::toString(pos));
2389 						break;
2390 					}
2391 				}
2392 			}
2393 		}
2394 
2395 		vkd.unmapMemory(device, *m_memory);
2396 
2397 		if (!isOk)
2398 			context.getLog() << TestLog::Message << commandIndex << ": Buffer copy to buffer verification failed" << TestLog::EndMessage;
2399 	}
2400 }
2401 
2402 class BufferCopyFromBuffer : public CmdCommand
2403 {
2404 public:
BufferCopyFromBuffer(deUint32 seed)2405 									BufferCopyFromBuffer	(deUint32 seed) : m_seed(seed) {}
~BufferCopyFromBuffer(void)2406 									~BufferCopyFromBuffer	(void) {}
getName(void) const2407 	const char*						getName					(void) const { return "BufferCopyFromBuffer"; }
2408 
2409 	void							logPrepare				(TestLog& log, size_t commandIndex) const;
2410 	void							prepare					(PrepareContext& context);
2411 	void							logSubmit				(TestLog& log, size_t commandIndex) const;
2412 	void							submit					(SubmitContext& context);
2413 	void							verify					(VerifyContext& context, size_t commandIndex);
2414 
2415 private:
2416 	const deUint32					m_seed;
2417 	vk::VkDeviceSize				m_bufferSize;
2418 	vk::Move<vk::VkBuffer>			m_srcBuffer;
2419 	vk::Move<vk::VkDeviceMemory>	m_memory;
2420 };
2421 
logPrepare(TestLog & log,size_t commandIndex) const2422 void BufferCopyFromBuffer::logPrepare (TestLog& log, size_t commandIndex) const
2423 {
2424 	log << TestLog::Message << commandIndex << ":" << getName() << " Allocate source buffer for buffer to buffer copy. Seed: " << m_seed << TestLog::EndMessage;
2425 }
2426 
prepare(PrepareContext & context)2427 void BufferCopyFromBuffer::prepare (PrepareContext& context)
2428 {
2429 	const vk::InstanceInterface&	vki				= context.getContext().getInstanceInterface();
2430 	const vk::DeviceInterface&		vkd				= context.getContext().getDeviceInterface();
2431 	const vk::VkPhysicalDevice		physicalDevice	= context.getContext().getPhysicalDevice();
2432 	const vk::VkDevice				device			= context.getContext().getDevice();
2433 	const vector<deUint32>&			queueFamilies	= context.getContext().getQueueFamilies();
2434 
2435 	m_bufferSize	= context.getBufferSize();
2436 	m_srcBuffer		= createBuffer(vkd, device, m_bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies);
2437 	m_memory		= bindBufferMemory(vki, vkd, physicalDevice, device, *m_srcBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
2438 
2439 	{
2440 		void* const	ptr	= mapMemory(vkd, device, *m_memory, m_bufferSize);
2441 		de::Random	rng	(m_seed);
2442 
2443 		{
2444 			deUint8* const	data = (deUint8*)ptr;
2445 
2446 			for (size_t ndx = 0; ndx < (size_t)m_bufferSize; ndx++)
2447 				data[ndx] = rng.getUint8();
2448 		}
2449 
2450 		vk::flushMappedMemoryRange(vkd, device, *m_memory, 0, m_bufferSize);
2451 		vkd.unmapMemory(device, *m_memory);
2452 	}
2453 }
2454 
logSubmit(TestLog & log,size_t commandIndex) const2455 void BufferCopyFromBuffer::logSubmit (TestLog& log, size_t commandIndex) const
2456 {
2457 	log << TestLog::Message << commandIndex << ":" << getName() << " Copy buffer data from another buffer" << TestLog::EndMessage;
2458 }
2459 
submit(SubmitContext & context)2460 void BufferCopyFromBuffer::submit (SubmitContext& context)
2461 {
2462 	const vk::DeviceInterface&	vkd				= context.getContext().getDeviceInterface();
2463 	const vk::VkCommandBuffer	commandBuffer	= context.getCommandBuffer();
2464 	const vk::VkBufferCopy		range			=
2465 	{
2466 		0, 0, // Offsets
2467 		m_bufferSize
2468 	};
2469 
2470 	vkd.cmdCopyBuffer(commandBuffer, *m_srcBuffer, context.getBuffer(), 1, &range);
2471 }
2472 
verify(VerifyContext & context,size_t)2473 void BufferCopyFromBuffer::verify (VerifyContext& context, size_t)
2474 {
2475 	ReferenceMemory&	reference	(context.getReference());
2476 	de::Random			rng			(m_seed);
2477 
2478 	for (size_t ndx = 0; ndx < (size_t)m_bufferSize; ndx++)
2479 		reference.set(ndx, rng.getUint8());
2480 }
2481 
2482 class BufferCopyToImage : public CmdCommand
2483 {
2484 public:
BufferCopyToImage(void)2485 									BufferCopyToImage	(void) {}
~BufferCopyToImage(void)2486 									~BufferCopyToImage	(void) {}
getName(void) const2487 	const char*						getName				(void) const { return "BufferCopyToImage"; }
2488 
2489 	void							logPrepare			(TestLog& log, size_t commandIndex) const;
2490 	void							prepare				(PrepareContext& context);
2491 	void							logSubmit			(TestLog& log, size_t commandIndex) const;
2492 	void							submit				(SubmitContext& context);
2493 	void							verify				(VerifyContext& context, size_t commandIndex);
2494 
2495 private:
2496 	deInt32							m_imageWidth;
2497 	deInt32							m_imageHeight;
2498 	vk::Move<vk::VkImage>			m_dstImage;
2499 	vk::Move<vk::VkDeviceMemory>	m_memory;
2500 };
2501 
logPrepare(TestLog & log,size_t commandIndex) const2502 void BufferCopyToImage::logPrepare (TestLog& log, size_t commandIndex) const
2503 {
2504 	log << TestLog::Message << commandIndex << ":" << getName() << " Allocate destination image for buffer to image copy." << TestLog::EndMessage;
2505 }
2506 
prepare(PrepareContext & context)2507 void BufferCopyToImage::prepare (PrepareContext& context)
2508 {
2509 	const vk::InstanceInterface&	vki				= context.getContext().getInstanceInterface();
2510 	const vk::DeviceInterface&		vkd				= context.getContext().getDeviceInterface();
2511 	const vk::VkPhysicalDevice		physicalDevice	= context.getContext().getPhysicalDevice();
2512 	const vk::VkDevice				device			= context.getContext().getDevice();
2513 	const vk::VkQueue				queue			= context.getContext().getQueue();
2514 	const vk::VkCommandPool			commandPool		= context.getContext().getCommandPool();
2515 	const vector<deUint32>&			queueFamilies	= context.getContext().getQueueFamilies();
2516 	const IVec2						imageSize		= findImageSizeWxHx4(context.getBufferSize());
2517 
2518 	m_imageWidth	= imageSize[0];
2519 	m_imageHeight	= imageSize[1];
2520 
2521 	{
2522 		const vk::VkImageCreateInfo	createInfo =
2523 		{
2524 			vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
2525 			DE_NULL,
2526 
2527 			0,
2528 			vk::VK_IMAGE_TYPE_2D,
2529 			vk::VK_FORMAT_R8G8B8A8_UNORM,
2530 			{
2531 				(deUint32)m_imageWidth,
2532 				(deUint32)m_imageHeight,
2533 				1u,
2534 			},
2535 			1, 1, // mipLevels, arrayLayers
2536 			vk::VK_SAMPLE_COUNT_1_BIT,
2537 
2538 			vk::VK_IMAGE_TILING_OPTIMAL,
2539 			vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
2540 			vk::VK_SHARING_MODE_EXCLUSIVE,
2541 
2542 			(deUint32)queueFamilies.size(),
2543 			&queueFamilies[0],
2544 			vk::VK_IMAGE_LAYOUT_UNDEFINED
2545 		};
2546 
2547 		m_dstImage = vk::createImage(vkd, device, &createInfo);
2548 	}
2549 
2550 	m_memory = bindImageMemory(vki, vkd, physicalDevice, device, *m_dstImage, 0);
2551 
2552 	{
2553 		const vk::Unique<vk::VkCommandBuffer>	commandBuffer	(createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2554 		const vk::VkImageMemoryBarrier			barrier			=
2555 		{
2556 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2557 			DE_NULL,
2558 
2559 			0,
2560 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2561 
2562 			vk::VK_IMAGE_LAYOUT_UNDEFINED,
2563 			vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2564 
2565 			vk::VK_QUEUE_FAMILY_IGNORED,
2566 			vk::VK_QUEUE_FAMILY_IGNORED,
2567 
2568 			*m_dstImage,
2569 			{
2570 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
2571 				0,	// Mip level
2572 				1,	// Mip level count
2573 				0,	// Layer
2574 				1	// Layer count
2575 			}
2576 		};
2577 
2578 		vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
2579 
2580 		VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
2581 		queueRun(vkd, queue, *commandBuffer);
2582 	}
2583 }
2584 
logSubmit(TestLog & log,size_t commandIndex) const2585 void BufferCopyToImage::logSubmit (TestLog& log, size_t commandIndex) const
2586 {
2587 	log << TestLog::Message << commandIndex << ":" << getName() << " Copy buffer to image" << TestLog::EndMessage;
2588 }
2589 
submit(SubmitContext & context)2590 void BufferCopyToImage::submit (SubmitContext& context)
2591 {
2592 	const vk::DeviceInterface&	vkd				= context.getContext().getDeviceInterface();
2593 	const vk::VkCommandBuffer	commandBuffer	= context.getCommandBuffer();
2594 	const vk::VkBufferImageCopy	region			=
2595 	{
2596 		0,
2597 		0, 0,
2598 		{
2599 			vk::VK_IMAGE_ASPECT_COLOR_BIT,
2600 			0,	// mipLevel
2601 			0,	// arrayLayer
2602 			1	// layerCount
2603 		},
2604 		{ 0, 0, 0 },
2605 		{
2606 			(deUint32)m_imageWidth,
2607 			(deUint32)m_imageHeight,
2608 			1u
2609 		}
2610 	};
2611 
2612 	vkd.cmdCopyBufferToImage(commandBuffer, context.getBuffer(), *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
2613 }
2614 
verify(VerifyContext & context,size_t commandIndex)2615 void BufferCopyToImage::verify (VerifyContext& context, size_t commandIndex)
2616 {
2617 	tcu::ResultCollector&					resultCollector	(context.getResultCollector());
2618 	ReferenceMemory&						reference		(context.getReference());
2619 	const vk::InstanceInterface&			vki				= context.getContext().getInstanceInterface();
2620 	const vk::DeviceInterface&				vkd				= context.getContext().getDeviceInterface();
2621 	const vk::VkPhysicalDevice				physicalDevice	= context.getContext().getPhysicalDevice();
2622 	const vk::VkDevice						device			= context.getContext().getDevice();
2623 	const vk::VkQueue						queue			= context.getContext().getQueue();
2624 	const vk::VkCommandPool					commandPool		= context.getContext().getCommandPool();
2625 	const vk::Unique<vk::VkCommandBuffer>	commandBuffer	(createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2626 	const vector<deUint32>&					queueFamilies	= context.getContext().getQueueFamilies();
2627 	const vk::Unique<vk::VkBuffer>			dstBuffer		(createBuffer(vkd, device, 4 * m_imageWidth * m_imageHeight, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies));
2628 	const vk::Unique<vk::VkDeviceMemory>	memory			(bindBufferMemory(vki, vkd, physicalDevice, device, *dstBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
2629 	{
2630 		const vk::VkImageMemoryBarrier		imageBarrier	=
2631 		{
2632 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2633 			DE_NULL,
2634 
2635 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2636 			vk::VK_ACCESS_TRANSFER_READ_BIT,
2637 
2638 			vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2639 			vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2640 
2641 			vk::VK_QUEUE_FAMILY_IGNORED,
2642 			vk::VK_QUEUE_FAMILY_IGNORED,
2643 
2644 			*m_dstImage,
2645 			{
2646 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
2647 				0,	// Mip level
2648 				1,	// Mip level count
2649 				0,	// Layer
2650 				1	// Layer count
2651 			}
2652 		};
2653 		const vk::VkBufferMemoryBarrier bufferBarrier =
2654 		{
2655 			vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2656 			DE_NULL,
2657 
2658 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2659 			vk::VK_ACCESS_HOST_READ_BIT,
2660 
2661 			vk::VK_QUEUE_FAMILY_IGNORED,
2662 			vk::VK_QUEUE_FAMILY_IGNORED,
2663 			*dstBuffer,
2664 			0,
2665 			vk::VK_WHOLE_SIZE
2666 		};
2667 
2668 		const vk::VkBufferImageCopy	region =
2669 		{
2670 			0,
2671 			0, 0,
2672 			{
2673 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
2674 				0,	// mipLevel
2675 				0,	// arrayLayer
2676 				1	// layerCount
2677 			},
2678 			{ 0, 0, 0 },
2679 			{
2680 				(deUint32)m_imageWidth,
2681 				(deUint32)m_imageHeight,
2682 				1u
2683 			}
2684 		};
2685 
2686 		vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &imageBarrier);
2687 		vkd.cmdCopyImageToBuffer(*commandBuffer, *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dstBuffer, 1, &region);
2688 		vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
2689 	}
2690 
2691 	VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
2692 	queueRun(vkd, queue, *commandBuffer);
2693 
2694 	{
2695 		void* const	ptr		= mapMemory(vkd, device, *memory, 4 * m_imageWidth * m_imageHeight);
2696 
2697 		vk::invalidateMappedMemoryRange(vkd, device, *memory, 0,  4 * m_imageWidth * m_imageHeight);
2698 
2699 		{
2700 			const deUint8* const	data = (const deUint8*)ptr;
2701 
2702 			for (size_t pos = 0; pos < (size_t)( 4 * m_imageWidth * m_imageHeight); pos++)
2703 			{
2704 				if (reference.isDefined(pos))
2705 				{
2706 					if (data[pos] != reference.get(pos))
2707 					{
2708 						resultCollector.fail(
2709 								de::toString(commandIndex) + ":" + getName()
2710 								+ " Result differs from reference, Expected: "
2711 								+ de::toString(tcu::toHex<8>(reference.get(pos)))
2712 								+ ", Got: "
2713 								+ de::toString(tcu::toHex<8>(data[pos]))
2714 								+ ", At offset: "
2715 								+ de::toString(pos));
2716 						break;
2717 					}
2718 				}
2719 			}
2720 		}
2721 
2722 		vkd.unmapMemory(device, *memory);
2723 	}
2724 }
2725 
2726 class BufferCopyFromImage : public CmdCommand
2727 {
2728 public:
BufferCopyFromImage(deUint32 seed)2729 									BufferCopyFromImage		(deUint32 seed) : m_seed(seed) {}
~BufferCopyFromImage(void)2730 									~BufferCopyFromImage	(void) {}
getName(void) const2731 	const char*						getName					(void) const { return "BufferCopyFromImage"; }
2732 
2733 	void							logPrepare				(TestLog& log, size_t commandIndex) const;
2734 	void							prepare					(PrepareContext& context);
2735 	void							logSubmit				(TestLog& log, size_t commandIndex) const;
2736 	void							submit					(SubmitContext& context);
2737 	void							verify					(VerifyContext& context, size_t commandIndex);
2738 
2739 private:
2740 	const deUint32					m_seed;
2741 	deInt32							m_imageWidth;
2742 	deInt32							m_imageHeight;
2743 	vk::Move<vk::VkImage>			m_srcImage;
2744 	vk::Move<vk::VkDeviceMemory>	m_memory;
2745 };
2746 
logPrepare(TestLog & log,size_t commandIndex) const2747 void BufferCopyFromImage::logPrepare (TestLog& log, size_t commandIndex) const
2748 {
2749 	log << TestLog::Message << commandIndex << ":" << getName() << " Allocate source image for image to buffer copy." << TestLog::EndMessage;
2750 }
2751 
prepare(PrepareContext & context)2752 void BufferCopyFromImage::prepare (PrepareContext& context)
2753 {
2754 	const vk::InstanceInterface&	vki				= context.getContext().getInstanceInterface();
2755 	const vk::DeviceInterface&		vkd				= context.getContext().getDeviceInterface();
2756 	const vk::VkPhysicalDevice		physicalDevice	= context.getContext().getPhysicalDevice();
2757 	const vk::VkDevice				device			= context.getContext().getDevice();
2758 	const vk::VkQueue				queue			= context.getContext().getQueue();
2759 	const vk::VkCommandPool			commandPool		= context.getContext().getCommandPool();
2760 	const vector<deUint32>&			queueFamilies	= context.getContext().getQueueFamilies();
2761 	const IVec2						imageSize		= findImageSizeWxHx4(context.getBufferSize());
2762 
2763 	m_imageWidth	= imageSize[0];
2764 	m_imageHeight	= imageSize[1];
2765 
2766 	{
2767 		const vk::VkImageCreateInfo	createInfo =
2768 		{
2769 			vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
2770 			DE_NULL,
2771 
2772 			0,
2773 			vk::VK_IMAGE_TYPE_2D,
2774 			vk::VK_FORMAT_R8G8B8A8_UNORM,
2775 			{
2776 				(deUint32)m_imageWidth,
2777 				(deUint32)m_imageHeight,
2778 				1u,
2779 			},
2780 			1, 1, // mipLevels, arrayLayers
2781 			vk::VK_SAMPLE_COUNT_1_BIT,
2782 
2783 			vk::VK_IMAGE_TILING_OPTIMAL,
2784 			vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
2785 			vk::VK_SHARING_MODE_EXCLUSIVE,
2786 
2787 			(deUint32)queueFamilies.size(),
2788 			&queueFamilies[0],
2789 			vk::VK_IMAGE_LAYOUT_UNDEFINED
2790 		};
2791 
2792 		m_srcImage = vk::createImage(vkd, device, &createInfo);
2793 	}
2794 
2795 	m_memory = bindImageMemory(vki, vkd, physicalDevice, device, *m_srcImage, 0);
2796 
2797 	{
2798 		const vk::Unique<vk::VkBuffer>			srcBuffer		(createBuffer(vkd, device, 4 * m_imageWidth * m_imageHeight, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies));
2799 		const vk::Unique<vk::VkDeviceMemory>	memory			(bindBufferMemory(vki, vkd, physicalDevice, device, *srcBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
2800 		const vk::Unique<vk::VkCommandBuffer>	commandBuffer	(createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2801 		const vk::VkImageMemoryBarrier			preImageBarrier	=
2802 		{
2803 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2804 			DE_NULL,
2805 
2806 			0,
2807 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2808 
2809 			vk::VK_IMAGE_LAYOUT_UNDEFINED,
2810 			vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2811 
2812 			vk::VK_QUEUE_FAMILY_IGNORED,
2813 			vk::VK_QUEUE_FAMILY_IGNORED,
2814 
2815 			*m_srcImage,
2816 			{
2817 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
2818 				0,	// Mip level
2819 				1,	// Mip level count
2820 				0,	// Layer
2821 				1	// Layer count
2822 			}
2823 		};
2824 		const vk::VkImageMemoryBarrier			postImageBarrier =
2825 		{
2826 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2827 			DE_NULL,
2828 
2829 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2830 			0,
2831 
2832 			vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2833 			vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2834 
2835 			vk::VK_QUEUE_FAMILY_IGNORED,
2836 			vk::VK_QUEUE_FAMILY_IGNORED,
2837 
2838 			*m_srcImage,
2839 			{
2840 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
2841 				0,	// Mip level
2842 				1,	// Mip level count
2843 				0,	// Layer
2844 				1	// Layer count
2845 			}
2846 		};
2847 		const vk::VkBufferImageCopy				region				=
2848 		{
2849 			0,
2850 			0, 0,
2851 			{
2852 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
2853 				0,	// mipLevel
2854 				0,	// arrayLayer
2855 				1	// layerCount
2856 			},
2857 			{ 0, 0, 0 },
2858 			{
2859 				(deUint32)m_imageWidth,
2860 				(deUint32)m_imageHeight,
2861 				1u
2862 			}
2863 		};
2864 
2865 		{
2866 			void* const	ptr	= mapMemory(vkd, device, *memory, 4 * m_imageWidth * m_imageHeight);
2867 			de::Random	rng	(m_seed);
2868 
2869 			{
2870 				deUint8* const	data = (deUint8*)ptr;
2871 
2872 				for (size_t ndx = 0; ndx < (size_t)(4 * m_imageWidth * m_imageHeight); ndx++)
2873 					data[ndx] = rng.getUint8();
2874 			}
2875 
2876 			vk::flushMappedMemoryRange(vkd, device, *memory, 0, 4 * m_imageWidth * m_imageHeight);
2877 			vkd.unmapMemory(device, *memory);
2878 		}
2879 
2880 		vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
2881 		vkd.cmdCopyBufferToImage(*commandBuffer, *srcBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
2882 		vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
2883 
2884 		VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
2885 		queueRun(vkd, queue, *commandBuffer);
2886 	}
2887 }
2888 
logSubmit(TestLog & log,size_t commandIndex) const2889 void BufferCopyFromImage::logSubmit (TestLog& log, size_t commandIndex) const
2890 {
2891 	log << TestLog::Message << commandIndex << ":" << getName() << " Copy buffer data from image" << TestLog::EndMessage;
2892 }
2893 
submit(SubmitContext & context)2894 void BufferCopyFromImage::submit (SubmitContext& context)
2895 {
2896 	const vk::DeviceInterface&	vkd				= context.getContext().getDeviceInterface();
2897 	const vk::VkCommandBuffer	commandBuffer	= context.getCommandBuffer();
2898 	const vk::VkBufferImageCopy	region			=
2899 	{
2900 		0,
2901 		0, 0,
2902 		{
2903 			vk::VK_IMAGE_ASPECT_COLOR_BIT,
2904 			0,	// mipLevel
2905 			0,	// arrayLayer
2906 			1	// layerCount
2907 		},
2908 		{ 0, 0, 0 },
2909 		{
2910 			(deUint32)m_imageWidth,
2911 			(deUint32)m_imageHeight,
2912 			1u
2913 		}
2914 	};
2915 
2916 	vkd.cmdCopyImageToBuffer(commandBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, context.getBuffer(), 1, &region);
2917 }
2918 
verify(VerifyContext & context,size_t)2919 void BufferCopyFromImage::verify (VerifyContext& context, size_t)
2920 {
2921 	ReferenceMemory&	reference		(context.getReference());
2922 	de::Random			rng	(m_seed);
2923 
2924 	for (size_t ndx = 0; ndx < (size_t)(4 * m_imageWidth * m_imageHeight); ndx++)
2925 		reference.set(ndx, rng.getUint8());
2926 }
2927 
2928 class ImageCopyToBuffer : public CmdCommand
2929 {
2930 public:
ImageCopyToBuffer(vk::VkImageLayout imageLayout)2931 									ImageCopyToBuffer	(vk::VkImageLayout imageLayout) : m_imageLayout (imageLayout) {}
~ImageCopyToBuffer(void)2932 									~ImageCopyToBuffer	(void) {}
getName(void) const2933 	const char*						getName				(void) const { return "BufferCopyToImage"; }
2934 
2935 	void							logPrepare			(TestLog& log, size_t commandIndex) const;
2936 	void							prepare				(PrepareContext& context);
2937 	void							logSubmit			(TestLog& log, size_t commandIndex) const;
2938 	void							submit				(SubmitContext& context);
2939 	void							verify				(VerifyContext& context, size_t commandIndex);
2940 
2941 private:
2942 	vk::VkImageLayout				m_imageLayout;
2943 	vk::VkDeviceSize				m_bufferSize;
2944 	vk::Move<vk::VkBuffer>			m_dstBuffer;
2945 	vk::Move<vk::VkDeviceMemory>	m_memory;
2946 	vk::VkDeviceSize				m_imageMemorySize;
2947 	deInt32							m_imageWidth;
2948 	deInt32							m_imageHeight;
2949 };
2950 
logPrepare(TestLog & log,size_t commandIndex) const2951 void ImageCopyToBuffer::logPrepare (TestLog& log, size_t commandIndex) const
2952 {
2953 	log << TestLog::Message << commandIndex << ":" << getName() << " Allocate destination buffer for image to buffer copy." << TestLog::EndMessage;
2954 }
2955 
prepare(PrepareContext & context)2956 void ImageCopyToBuffer::prepare (PrepareContext& context)
2957 {
2958 	const vk::InstanceInterface&	vki				= context.getContext().getInstanceInterface();
2959 	const vk::DeviceInterface&		vkd				= context.getContext().getDeviceInterface();
2960 	const vk::VkPhysicalDevice		physicalDevice	= context.getContext().getPhysicalDevice();
2961 	const vk::VkDevice				device			= context.getContext().getDevice();
2962 	const vector<deUint32>&			queueFamilies	= context.getContext().getQueueFamilies();
2963 
2964 	m_imageWidth		= context.getImageWidth();
2965 	m_imageHeight		= context.getImageHeight();
2966 	m_bufferSize		= 4 * m_imageWidth * m_imageHeight;
2967 	m_imageMemorySize	= context.getImageMemorySize();
2968 	m_dstBuffer			= createBuffer(vkd, device, m_bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies);
2969 	m_memory			= bindBufferMemory(vki, vkd, physicalDevice, device, *m_dstBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
2970 }
2971 
logSubmit(TestLog & log,size_t commandIndex) const2972 void ImageCopyToBuffer::logSubmit (TestLog& log, size_t commandIndex) const
2973 {
2974 	log << TestLog::Message << commandIndex << ":" << getName() << " Copy image to buffer" << TestLog::EndMessage;
2975 }
2976 
submit(SubmitContext & context)2977 void ImageCopyToBuffer::submit (SubmitContext& context)
2978 {
2979 	const vk::DeviceInterface&	vkd				= context.getContext().getDeviceInterface();
2980 	const vk::VkCommandBuffer	commandBuffer	= context.getCommandBuffer();
2981 	const vk::VkBufferImageCopy	region			=
2982 	{
2983 		0,
2984 		0, 0,
2985 		{
2986 			vk::VK_IMAGE_ASPECT_COLOR_BIT,
2987 			0,	// mipLevel
2988 			0,	// arrayLayer
2989 			1	// layerCount
2990 		},
2991 		{ 0, 0, 0 },
2992 		{
2993 			(deUint32)m_imageWidth,
2994 			(deUint32)m_imageHeight,
2995 			1u
2996 		}
2997 	};
2998 
2999 	vkd.cmdCopyImageToBuffer(commandBuffer, context.getImage(), m_imageLayout, *m_dstBuffer, 1, &region);
3000 }
3001 
verify(VerifyContext & context,size_t commandIndex)3002 void ImageCopyToBuffer::verify (VerifyContext& context, size_t commandIndex)
3003 {
3004 	tcu::ResultCollector&					resultCollector	(context.getResultCollector());
3005 	ReferenceMemory&						reference		(context.getReference());
3006 	const vk::DeviceInterface&				vkd				= context.getContext().getDeviceInterface();
3007 	const vk::VkDevice						device			= context.getContext().getDevice();
3008 	const vk::VkQueue						queue			= context.getContext().getQueue();
3009 	const vk::VkCommandPool					commandPool		= context.getContext().getCommandPool();
3010 	const vk::Unique<vk::VkCommandBuffer>	commandBuffer	(createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3011 	const vk::VkBufferMemoryBarrier			barrier			=
3012 	{
3013 		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
3014 		DE_NULL,
3015 
3016 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3017 		vk::VK_ACCESS_HOST_READ_BIT,
3018 
3019 		vk::VK_QUEUE_FAMILY_IGNORED,
3020 		vk::VK_QUEUE_FAMILY_IGNORED,
3021 		*m_dstBuffer,
3022 		0,
3023 		vk::VK_WHOLE_SIZE
3024 	};
3025 
3026 	vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 1, &barrier, 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
3027 
3028 	VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
3029 	queueRun(vkd, queue, *commandBuffer);
3030 
3031 	reference.setUndefined(0, (size_t)m_imageMemorySize);
3032 	{
3033 		void* const						ptr				= mapMemory(vkd, device, *m_memory, m_bufferSize);
3034 		const ConstPixelBufferAccess	referenceImage	(context.getReferenceImage().getAccess());
3035 		const ConstPixelBufferAccess	resultImage		(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_imageWidth, m_imageHeight, 1, ptr);
3036 
3037 		vk::invalidateMappedMemoryRange(vkd, device, *m_memory, 0, m_bufferSize);
3038 
3039 		if (!tcu::intThresholdCompare(context.getLog(), (de::toString(commandIndex) + ":" + getName()).c_str(), (de::toString(commandIndex) + ":" + getName()).c_str(), referenceImage, resultImage, UVec4(0), tcu::COMPARE_LOG_ON_ERROR))
3040 			resultCollector.fail(de::toString(commandIndex) + ":" + getName() + " Image comparison failed");
3041 
3042 		vkd.unmapMemory(device, *m_memory);
3043 	}
3044 }
3045 
3046 class ImageCopyFromBuffer : public CmdCommand
3047 {
3048 public:
ImageCopyFromBuffer(deUint32 seed,vk::VkImageLayout imageLayout)3049 									ImageCopyFromBuffer		(deUint32 seed, vk::VkImageLayout imageLayout) : m_seed(seed), m_imageLayout(imageLayout) {}
~ImageCopyFromBuffer(void)3050 									~ImageCopyFromBuffer	(void) {}
getName(void) const3051 	const char*						getName					(void) const { return "ImageCopyFromBuffer"; }
3052 
3053 	void							logPrepare				(TestLog& log, size_t commandIndex) const;
3054 	void							prepare					(PrepareContext& context);
3055 	void							logSubmit				(TestLog& log, size_t commandIndex) const;
3056 	void							submit					(SubmitContext& context);
3057 	void							verify					(VerifyContext& context, size_t commandIndex);
3058 
3059 private:
3060 	const deUint32					m_seed;
3061 	const vk::VkImageLayout			m_imageLayout;
3062 	deInt32							m_imageWidth;
3063 	deInt32							m_imageHeight;
3064 	vk::VkDeviceSize				m_imageMemorySize;
3065 	vk::VkDeviceSize				m_bufferSize;
3066 	vk::Move<vk::VkBuffer>			m_srcBuffer;
3067 	vk::Move<vk::VkDeviceMemory>	m_memory;
3068 };
3069 
logPrepare(TestLog & log,size_t commandIndex) const3070 void ImageCopyFromBuffer::logPrepare (TestLog& log, size_t commandIndex) const
3071 {
3072 	log << TestLog::Message << commandIndex << ":" << getName() << " Allocate source buffer for buffer to image copy. Seed: " << m_seed << TestLog::EndMessage;
3073 }
3074 
prepare(PrepareContext & context)3075 void ImageCopyFromBuffer::prepare (PrepareContext& context)
3076 {
3077 	const vk::InstanceInterface&	vki				= context.getContext().getInstanceInterface();
3078 	const vk::DeviceInterface&		vkd				= context.getContext().getDeviceInterface();
3079 	const vk::VkPhysicalDevice		physicalDevice	= context.getContext().getPhysicalDevice();
3080 	const vk::VkDevice				device			= context.getContext().getDevice();
3081 	const vector<deUint32>&			queueFamilies	= context.getContext().getQueueFamilies();
3082 
3083 	m_imageWidth		= context.getImageHeight();
3084 	m_imageHeight		= context.getImageWidth();
3085 	m_imageMemorySize	= context.getImageMemorySize();
3086 	m_bufferSize		= m_imageWidth * m_imageHeight * 4;
3087 	m_srcBuffer			= createBuffer(vkd, device, m_bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies);
3088 	m_memory			= bindBufferMemory(vki, vkd, physicalDevice, device, *m_srcBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
3089 
3090 	{
3091 		void* const	ptr	= mapMemory(vkd, device, *m_memory, m_bufferSize);
3092 		de::Random	rng	(m_seed);
3093 
3094 		{
3095 			deUint8* const	data = (deUint8*)ptr;
3096 
3097 			for (size_t ndx = 0; ndx < (size_t)m_bufferSize; ndx++)
3098 				data[ndx] = rng.getUint8();
3099 		}
3100 
3101 		vk::flushMappedMemoryRange(vkd, device, *m_memory, 0, m_bufferSize);
3102 		vkd.unmapMemory(device, *m_memory);
3103 	}
3104 }
3105 
logSubmit(TestLog & log,size_t commandIndex) const3106 void ImageCopyFromBuffer::logSubmit (TestLog& log, size_t commandIndex) const
3107 {
3108 	log << TestLog::Message << commandIndex << ":" << getName() << " Copy image data from buffer" << TestLog::EndMessage;
3109 }
3110 
submit(SubmitContext & context)3111 void ImageCopyFromBuffer::submit (SubmitContext& context)
3112 {
3113 	const vk::DeviceInterface&	vkd				= context.getContext().getDeviceInterface();
3114 	const vk::VkCommandBuffer	commandBuffer	= context.getCommandBuffer();
3115 	const vk::VkBufferImageCopy	region			=
3116 	{
3117 		0,
3118 		0, 0,
3119 		{
3120 			vk::VK_IMAGE_ASPECT_COLOR_BIT,
3121 			0,	// mipLevel
3122 			0,	// arrayLayer
3123 			1	// layerCount
3124 		},
3125 		{ 0, 0, 0 },
3126 		{
3127 			(deUint32)m_imageWidth,
3128 			(deUint32)m_imageHeight,
3129 			1u
3130 		}
3131 	};
3132 
3133 	vkd.cmdCopyBufferToImage(commandBuffer, *m_srcBuffer, context.getImage(), m_imageLayout, 1, &region);
3134 }
3135 
verify(VerifyContext & context,size_t)3136 void ImageCopyFromBuffer::verify (VerifyContext& context, size_t)
3137 {
3138 	ReferenceMemory&	reference	(context.getReference());
3139 	de::Random			rng			(m_seed);
3140 
3141 	reference.setUndefined(0, (size_t)m_imageMemorySize);
3142 
3143 	{
3144 		const PixelBufferAccess&	refAccess	(context.getReferenceImage().getAccess());
3145 
3146 		for (deInt32 y = 0; y < m_imageHeight; y++)
3147 		for (deInt32 x = 0; x < m_imageWidth; x++)
3148 		{
3149 			const deUint8 r8 = rng.getUint8();
3150 			const deUint8 g8 = rng.getUint8();
3151 			const deUint8 b8 = rng.getUint8();
3152 			const deUint8 a8 = rng.getUint8();
3153 
3154 			refAccess.setPixel(UVec4(r8, g8, b8, a8), x, y);
3155 		}
3156 	}
3157 }
3158 
3159 class ImageCopyFromImage : public CmdCommand
3160 {
3161 public:
ImageCopyFromImage(deUint32 seed,vk::VkImageLayout imageLayout)3162 									ImageCopyFromImage	(deUint32 seed, vk::VkImageLayout imageLayout) : m_seed(seed), m_imageLayout(imageLayout) {}
~ImageCopyFromImage(void)3163 									~ImageCopyFromImage	(void) {}
getName(void) const3164 	const char*						getName				(void) const { return "ImageCopyFromImage"; }
3165 
3166 	void							logPrepare			(TestLog& log, size_t commandIndex) const;
3167 	void							prepare				(PrepareContext& context);
3168 	void							logSubmit			(TestLog& log, size_t commandIndex) const;
3169 	void							submit				(SubmitContext& context);
3170 	void							verify				(VerifyContext& context, size_t commandIndex);
3171 
3172 private:
3173 	const deUint32					m_seed;
3174 	const vk::VkImageLayout			m_imageLayout;
3175 	deInt32							m_imageWidth;
3176 	deInt32							m_imageHeight;
3177 	vk::VkDeviceSize				m_imageMemorySize;
3178 	vk::Move<vk::VkImage>			m_srcImage;
3179 	vk::Move<vk::VkDeviceMemory>	m_memory;
3180 };
3181 
logPrepare(TestLog & log,size_t commandIndex) const3182 void ImageCopyFromImage::logPrepare (TestLog& log, size_t commandIndex) const
3183 {
3184 	log << TestLog::Message << commandIndex << ":" << getName() << " Allocate source image for image to image copy." << TestLog::EndMessage;
3185 }
3186 
prepare(PrepareContext & context)3187 void ImageCopyFromImage::prepare (PrepareContext& context)
3188 {
3189 	const vk::InstanceInterface&	vki				= context.getContext().getInstanceInterface();
3190 	const vk::DeviceInterface&		vkd				= context.getContext().getDeviceInterface();
3191 	const vk::VkPhysicalDevice		physicalDevice	= context.getContext().getPhysicalDevice();
3192 	const vk::VkDevice				device			= context.getContext().getDevice();
3193 	const vk::VkQueue				queue			= context.getContext().getQueue();
3194 	const vk::VkCommandPool			commandPool		= context.getContext().getCommandPool();
3195 	const vector<deUint32>&			queueFamilies	= context.getContext().getQueueFamilies();
3196 
3197 	m_imageWidth		= context.getImageWidth();
3198 	m_imageHeight		= context.getImageHeight();
3199 	m_imageMemorySize	= context.getImageMemorySize();
3200 
3201 	{
3202 		const vk::VkImageCreateInfo	createInfo =
3203 		{
3204 			vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3205 			DE_NULL,
3206 
3207 			0,
3208 			vk::VK_IMAGE_TYPE_2D,
3209 			vk::VK_FORMAT_R8G8B8A8_UNORM,
3210 			{
3211 				(deUint32)m_imageWidth,
3212 				(deUint32)m_imageHeight,
3213 				1u,
3214 			},
3215 			1, 1, // mipLevels, arrayLayers
3216 			vk::VK_SAMPLE_COUNT_1_BIT,
3217 
3218 			vk::VK_IMAGE_TILING_OPTIMAL,
3219 			vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3220 			vk::VK_SHARING_MODE_EXCLUSIVE,
3221 
3222 			(deUint32)queueFamilies.size(),
3223 			&queueFamilies[0],
3224 			vk::VK_IMAGE_LAYOUT_UNDEFINED
3225 		};
3226 
3227 		m_srcImage = vk::createImage(vkd, device, &createInfo);
3228 	}
3229 
3230 	m_memory = bindImageMemory(vki, vkd, physicalDevice, device, *m_srcImage, 0);
3231 
3232 	{
3233 		const vk::Unique<vk::VkBuffer>			srcBuffer		(createBuffer(vkd, device, 4 * m_imageWidth * m_imageHeight, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies));
3234 		const vk::Unique<vk::VkDeviceMemory>	memory			(bindBufferMemory(vki, vkd, physicalDevice, device, *srcBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
3235 		const vk::Unique<vk::VkCommandBuffer>	commandBuffer	(createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3236 		const vk::VkImageMemoryBarrier			preImageBarrier	=
3237 		{
3238 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3239 			DE_NULL,
3240 
3241 			0,
3242 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3243 
3244 			vk::VK_IMAGE_LAYOUT_UNDEFINED,
3245 			vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3246 
3247 			vk::VK_QUEUE_FAMILY_IGNORED,
3248 			vk::VK_QUEUE_FAMILY_IGNORED,
3249 
3250 			*m_srcImage,
3251 			{
3252 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
3253 				0,	// Mip level
3254 				1,	// Mip level count
3255 				0,	// Layer
3256 				1	// Layer count
3257 			}
3258 		};
3259 		const vk::VkImageMemoryBarrier			postImageBarrier =
3260 		{
3261 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3262 			DE_NULL,
3263 
3264 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3265 			0,
3266 
3267 			vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3268 			vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3269 
3270 			vk::VK_QUEUE_FAMILY_IGNORED,
3271 			vk::VK_QUEUE_FAMILY_IGNORED,
3272 
3273 			*m_srcImage,
3274 			{
3275 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
3276 				0,	// Mip level
3277 				1,	// Mip level count
3278 				0,	// Layer
3279 				1	// Layer count
3280 			}
3281 		};
3282 		const vk::VkBufferImageCopy				region				=
3283 		{
3284 			0,
3285 			0, 0,
3286 			{
3287 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
3288 				0,	// mipLevel
3289 				0,	// arrayLayer
3290 				1	// layerCount
3291 			},
3292 			{ 0, 0, 0 },
3293 			{
3294 				(deUint32)m_imageWidth,
3295 				(deUint32)m_imageHeight,
3296 				1u
3297 			}
3298 		};
3299 
3300 		{
3301 			void* const	ptr	= mapMemory(vkd, device, *memory, 4 * m_imageWidth * m_imageHeight);
3302 			de::Random	rng	(m_seed);
3303 
3304 			{
3305 				deUint8* const	data = (deUint8*)ptr;
3306 
3307 				for (size_t ndx = 0; ndx < (size_t)(4 * m_imageWidth * m_imageHeight); ndx++)
3308 					data[ndx] = rng.getUint8();
3309 			}
3310 
3311 			vk::flushMappedMemoryRange(vkd, device, *memory, 0, 4 * m_imageWidth * m_imageHeight);
3312 			vkd.unmapMemory(device, *memory);
3313 		}
3314 
3315 		vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
3316 		vkd.cmdCopyBufferToImage(*commandBuffer, *srcBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
3317 		vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
3318 
3319 		VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
3320 		queueRun(vkd, queue, *commandBuffer);
3321 	}
3322 }
3323 
logSubmit(TestLog & log,size_t commandIndex) const3324 void ImageCopyFromImage::logSubmit (TestLog& log, size_t commandIndex) const
3325 {
3326 	log << TestLog::Message << commandIndex << ":" << getName() << " Copy image data from another image" << TestLog::EndMessage;
3327 }
3328 
submit(SubmitContext & context)3329 void ImageCopyFromImage::submit (SubmitContext& context)
3330 {
3331 	const vk::DeviceInterface&	vkd				= context.getContext().getDeviceInterface();
3332 	const vk::VkCommandBuffer	commandBuffer	= context.getCommandBuffer();
3333 	const vk::VkImageCopy		region			=
3334 	{
3335 		{
3336 			vk::VK_IMAGE_ASPECT_COLOR_BIT,
3337 			0,	// mipLevel
3338 			0,	// arrayLayer
3339 			1	// layerCount
3340 		},
3341 		{ 0, 0, 0 },
3342 
3343 		{
3344 			vk::VK_IMAGE_ASPECT_COLOR_BIT,
3345 			0,	// mipLevel
3346 			0,	// arrayLayer
3347 			1	// layerCount
3348 		},
3349 		{ 0, 0, 0 },
3350 		{
3351 			(deUint32)m_imageWidth,
3352 			(deUint32)m_imageHeight,
3353 			1u
3354 		}
3355 	};
3356 
3357 	vkd.cmdCopyImage(commandBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, context.getImage(), m_imageLayout, 1, &region);
3358 }
3359 
verify(VerifyContext & context,size_t)3360 void ImageCopyFromImage::verify (VerifyContext& context, size_t)
3361 {
3362 	ReferenceMemory&	reference	(context.getReference());
3363 	de::Random			rng			(m_seed);
3364 
3365 	reference.setUndefined(0, (size_t)m_imageMemorySize);
3366 
3367 	{
3368 		const PixelBufferAccess&	refAccess	(context.getReferenceImage().getAccess());
3369 
3370 		for (deInt32 y = 0; y < m_imageHeight; y++)
3371 		for (deInt32 x = 0; x < m_imageWidth; x++)
3372 		{
3373 			const deUint8 r8 = rng.getUint8();
3374 			const deUint8 g8 = rng.getUint8();
3375 			const deUint8 b8 = rng.getUint8();
3376 			const deUint8 a8 = rng.getUint8();
3377 
3378 			refAccess.setPixel(UVec4(r8, g8, b8, a8), x, y);
3379 		}
3380 	}
3381 }
3382 
3383 class ImageCopyToImage : public CmdCommand
3384 {
3385 public:
ImageCopyToImage(vk::VkImageLayout imageLayout)3386 									ImageCopyToImage	(vk::VkImageLayout imageLayout) : m_imageLayout(imageLayout) {}
~ImageCopyToImage(void)3387 									~ImageCopyToImage	(void) {}
getName(void) const3388 	const char*						getName				(void) const { return "ImageCopyToImage"; }
3389 
3390 	void							logPrepare			(TestLog& log, size_t commandIndex) const;
3391 	void							prepare				(PrepareContext& context);
3392 	void							logSubmit			(TestLog& log, size_t commandIndex) const;
3393 	void							submit				(SubmitContext& context);
3394 	void							verify				(VerifyContext& context, size_t commandIndex);
3395 
3396 private:
3397 	const vk::VkImageLayout			m_imageLayout;
3398 	deInt32							m_imageWidth;
3399 	deInt32							m_imageHeight;
3400 	vk::VkDeviceSize				m_imageMemorySize;
3401 	vk::Move<vk::VkImage>			m_dstImage;
3402 	vk::Move<vk::VkDeviceMemory>	m_memory;
3403 };
3404 
logPrepare(TestLog & log,size_t commandIndex) const3405 void ImageCopyToImage::logPrepare (TestLog& log, size_t commandIndex) const
3406 {
3407 	log << TestLog::Message << commandIndex << ":" << getName() << " Allocate destination image for image to image copy." << TestLog::EndMessage;
3408 }
3409 
prepare(PrepareContext & context)3410 void ImageCopyToImage::prepare (PrepareContext& context)
3411 {
3412 	const vk::InstanceInterface&	vki				= context.getContext().getInstanceInterface();
3413 	const vk::DeviceInterface&		vkd				= context.getContext().getDeviceInterface();
3414 	const vk::VkPhysicalDevice		physicalDevice	= context.getContext().getPhysicalDevice();
3415 	const vk::VkDevice				device			= context.getContext().getDevice();
3416 	const vk::VkQueue				queue			= context.getContext().getQueue();
3417 	const vk::VkCommandPool			commandPool		= context.getContext().getCommandPool();
3418 	const vector<deUint32>&			queueFamilies	= context.getContext().getQueueFamilies();
3419 
3420 	m_imageWidth		= context.getImageWidth();
3421 	m_imageHeight		= context.getImageHeight();
3422 	m_imageMemorySize	= context.getImageMemorySize();
3423 
3424 	{
3425 		const vk::VkImageCreateInfo	createInfo =
3426 		{
3427 			vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3428 			DE_NULL,
3429 
3430 			0,
3431 			vk::VK_IMAGE_TYPE_2D,
3432 			vk::VK_FORMAT_R8G8B8A8_UNORM,
3433 			{
3434 				(deUint32)m_imageWidth,
3435 				(deUint32)m_imageHeight,
3436 				1u,
3437 			},
3438 			1, 1, // mipLevels, arrayLayers
3439 			vk::VK_SAMPLE_COUNT_1_BIT,
3440 
3441 			vk::VK_IMAGE_TILING_OPTIMAL,
3442 			vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3443 			vk::VK_SHARING_MODE_EXCLUSIVE,
3444 
3445 			(deUint32)queueFamilies.size(),
3446 			&queueFamilies[0],
3447 			vk::VK_IMAGE_LAYOUT_UNDEFINED
3448 		};
3449 
3450 		m_dstImage = vk::createImage(vkd, device, &createInfo);
3451 	}
3452 
3453 	m_memory = bindImageMemory(vki, vkd, physicalDevice, device, *m_dstImage, 0);
3454 
3455 	{
3456 		const vk::Unique<vk::VkCommandBuffer>	commandBuffer	(createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3457 		const vk::VkImageMemoryBarrier			barrier			=
3458 		{
3459 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3460 			DE_NULL,
3461 
3462 			0,
3463 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3464 
3465 			vk::VK_IMAGE_LAYOUT_UNDEFINED,
3466 			vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3467 
3468 			vk::VK_QUEUE_FAMILY_IGNORED,
3469 			vk::VK_QUEUE_FAMILY_IGNORED,
3470 
3471 			*m_dstImage,
3472 			{
3473 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
3474 				0,	// Mip level
3475 				1,	// Mip level count
3476 				0,	// Layer
3477 				1	// Layer count
3478 			}
3479 		};
3480 
3481 		vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
3482 
3483 		VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
3484 		queueRun(vkd, queue, *commandBuffer);
3485 	}
3486 }
3487 
logSubmit(TestLog & log,size_t commandIndex) const3488 void ImageCopyToImage::logSubmit (TestLog& log, size_t commandIndex) const
3489 {
3490 	log << TestLog::Message << commandIndex << ":" << getName() << " Copy image to another image" << TestLog::EndMessage;
3491 }
3492 
submit(SubmitContext & context)3493 void ImageCopyToImage::submit (SubmitContext& context)
3494 {
3495 	const vk::DeviceInterface&	vkd				= context.getContext().getDeviceInterface();
3496 	const vk::VkCommandBuffer	commandBuffer	= context.getCommandBuffer();
3497 	const vk::VkImageCopy		region			=
3498 	{
3499 		{
3500 			vk::VK_IMAGE_ASPECT_COLOR_BIT,
3501 			0,	// mipLevel
3502 			0,	// arrayLayer
3503 			1	// layerCount
3504 		},
3505 		{ 0, 0, 0 },
3506 
3507 		{
3508 			vk::VK_IMAGE_ASPECT_COLOR_BIT,
3509 			0,	// mipLevel
3510 			0,	// arrayLayer
3511 			1	// layerCount
3512 		},
3513 		{ 0, 0, 0 },
3514 		{
3515 			(deUint32)m_imageWidth,
3516 			(deUint32)m_imageHeight,
3517 			1u
3518 		}
3519 	};
3520 
3521 	vkd.cmdCopyImage(commandBuffer, context.getImage(), m_imageLayout, *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
3522 }
3523 
verify(VerifyContext & context,size_t commandIndex)3524 void ImageCopyToImage::verify (VerifyContext& context, size_t commandIndex)
3525 {
3526 	tcu::ResultCollector&					resultCollector	(context.getResultCollector());
3527 	const vk::InstanceInterface&			vki				= context.getContext().getInstanceInterface();
3528 	const vk::DeviceInterface&				vkd				= context.getContext().getDeviceInterface();
3529 	const vk::VkPhysicalDevice				physicalDevice	= context.getContext().getPhysicalDevice();
3530 	const vk::VkDevice						device			= context.getContext().getDevice();
3531 	const vk::VkQueue						queue			= context.getContext().getQueue();
3532 	const vk::VkCommandPool					commandPool		= context.getContext().getCommandPool();
3533 	const vk::Unique<vk::VkCommandBuffer>	commandBuffer	(createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3534 	const vector<deUint32>&					queueFamilies	= context.getContext().getQueueFamilies();
3535 	const vk::Unique<vk::VkBuffer>			dstBuffer		(createBuffer(vkd, device, 4 * m_imageWidth * m_imageHeight, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies));
3536 	const vk::Unique<vk::VkDeviceMemory>	memory			(bindBufferMemory(vki, vkd, physicalDevice, device, *dstBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
3537 	{
3538 		const vk::VkImageMemoryBarrier		imageBarrier	=
3539 		{
3540 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3541 			DE_NULL,
3542 
3543 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3544 			vk::VK_ACCESS_TRANSFER_READ_BIT,
3545 
3546 			vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3547 			vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3548 
3549 			vk::VK_QUEUE_FAMILY_IGNORED,
3550 			vk::VK_QUEUE_FAMILY_IGNORED,
3551 
3552 			*m_dstImage,
3553 			{
3554 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
3555 				0,	// Mip level
3556 				1,	// Mip level count
3557 				0,	// Layer
3558 				1	// Layer count
3559 			}
3560 		};
3561 		const vk::VkBufferMemoryBarrier bufferBarrier =
3562 		{
3563 			vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
3564 			DE_NULL,
3565 
3566 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3567 			vk::VK_ACCESS_HOST_READ_BIT,
3568 
3569 			vk::VK_QUEUE_FAMILY_IGNORED,
3570 			vk::VK_QUEUE_FAMILY_IGNORED,
3571 			*dstBuffer,
3572 			0,
3573 			vk::VK_WHOLE_SIZE
3574 		};
3575 		const vk::VkBufferImageCopy	region =
3576 		{
3577 			0,
3578 			0, 0,
3579 			{
3580 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
3581 				0,	// mipLevel
3582 				0,	// arrayLayer
3583 				1	// layerCount
3584 			},
3585 			{ 0, 0, 0 },
3586 			{
3587 				(deUint32)m_imageWidth,
3588 				(deUint32)m_imageHeight,
3589 				1u
3590 			}
3591 		};
3592 
3593 		vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &imageBarrier);
3594 		vkd.cmdCopyImageToBuffer(*commandBuffer, *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dstBuffer, 1, &region);
3595 		vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
3596 	}
3597 
3598 	VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
3599 	queueRun(vkd, queue, *commandBuffer);
3600 
3601 	{
3602 		void* const	ptr		= mapMemory(vkd, device, *memory, 4 * m_imageWidth * m_imageHeight);
3603 
3604 		vk::invalidateMappedMemoryRange(vkd, device, *memory, 0,  4 * m_imageWidth * m_imageHeight);
3605 
3606 		{
3607 			const deUint8* const			data		= (const deUint8*)ptr;
3608 			const ConstPixelBufferAccess	resAccess	(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_imageWidth, m_imageHeight, 1, data);
3609 			const ConstPixelBufferAccess&	refAccess	(context.getReferenceImage().getAccess());
3610 
3611 			if (!tcu::intThresholdCompare(context.getLog(), (de::toString(commandIndex) + ":" + getName()).c_str(), (de::toString(commandIndex) + ":" + getName()).c_str(), refAccess, resAccess, UVec4(0), tcu::COMPARE_LOG_ON_ERROR))
3612 				resultCollector.fail(de::toString(commandIndex) + ":" + getName() + " Image comparison failed");
3613 		}
3614 
3615 		vkd.unmapMemory(device, *memory);
3616 	}
3617 }
3618 
3619 enum BlitScale
3620 {
3621 	BLIT_SCALE_20,
3622 	BLIT_SCALE_10,
3623 };
3624 
3625 class ImageBlitFromImage : public CmdCommand
3626 {
3627 public:
ImageBlitFromImage(deUint32 seed,BlitScale scale,vk::VkImageLayout imageLayout)3628 									ImageBlitFromImage	(deUint32 seed, BlitScale scale, vk::VkImageLayout imageLayout) : m_seed(seed), m_scale(scale), m_imageLayout(imageLayout) {}
~ImageBlitFromImage(void)3629 									~ImageBlitFromImage	(void) {}
getName(void) const3630 	const char*						getName				(void) const { return "ImageBlitFromImage"; }
3631 
3632 	void							logPrepare			(TestLog& log, size_t commandIndex) const;
3633 	void							prepare				(PrepareContext& context);
3634 	void							logSubmit			(TestLog& log, size_t commandIndex) const;
3635 	void							submit				(SubmitContext& context);
3636 	void							verify				(VerifyContext& context, size_t commandIndex);
3637 
3638 private:
3639 	const deUint32					m_seed;
3640 	const BlitScale					m_scale;
3641 	const vk::VkImageLayout			m_imageLayout;
3642 	deInt32							m_imageWidth;
3643 	deInt32							m_imageHeight;
3644 	vk::VkDeviceSize				m_imageMemorySize;
3645 	deInt32							m_srcImageWidth;
3646 	deInt32							m_srcImageHeight;
3647 	vk::Move<vk::VkImage>			m_srcImage;
3648 	vk::Move<vk::VkDeviceMemory>	m_memory;
3649 };
3650 
logPrepare(TestLog & log,size_t commandIndex) const3651 void ImageBlitFromImage::logPrepare (TestLog& log, size_t commandIndex) const
3652 {
3653 	log << TestLog::Message << commandIndex << ":" << getName() << " Allocate source image for image to image blit." << TestLog::EndMessage;
3654 }
3655 
prepare(PrepareContext & context)3656 void ImageBlitFromImage::prepare (PrepareContext& context)
3657 {
3658 	const vk::InstanceInterface&	vki				= context.getContext().getInstanceInterface();
3659 	const vk::DeviceInterface&		vkd				= context.getContext().getDeviceInterface();
3660 	const vk::VkPhysicalDevice		physicalDevice	= context.getContext().getPhysicalDevice();
3661 	const vk::VkDevice				device			= context.getContext().getDevice();
3662 	const vk::VkQueue				queue			= context.getContext().getQueue();
3663 	const vk::VkCommandPool			commandPool		= context.getContext().getCommandPool();
3664 	const vector<deUint32>&			queueFamilies	= context.getContext().getQueueFamilies();
3665 
3666 	m_imageWidth		= context.getImageWidth();
3667 	m_imageHeight		= context.getImageHeight();
3668 	m_imageMemorySize	= context.getImageMemorySize();
3669 
3670 	if (m_scale == BLIT_SCALE_10)
3671 	{
3672 		m_srcImageWidth			= m_imageWidth;
3673 		m_srcImageHeight		= m_imageHeight;
3674 	}
3675 	else if (m_scale == BLIT_SCALE_20)
3676 	{
3677 		m_srcImageWidth			= m_imageWidth / 2;
3678 		m_srcImageHeight		= m_imageHeight / 2;
3679 	}
3680 	else
3681 		DE_FATAL("Unsupported scale");
3682 
3683 	{
3684 		const vk::VkImageCreateInfo	createInfo =
3685 		{
3686 			vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3687 			DE_NULL,
3688 
3689 			0,
3690 			vk::VK_IMAGE_TYPE_2D,
3691 			vk::VK_FORMAT_R8G8B8A8_UNORM,
3692 			{
3693 				(deUint32)m_srcImageWidth,
3694 				(deUint32)m_srcImageHeight,
3695 				1u,
3696 			},
3697 			1, 1, // mipLevels, arrayLayers
3698 			vk::VK_SAMPLE_COUNT_1_BIT,
3699 
3700 			vk::VK_IMAGE_TILING_OPTIMAL,
3701 			vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3702 			vk::VK_SHARING_MODE_EXCLUSIVE,
3703 
3704 			(deUint32)queueFamilies.size(),
3705 			&queueFamilies[0],
3706 			vk::VK_IMAGE_LAYOUT_UNDEFINED
3707 		};
3708 
3709 		m_srcImage = vk::createImage(vkd, device, &createInfo);
3710 	}
3711 
3712 	m_memory = bindImageMemory(vki, vkd, physicalDevice, device, *m_srcImage, 0);
3713 
3714 	{
3715 		const vk::Unique<vk::VkBuffer>			srcBuffer		(createBuffer(vkd, device, 4 * m_srcImageWidth * m_srcImageHeight, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies));
3716 		const vk::Unique<vk::VkDeviceMemory>	memory			(bindBufferMemory(vki, vkd, physicalDevice, device, *srcBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
3717 		const vk::Unique<vk::VkCommandBuffer>	commandBuffer	(createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3718 		const vk::VkImageMemoryBarrier			preImageBarrier	=
3719 		{
3720 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3721 			DE_NULL,
3722 
3723 			0,
3724 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3725 
3726 			vk::VK_IMAGE_LAYOUT_UNDEFINED,
3727 			vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3728 
3729 			vk::VK_QUEUE_FAMILY_IGNORED,
3730 			vk::VK_QUEUE_FAMILY_IGNORED,
3731 
3732 			*m_srcImage,
3733 			{
3734 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
3735 				0,	// Mip level
3736 				1,	// Mip level count
3737 				0,	// Layer
3738 				1	// Layer count
3739 			}
3740 		};
3741 		const vk::VkImageMemoryBarrier			postImageBarrier =
3742 		{
3743 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3744 			DE_NULL,
3745 
3746 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3747 			0,
3748 
3749 			vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3750 			vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3751 
3752 			vk::VK_QUEUE_FAMILY_IGNORED,
3753 			vk::VK_QUEUE_FAMILY_IGNORED,
3754 
3755 			*m_srcImage,
3756 			{
3757 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
3758 				0,	// Mip level
3759 				1,	// Mip level count
3760 				0,	// Layer
3761 				1	// Layer count
3762 			}
3763 		};
3764 		const vk::VkBufferImageCopy				region				=
3765 		{
3766 			0,
3767 			0, 0,
3768 			{
3769 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
3770 				0,	// mipLevel
3771 				0,	// arrayLayer
3772 				1	// layerCount
3773 			},
3774 			{ 0, 0, 0 },
3775 			{
3776 				(deUint32)m_srcImageWidth,
3777 				(deUint32)m_srcImageHeight,
3778 				1u
3779 			}
3780 		};
3781 
3782 		{
3783 			void* const	ptr	= mapMemory(vkd, device, *memory, 4 * m_srcImageWidth * m_srcImageHeight);
3784 			de::Random	rng	(m_seed);
3785 
3786 			{
3787 				deUint8* const	data = (deUint8*)ptr;
3788 
3789 				for (size_t ndx = 0; ndx < (size_t)(4 * m_srcImageWidth * m_srcImageHeight); ndx++)
3790 					data[ndx] = rng.getUint8();
3791 			}
3792 
3793 			vk::flushMappedMemoryRange(vkd, device, *memory, 0, 4 * m_srcImageWidth * m_srcImageHeight);
3794 			vkd.unmapMemory(device, *memory);
3795 		}
3796 
3797 		vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
3798 		vkd.cmdCopyBufferToImage(*commandBuffer, *srcBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
3799 		vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
3800 
3801 		VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
3802 		queueRun(vkd, queue, *commandBuffer);
3803 	}
3804 }
3805 
logSubmit(TestLog & log,size_t commandIndex) const3806 void ImageBlitFromImage::logSubmit (TestLog& log, size_t commandIndex) const
3807 {
3808 	log << TestLog::Message << commandIndex << ":" << getName() << " Blit from another image" << (m_scale == BLIT_SCALE_20 ? " scale 2x" : "")  << TestLog::EndMessage;
3809 }
3810 
submit(SubmitContext & context)3811 void ImageBlitFromImage::submit (SubmitContext& context)
3812 {
3813 	const vk::DeviceInterface&	vkd				= context.getContext().getDeviceInterface();
3814 	const vk::VkCommandBuffer	commandBuffer	= context.getCommandBuffer();
3815 	const vk::VkImageBlit		region			=
3816 	{
3817 		// Src
3818 		{
3819 			vk::VK_IMAGE_ASPECT_COLOR_BIT,
3820 			0,	// mipLevel
3821 			0,	// arrayLayer
3822 			1	// layerCount
3823 		},
3824 		{
3825 			{ 0, 0, 0 },
3826 			{
3827 				m_srcImageWidth,
3828 				m_srcImageHeight,
3829 				1
3830 			},
3831 		},
3832 
3833 		// Dst
3834 		{
3835 			vk::VK_IMAGE_ASPECT_COLOR_BIT,
3836 			0,	// mipLevel
3837 			0,	// arrayLayer
3838 			1	// layerCount
3839 		},
3840 		{
3841 			{ 0, 0, 0 },
3842 			{
3843 				m_imageWidth,
3844 				m_imageHeight,
3845 				1u
3846 			}
3847 		}
3848 	};
3849 	vkd.cmdBlitImage(commandBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, context.getImage(), m_imageLayout, 1, &region, vk::VK_FILTER_NEAREST);
3850 }
3851 
verify(VerifyContext & context,size_t)3852 void ImageBlitFromImage::verify (VerifyContext& context, size_t)
3853 {
3854 	ReferenceMemory&	reference	(context.getReference());
3855 	de::Random			rng			(m_seed);
3856 
3857 	reference.setUndefined(0, (size_t)m_imageMemorySize);
3858 
3859 	{
3860 		const PixelBufferAccess&	refAccess	(context.getReferenceImage().getAccess());
3861 
3862 		if (m_scale == BLIT_SCALE_10)
3863 		{
3864 			for (deInt32 y = 0; y < m_imageHeight; y++)
3865 			for (deInt32 x = 0; x < m_imageWidth; x++)
3866 			{
3867 				const deUint8 r8 = rng.getUint8();
3868 				const deUint8 g8 = rng.getUint8();
3869 				const deUint8 b8 = rng.getUint8();
3870 				const deUint8 a8 = rng.getUint8();
3871 
3872 				refAccess.setPixel(UVec4(r8, g8, b8, a8), x, y);
3873 			}
3874 		}
3875 		else if (m_scale == BLIT_SCALE_20)
3876 		{
3877 			tcu::TextureLevel	source	(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_srcImageWidth, m_srcImageHeight);
3878 			const float			xscale	= ((float)m_srcImageWidth)  / (float)m_imageWidth;
3879 			const float			yscale	= ((float)m_srcImageHeight) / (float)m_imageHeight;
3880 
3881 			for (deInt32 y = 0; y < m_srcImageHeight; y++)
3882 			for (deInt32 x = 0; x < m_srcImageWidth; x++)
3883 			{
3884 				const deUint8 r8 = rng.getUint8();
3885 				const deUint8 g8 = rng.getUint8();
3886 				const deUint8 b8 = rng.getUint8();
3887 				const deUint8 a8 = rng.getUint8();
3888 
3889 				source.getAccess().setPixel(UVec4(r8, g8, b8, a8), x, y);
3890 			}
3891 
3892 			for (deInt32 y = 0; y < m_imageHeight; y++)
3893 			for (deInt32 x = 0; x < m_imageWidth; x++)
3894 				refAccess.setPixel(source.getAccess().getPixelUint(int(float(x) * xscale), int(float(y) * yscale)), x, y);
3895 		}
3896 		else
3897 			DE_FATAL("Unsupported scale");
3898 	}
3899 }
3900 
3901 class ImageBlitToImage : public CmdCommand
3902 {
3903 public:
ImageBlitToImage(BlitScale scale,vk::VkImageLayout imageLayout)3904 									ImageBlitToImage	(BlitScale scale, vk::VkImageLayout imageLayout) : m_scale(scale), m_imageLayout(imageLayout) {}
~ImageBlitToImage(void)3905 									~ImageBlitToImage	(void) {}
getName(void) const3906 	const char*						getName				(void) const { return "ImageBlitToImage"; }
3907 
3908 	void							logPrepare			(TestLog& log, size_t commandIndex) const;
3909 	void							prepare				(PrepareContext& context);
3910 	void							logSubmit			(TestLog& log, size_t commandIndex) const;
3911 	void							submit				(SubmitContext& context);
3912 	void							verify				(VerifyContext& context, size_t commandIndex);
3913 
3914 private:
3915 	const BlitScale					m_scale;
3916 	const vk::VkImageLayout			m_imageLayout;
3917 	deInt32							m_imageWidth;
3918 	deInt32							m_imageHeight;
3919 	vk::VkDeviceSize				m_imageMemorySize;
3920 	deInt32							m_dstImageWidth;
3921 	deInt32							m_dstImageHeight;
3922 	vk::Move<vk::VkImage>			m_dstImage;
3923 	vk::Move<vk::VkDeviceMemory>	m_memory;
3924 };
3925 
logPrepare(TestLog & log,size_t commandIndex) const3926 void ImageBlitToImage::logPrepare (TestLog& log, size_t commandIndex) const
3927 {
3928 	log << TestLog::Message << commandIndex << ":" << getName() << " Allocate destination image for image to image blit." << TestLog::EndMessage;
3929 }
3930 
prepare(PrepareContext & context)3931 void ImageBlitToImage::prepare (PrepareContext& context)
3932 {
3933 	const vk::InstanceInterface&	vki				= context.getContext().getInstanceInterface();
3934 	const vk::DeviceInterface&		vkd				= context.getContext().getDeviceInterface();
3935 	const vk::VkPhysicalDevice		physicalDevice	= context.getContext().getPhysicalDevice();
3936 	const vk::VkDevice				device			= context.getContext().getDevice();
3937 	const vk::VkQueue				queue			= context.getContext().getQueue();
3938 	const vk::VkCommandPool			commandPool		= context.getContext().getCommandPool();
3939 	const vector<deUint32>&			queueFamilies	= context.getContext().getQueueFamilies();
3940 
3941 	m_imageWidth		= context.getImageWidth();
3942 	m_imageHeight		= context.getImageHeight();
3943 	m_imageMemorySize	= context.getImageMemorySize();
3944 
3945 	if (m_scale == BLIT_SCALE_10)
3946 	{
3947 		m_dstImageWidth		= context.getImageWidth();
3948 		m_dstImageHeight	= context.getImageHeight();
3949 	}
3950 	else if (m_scale == BLIT_SCALE_20)
3951 	{
3952 		m_dstImageWidth		= context.getImageWidth() * 2;
3953 		m_dstImageHeight	= context.getImageHeight() * 2;
3954 	}
3955 	else
3956 		DE_FATAL("Unsupportd blit scale");
3957 
3958 	{
3959 		const vk::VkImageCreateInfo	createInfo =
3960 		{
3961 			vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3962 			DE_NULL,
3963 
3964 			0,
3965 			vk::VK_IMAGE_TYPE_2D,
3966 			vk::VK_FORMAT_R8G8B8A8_UNORM,
3967 			{
3968 				(deUint32)m_dstImageWidth,
3969 				(deUint32)m_dstImageHeight,
3970 				1u,
3971 			},
3972 			1, 1, // mipLevels, arrayLayers
3973 			vk::VK_SAMPLE_COUNT_1_BIT,
3974 
3975 			vk::VK_IMAGE_TILING_OPTIMAL,
3976 			vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3977 			vk::VK_SHARING_MODE_EXCLUSIVE,
3978 
3979 			(deUint32)queueFamilies.size(),
3980 			&queueFamilies[0],
3981 			vk::VK_IMAGE_LAYOUT_UNDEFINED
3982 		};
3983 
3984 		m_dstImage = vk::createImage(vkd, device, &createInfo);
3985 	}
3986 
3987 	m_memory = bindImageMemory(vki, vkd, physicalDevice, device, *m_dstImage, 0);
3988 
3989 	{
3990 		const vk::Unique<vk::VkCommandBuffer>	commandBuffer	(createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3991 		const vk::VkImageMemoryBarrier			barrier			=
3992 		{
3993 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3994 			DE_NULL,
3995 
3996 			0,
3997 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3998 
3999 			vk::VK_IMAGE_LAYOUT_UNDEFINED,
4000 			vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4001 
4002 			vk::VK_QUEUE_FAMILY_IGNORED,
4003 			vk::VK_QUEUE_FAMILY_IGNORED,
4004 
4005 			*m_dstImage,
4006 			{
4007 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
4008 				0,	// Mip level
4009 				1,	// Mip level count
4010 				0,	// Layer
4011 				1	// Layer count
4012 			}
4013 		};
4014 
4015 		vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
4016 
4017 		VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
4018 		queueRun(vkd, queue, *commandBuffer);
4019 	}
4020 }
4021 
logSubmit(TestLog & log,size_t commandIndex) const4022 void ImageBlitToImage::logSubmit (TestLog& log, size_t commandIndex) const
4023 {
4024 	log << TestLog::Message << commandIndex << ":" << getName() << " Blit image to another image" << (m_scale == BLIT_SCALE_20 ? " scale 2x" : "")  << TestLog::EndMessage;
4025 }
4026 
submit(SubmitContext & context)4027 void ImageBlitToImage::submit (SubmitContext& context)
4028 {
4029 	const vk::DeviceInterface&	vkd				= context.getContext().getDeviceInterface();
4030 	const vk::VkCommandBuffer	commandBuffer	= context.getCommandBuffer();
4031 	const vk::VkImageBlit		region			=
4032 	{
4033 		// Src
4034 		{
4035 			vk::VK_IMAGE_ASPECT_COLOR_BIT,
4036 			0,	// mipLevel
4037 			0,	// arrayLayer
4038 			1	// layerCount
4039 		},
4040 		{
4041 			{ 0, 0, 0 },
4042 			{
4043 				m_imageWidth,
4044 				m_imageHeight,
4045 				1
4046 			},
4047 		},
4048 
4049 		// Dst
4050 		{
4051 			vk::VK_IMAGE_ASPECT_COLOR_BIT,
4052 			0,	// mipLevel
4053 			0,	// arrayLayer
4054 			1	// layerCount
4055 		},
4056 		{
4057 			{ 0, 0, 0 },
4058 			{
4059 				m_dstImageWidth,
4060 				m_dstImageHeight,
4061 				1u
4062 			}
4063 		}
4064 	};
4065 	vkd.cmdBlitImage(commandBuffer, context.getImage(), m_imageLayout, *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region, vk::VK_FILTER_NEAREST);
4066 }
4067 
verify(VerifyContext & context,size_t commandIndex)4068 void ImageBlitToImage::verify (VerifyContext& context, size_t commandIndex)
4069 {
4070 	tcu::ResultCollector&					resultCollector	(context.getResultCollector());
4071 	const vk::InstanceInterface&			vki				= context.getContext().getInstanceInterface();
4072 	const vk::DeviceInterface&				vkd				= context.getContext().getDeviceInterface();
4073 	const vk::VkPhysicalDevice				physicalDevice	= context.getContext().getPhysicalDevice();
4074 	const vk::VkDevice						device			= context.getContext().getDevice();
4075 	const vk::VkQueue						queue			= context.getContext().getQueue();
4076 	const vk::VkCommandPool					commandPool		= context.getContext().getCommandPool();
4077 	const vk::Unique<vk::VkCommandBuffer>	commandBuffer	(createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
4078 	const vector<deUint32>&					queueFamilies	= context.getContext().getQueueFamilies();
4079 	const vk::Unique<vk::VkBuffer>			dstBuffer		(createBuffer(vkd, device, 4 * m_dstImageWidth * m_dstImageHeight, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies));
4080 	const vk::Unique<vk::VkDeviceMemory>	memory			(bindBufferMemory(vki, vkd, physicalDevice, device, *dstBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
4081 	{
4082 		const vk::VkImageMemoryBarrier		imageBarrier	=
4083 		{
4084 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
4085 			DE_NULL,
4086 
4087 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,
4088 			vk::VK_ACCESS_TRANSFER_READ_BIT,
4089 
4090 			vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4091 			vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4092 
4093 			vk::VK_QUEUE_FAMILY_IGNORED,
4094 			vk::VK_QUEUE_FAMILY_IGNORED,
4095 
4096 			*m_dstImage,
4097 			{
4098 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
4099 				0,	// Mip level
4100 				1,	// Mip level count
4101 				0,	// Layer
4102 				1	// Layer count
4103 			}
4104 		};
4105 		const vk::VkBufferMemoryBarrier bufferBarrier =
4106 		{
4107 			vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
4108 			DE_NULL,
4109 
4110 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,
4111 			vk::VK_ACCESS_HOST_READ_BIT,
4112 
4113 			vk::VK_QUEUE_FAMILY_IGNORED,
4114 			vk::VK_QUEUE_FAMILY_IGNORED,
4115 			*dstBuffer,
4116 			0,
4117 			vk::VK_WHOLE_SIZE
4118 		};
4119 		const vk::VkBufferImageCopy	region =
4120 		{
4121 			0,
4122 			0, 0,
4123 			{
4124 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
4125 				0,	// mipLevel
4126 				0,	// arrayLayer
4127 				1	// layerCount
4128 			},
4129 			{ 0, 0, 0 },
4130 			{
4131 				(deUint32)m_dstImageWidth,
4132 				(deUint32)m_dstImageHeight,
4133 				1
4134 			}
4135 		};
4136 
4137 		vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &imageBarrier);
4138 		vkd.cmdCopyImageToBuffer(*commandBuffer, *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dstBuffer, 1, &region);
4139 		vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
4140 	}
4141 
4142 	VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
4143 	queueRun(vkd, queue, *commandBuffer);
4144 
4145 	{
4146 		void* const	ptr		= mapMemory(vkd, device, *memory, 4 * m_dstImageWidth * m_dstImageHeight);
4147 
4148 		vk::invalidateMappedMemoryRange(vkd, device, *memory, 0,  4 * m_dstImageWidth * m_dstImageHeight);
4149 
4150 		if (m_scale == BLIT_SCALE_10)
4151 		{
4152 			const deUint8* const			data		= (const deUint8*)ptr;
4153 			const ConstPixelBufferAccess	resAccess	(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_dstImageWidth, m_dstImageHeight, 1, data);
4154 			const ConstPixelBufferAccess&	refAccess	(context.getReferenceImage().getAccess());
4155 
4156 			if (!tcu::intThresholdCompare(context.getLog(), (de::toString(commandIndex) + ":" + getName()).c_str(), (de::toString(commandIndex) + ":" + getName()).c_str(), refAccess, resAccess, UVec4(0), tcu::COMPARE_LOG_ON_ERROR))
4157 				resultCollector.fail(de::toString(commandIndex) + ":" + getName() + " Image comparison failed");
4158 		}
4159 		else if (m_scale == BLIT_SCALE_20)
4160 		{
4161 			const deUint8* const			data		= (const deUint8*)ptr;
4162 			const ConstPixelBufferAccess	resAccess	(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_dstImageWidth, m_dstImageHeight, 1, data);
4163 			tcu::TextureLevel				reference	(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_dstImageWidth, m_dstImageHeight, 1);
4164 
4165 			{
4166 				const ConstPixelBufferAccess&	refAccess	(context.getReferenceImage().getAccess());
4167 
4168 				for (deInt32 y = 0; y < m_dstImageHeight; y++)
4169 				for (deInt32 x = 0; x < m_dstImageWidth; x++)
4170 				{
4171 					reference.getAccess().setPixel(refAccess.getPixel(x/2, y/2), x, y);
4172 				}
4173 			}
4174 
4175 			if (!tcu::intThresholdCompare(context.getLog(), (de::toString(commandIndex) + ":" + getName()).c_str(), (de::toString(commandIndex) + ":" + getName()).c_str(), reference.getAccess(), resAccess, UVec4(0), tcu::COMPARE_LOG_ON_ERROR))
4176 				resultCollector.fail(de::toString(commandIndex) + ":" + getName() + " Image comparison failed");
4177 		}
4178 		else
4179 			DE_FATAL("Unknown scale");
4180 
4181 		vkd.unmapMemory(device, *memory);
4182 	}
4183 }
4184 
4185 class PrepareRenderPassContext
4186 {
4187 public:
PrepareRenderPassContext(PrepareContext & context,vk::VkRenderPass renderPass,vk::VkFramebuffer framebuffer,deInt32 targetWidth,deInt32 targetHeight)4188 								PrepareRenderPassContext	(PrepareContext&	context,
4189 															 vk::VkRenderPass	renderPass,
4190 															 vk::VkFramebuffer	framebuffer,
4191 															 deInt32			targetWidth,
4192 															 deInt32			targetHeight)
4193 		: m_context			(context)
4194 		, m_renderPass		(renderPass)
4195 		, m_framebuffer		(framebuffer)
4196 		, m_targetWidth		(targetWidth)
4197 		, m_targetHeight	(targetHeight)
4198 	{
4199 	}
4200 
getMemory(void) const4201 	const Memory&									getMemory					(void) const { return m_context.getMemory(); }
getContext(void) const4202 	const Context&									getContext					(void) const { return m_context.getContext(); }
getBinaryCollection(void) const4203 	const vk::ProgramCollection<vk::ProgramBinary>&	getBinaryCollection			(void) const { return m_context.getBinaryCollection(); }
4204 
getBuffer(void) const4205 	vk::VkBuffer				getBuffer					(void) const { return m_context.getBuffer(); }
getBufferSize(void) const4206 	vk::VkDeviceSize			getBufferSize				(void) const { return m_context.getBufferSize(); }
4207 
getImage(void) const4208 	vk::VkImage					getImage					(void) const { return m_context.getImage(); }
getImageWidth(void) const4209 	deInt32						getImageWidth				(void) const { return m_context.getImageWidth(); }
getImageHeight(void) const4210 	deInt32						getImageHeight				(void) const { return m_context.getImageHeight(); }
getImageLayout(void) const4211 	vk::VkImageLayout			getImageLayout				(void) const { return m_context.getImageLayout(); }
4212 
getTargetWidth(void) const4213 	deInt32						getTargetWidth				(void) const { return m_targetWidth; }
getTargetHeight(void) const4214 	deInt32						getTargetHeight				(void) const { return m_targetHeight; }
4215 
getRenderPass(void) const4216 	vk::VkRenderPass			getRenderPass				(void) const { return m_renderPass; }
4217 
4218 private:
4219 	PrepareContext&				m_context;
4220 	const vk::VkRenderPass		m_renderPass;
4221 	const vk::VkFramebuffer		m_framebuffer;
4222 	const deInt32				m_targetWidth;
4223 	const deInt32				m_targetHeight;
4224 };
4225 
4226 class VerifyRenderPassContext
4227 {
4228 public:
VerifyRenderPassContext(VerifyContext & context,deInt32 targetWidth,deInt32 targetHeight)4229 							VerifyRenderPassContext		(VerifyContext&			context,
4230 														 deInt32				targetWidth,
4231 														 deInt32				targetHeight)
4232 		: m_context			(context)
4233 		, m_referenceTarget	(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), targetWidth, targetHeight)
4234 	{
4235 	}
4236 
getContext(void) const4237 	const Context&			getContext			(void) const { return m_context.getContext(); }
getLog(void) const4238 	TestLog&				getLog				(void) const { return m_context.getLog(); }
getResultCollector(void) const4239 	tcu::ResultCollector&	getResultCollector	(void) const { return m_context.getResultCollector(); }
4240 
getReferenceTarget(void)4241 	TextureLevel&			getReferenceTarget	(void) { return m_referenceTarget; }
4242 
getReference(void)4243 	ReferenceMemory&		getReference		(void) { return m_context.getReference(); }
getReferenceImage(void)4244 	TextureLevel&			getReferenceImage	(void) { return m_context.getReferenceImage();}
4245 
4246 private:
4247 	VerifyContext&	m_context;
4248 	TextureLevel	m_referenceTarget;
4249 };
4250 
4251 
4252 class RenderPassCommand
4253 {
4254 public:
~RenderPassCommand(void)4255 	virtual				~RenderPassCommand	(void) {}
4256 	virtual const char*	getName				(void) const = 0;
4257 
4258 	// Log things that are done during prepare
logPrepare(TestLog &,size_t) const4259 	virtual void		logPrepare			(TestLog&, size_t) const {}
4260 	// Log submitted calls etc.
logSubmit(TestLog &,size_t) const4261 	virtual void		logSubmit			(TestLog&, size_t) const {}
4262 
4263 	// Allocate vulkan resources and prepare for submit.
prepare(PrepareRenderPassContext &)4264 	virtual void		prepare				(PrepareRenderPassContext&) {}
4265 
4266 	// Submit commands to command buffer.
submit(SubmitContext &)4267 	virtual void		submit				(SubmitContext&) {}
4268 
4269 	// Verify results
verify(VerifyRenderPassContext &,size_t)4270 	virtual void		verify				(VerifyRenderPassContext&, size_t) {}
4271 };
4272 
4273 class SubmitRenderPass : public CmdCommand
4274 {
4275 public:
4276 				SubmitRenderPass	(const vector<RenderPassCommand*>& commands);
4277 				~SubmitRenderPass	(void);
getName(void) const4278 	const char*	getName				(void) const { return "SubmitRenderPass"; }
4279 
4280 	void		logPrepare			(TestLog&, size_t) const;
4281 	void		logSubmit			(TestLog&, size_t) const;
4282 
4283 	void		prepare				(PrepareContext&);
4284 	void		submit				(SubmitContext&);
4285 
4286 	void		verify				(VerifyContext&, size_t);
4287 
4288 private:
4289 	const deInt32					m_targetWidth;
4290 	const deInt32					m_targetHeight;
4291 	vk::Move<vk::VkRenderPass>		m_renderPass;
4292 	vk::Move<vk::VkDeviceMemory>	m_colorTargetMemory;
4293 	de::MovePtr<vk::Allocation>		m_colorTargetMemory2;
4294 	vk::Move<vk::VkImage>			m_colorTarget;
4295 	vk::Move<vk::VkImageView>		m_colorTargetView;
4296 	vk::Move<vk::VkFramebuffer>		m_framebuffer;
4297 	vector<RenderPassCommand*>		m_commands;
4298 };
4299 
SubmitRenderPass(const vector<RenderPassCommand * > & commands)4300 SubmitRenderPass::SubmitRenderPass (const vector<RenderPassCommand*>& commands)
4301 	: m_targetWidth		(256)
4302 	, m_targetHeight	(256)
4303 	, m_commands		(commands)
4304 {
4305 }
4306 
~SubmitRenderPass()4307 SubmitRenderPass::~SubmitRenderPass()
4308 {
4309 	for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4310 		delete m_commands[cmdNdx];
4311 }
4312 
logPrepare(TestLog & log,size_t commandIndex) const4313 void SubmitRenderPass::logPrepare (TestLog& log, size_t commandIndex) const
4314 {
4315 	const string				sectionName	(de::toString(commandIndex) + ":" + getName());
4316 	const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
4317 
4318 	for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4319 	{
4320 		RenderPassCommand& command = *m_commands[cmdNdx];
4321 		command.logPrepare(log, cmdNdx);
4322 	}
4323 }
4324 
logSubmit(TestLog & log,size_t commandIndex) const4325 void SubmitRenderPass::logSubmit (TestLog& log, size_t commandIndex) const
4326 {
4327 	const string				sectionName	(de::toString(commandIndex) + ":" + getName());
4328 	const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
4329 
4330 	for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4331 	{
4332 		RenderPassCommand& command = *m_commands[cmdNdx];
4333 		command.logSubmit(log, cmdNdx);
4334 	}
4335 }
4336 
prepare(PrepareContext & context)4337 void SubmitRenderPass::prepare (PrepareContext& context)
4338 {
4339 	const vk::InstanceInterface&			vki				= context.getContext().getInstanceInterface();
4340 	const vk::DeviceInterface&				vkd				= context.getContext().getDeviceInterface();
4341 	const vk::VkPhysicalDevice				physicalDevice	= context.getContext().getPhysicalDevice();
4342 	const vk::VkDevice						device			= context.getContext().getDevice();
4343 	const vector<deUint32>&					queueFamilies	= context.getContext().getQueueFamilies();
4344 
4345 	const vk::VkAttachmentReference	colorAttachments[]	=
4346 	{
4347 		{ 0, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }
4348 	};
4349 	const vk::VkSubpassDescription	subpass				=
4350 	{
4351 		0u,
4352 		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
4353 
4354 		0u,
4355 		DE_NULL,
4356 
4357 		DE_LENGTH_OF_ARRAY(colorAttachments),
4358 		colorAttachments,
4359 		DE_NULL,
4360 		DE_NULL,
4361 		0u,
4362 		DE_NULL
4363 	};
4364 	const vk::VkAttachmentDescription attachment =
4365 	{
4366 		0u,
4367 		vk::VK_FORMAT_R8G8B8A8_UNORM,
4368 		vk::VK_SAMPLE_COUNT_1_BIT,
4369 
4370 		vk::VK_ATTACHMENT_LOAD_OP_CLEAR,
4371 		vk::VK_ATTACHMENT_STORE_OP_STORE,
4372 
4373 		vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4374 		vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
4375 
4376 		vk::VK_IMAGE_LAYOUT_UNDEFINED,
4377 		vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
4378 	};
4379 	{
4380 		const vk::VkImageCreateInfo createInfo =
4381 		{
4382 			vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
4383 			DE_NULL,
4384 			0u,
4385 
4386 			vk::VK_IMAGE_TYPE_2D,
4387 			vk::VK_FORMAT_R8G8B8A8_UNORM,
4388 			{ (deUint32)m_targetWidth, (deUint32)m_targetHeight, 1u },
4389 			1u,
4390 			1u,
4391 			vk::VK_SAMPLE_COUNT_1_BIT,
4392 			vk::VK_IMAGE_TILING_OPTIMAL,
4393 			vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
4394 			vk::VK_SHARING_MODE_EXCLUSIVE,
4395 			(deUint32)queueFamilies.size(),
4396 			&queueFamilies[0],
4397 			vk::VK_IMAGE_LAYOUT_UNDEFINED
4398 		};
4399 
4400 		m_colorTarget = vk::createImage(vkd, device, &createInfo);
4401 	}
4402 
4403 	m_colorTargetMemory = bindImageMemory(vki, vkd, physicalDevice, device, *m_colorTarget, 0);
4404 
4405 	{
4406 		const vk::VkImageViewCreateInfo createInfo =
4407 		{
4408 			vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
4409 			DE_NULL,
4410 
4411 			0u,
4412 			*m_colorTarget,
4413 			vk::VK_IMAGE_VIEW_TYPE_2D,
4414 			vk::VK_FORMAT_R8G8B8A8_UNORM,
4415 			{
4416 				vk::VK_COMPONENT_SWIZZLE_R,
4417 				vk::VK_COMPONENT_SWIZZLE_G,
4418 				vk::VK_COMPONENT_SWIZZLE_B,
4419 				vk::VK_COMPONENT_SWIZZLE_A
4420 			},
4421 			{
4422 				vk::VK_IMAGE_ASPECT_COLOR_BIT,
4423 				0u,
4424 				1u,
4425 				0u,
4426 				1u
4427 			}
4428 		};
4429 
4430 		m_colorTargetView = vk::createImageView(vkd, device, &createInfo);
4431 	}
4432 	{
4433 		const vk::VkRenderPassCreateInfo createInfo =
4434 		{
4435 			vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
4436 			DE_NULL,
4437 			0u,
4438 
4439 			1u,
4440 			&attachment,
4441 
4442 			1u,
4443 			&subpass,
4444 
4445 			0,
4446 			DE_NULL
4447 		};
4448 
4449 		m_renderPass = vk::createRenderPass(vkd, device, &createInfo);
4450 	}
4451 
4452 	{
4453 		const vk::VkImageView				imageViews[]	=
4454 		{
4455 			*m_colorTargetView
4456 		};
4457 		const vk::VkFramebufferCreateInfo	createInfo		=
4458 		{
4459 			vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
4460 			DE_NULL,
4461 			0u,
4462 
4463 			*m_renderPass,
4464 			DE_LENGTH_OF_ARRAY(imageViews),
4465 			imageViews,
4466 			(deUint32)m_targetWidth,
4467 			(deUint32)m_targetHeight,
4468 			1u
4469 		};
4470 
4471 		m_framebuffer = vk::createFramebuffer(vkd, device, &createInfo);
4472 	}
4473 
4474 	{
4475 		PrepareRenderPassContext renderpassContext (context, *m_renderPass, *m_framebuffer, m_targetWidth, m_targetHeight);
4476 
4477 		for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4478 		{
4479 			RenderPassCommand& command = *m_commands[cmdNdx];
4480 			command.prepare(renderpassContext);
4481 		}
4482 	}
4483 }
4484 
submit(SubmitContext & context)4485 void SubmitRenderPass::submit (SubmitContext& context)
4486 {
4487 	const vk::DeviceInterface&		vkd				= context.getContext().getDeviceInterface();
4488 	const vk::VkCommandBuffer		commandBuffer	= context.getCommandBuffer();
4489 	const vk::VkClearValue			clearValue		= vk::makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f);
4490 
4491 	const vk::VkRenderPassBeginInfo	beginInfo		=
4492 	{
4493 		vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
4494 		DE_NULL,
4495 
4496 		*m_renderPass,
4497 		*m_framebuffer,
4498 
4499 		{ { 0, 0 },  { (deUint32)m_targetWidth, (deUint32)m_targetHeight } },
4500 		1u,
4501 		&clearValue
4502 	};
4503 
4504 	vkd.cmdBeginRenderPass(commandBuffer, &beginInfo, vk::VK_SUBPASS_CONTENTS_INLINE);
4505 
4506 	for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4507 	{
4508 		RenderPassCommand& command = *m_commands[cmdNdx];
4509 
4510 		command.submit(context);
4511 	}
4512 
4513 	vkd.cmdEndRenderPass(commandBuffer);
4514 }
4515 
verify(VerifyContext & context,size_t commandIndex)4516 void SubmitRenderPass::verify (VerifyContext& context, size_t commandIndex)
4517 {
4518 	TestLog&					log				(context.getLog());
4519 	tcu::ResultCollector&		resultCollector	(context.getResultCollector());
4520 	const string				sectionName		(de::toString(commandIndex) + ":" + getName());
4521 	const tcu::ScopedLogSection	section			(log, sectionName, sectionName);
4522 	VerifyRenderPassContext		verifyContext	(context, m_targetWidth, m_targetHeight);
4523 
4524 	tcu::clear(verifyContext.getReferenceTarget().getAccess(), Vec4(0.0f, 0.0f, 0.0f, 1.0f));
4525 
4526 	for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4527 	{
4528 		RenderPassCommand& command = *m_commands[cmdNdx];
4529 		command.verify(verifyContext, cmdNdx);
4530 	}
4531 
4532 	{
4533 		const vk::InstanceInterface&			vki				= context.getContext().getInstanceInterface();
4534 		const vk::DeviceInterface&				vkd				= context.getContext().getDeviceInterface();
4535 		const vk::VkPhysicalDevice				physicalDevice	= context.getContext().getPhysicalDevice();
4536 		const vk::VkDevice						device			= context.getContext().getDevice();
4537 		const vk::VkQueue						queue			= context.getContext().getQueue();
4538 		const vk::VkCommandPool					commandPool		= context.getContext().getCommandPool();
4539 		const vk::Unique<vk::VkCommandBuffer>	commandBuffer	(createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
4540 		const vector<deUint32>&					queueFamilies	= context.getContext().getQueueFamilies();
4541 		const vk::Unique<vk::VkBuffer>			dstBuffer		(createBuffer(vkd, device, 4 * m_targetWidth * m_targetHeight, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies));
4542 		const vk::Unique<vk::VkDeviceMemory>	memory			(bindBufferMemory(vki, vkd, physicalDevice, device, *dstBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
4543 		{
4544 			const vk::VkImageMemoryBarrier		imageBarrier	=
4545 			{
4546 				vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
4547 				DE_NULL,
4548 
4549 				vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
4550 				vk::VK_ACCESS_TRANSFER_READ_BIT,
4551 
4552 				vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4553 				vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4554 
4555 				vk::VK_QUEUE_FAMILY_IGNORED,
4556 				vk::VK_QUEUE_FAMILY_IGNORED,
4557 
4558 				*m_colorTarget,
4559 				{
4560 					vk::VK_IMAGE_ASPECT_COLOR_BIT,
4561 					0,	// Mip level
4562 					1,	// Mip level count
4563 					0,	// Layer
4564 					1	// Layer count
4565 				}
4566 			};
4567 			const vk::VkBufferMemoryBarrier bufferBarrier =
4568 			{
4569 				vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
4570 				DE_NULL,
4571 
4572 				vk::VK_ACCESS_TRANSFER_WRITE_BIT,
4573 				vk::VK_ACCESS_HOST_READ_BIT,
4574 
4575 				vk::VK_QUEUE_FAMILY_IGNORED,
4576 				vk::VK_QUEUE_FAMILY_IGNORED,
4577 				*dstBuffer,
4578 				0,
4579 				vk::VK_WHOLE_SIZE
4580 			};
4581 			const vk::VkBufferImageCopy	region =
4582 			{
4583 				0,
4584 				0, 0,
4585 				{
4586 					vk::VK_IMAGE_ASPECT_COLOR_BIT,
4587 					0,	// mipLevel
4588 					0,	// arrayLayer
4589 					1	// layerCount
4590 				},
4591 				{ 0, 0, 0 },
4592 				{
4593 					(deUint32)m_targetWidth,
4594 					(deUint32)m_targetHeight,
4595 					1u
4596 				}
4597 			};
4598 
4599 			vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &imageBarrier);
4600 			vkd.cmdCopyImageToBuffer(*commandBuffer, *m_colorTarget, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dstBuffer, 1, &region);
4601 			vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
4602 		}
4603 
4604 		VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
4605 		queueRun(vkd, queue, *commandBuffer);
4606 
4607 		{
4608 			void* const	ptr		= mapMemory(vkd, device, *memory, 4 * m_targetWidth * m_targetHeight);
4609 
4610 			vk::invalidateMappedMemoryRange(vkd, device, *memory, 0,  4 * m_targetWidth * m_targetHeight);
4611 
4612 			{
4613 				const deUint8* const			data		= (const deUint8*)ptr;
4614 				const ConstPixelBufferAccess	resAccess	(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_targetWidth, m_targetHeight, 1, data);
4615 				const ConstPixelBufferAccess&	refAccess	(verifyContext.getReferenceTarget().getAccess());
4616 
4617 				if (!tcu::intThresholdCompare(context.getLog(), (de::toString(commandIndex) + ":" + getName()).c_str(), (de::toString(commandIndex) + ":" + getName()).c_str(), refAccess, resAccess, UVec4(0), tcu::COMPARE_LOG_ON_ERROR))
4618 					resultCollector.fail(de::toString(commandIndex) + ":" + getName() + " Image comparison failed");
4619 			}
4620 
4621 			vkd.unmapMemory(device, *memory);
4622 		}
4623 	}
4624 }
4625 
4626 class RenderBuffer : public RenderPassCommand
4627 {
4628 public:
4629 	enum RenderAs
4630 	{
4631 		RENDERAS_VERTEX_BUFFER,
4632 		RENDERAS_INDEX_BUFFER,
4633 	};
RenderBuffer(RenderAs renderAs)4634 				RenderBuffer		(RenderAs renderAs) : m_renderAs(renderAs) {}
~RenderBuffer(void)4635 				~RenderBuffer		(void) {}
4636 
getName(void) const4637 	const char*	getName				(void) const { return "RenderBuffer"; }
4638 	void		logPrepare			(TestLog&, size_t) const;
4639 	void		logSubmit			(TestLog&, size_t) const;
4640 	void		prepare				(PrepareRenderPassContext&);
4641 	void		submit				(SubmitContext& context);
4642 	void		verify				(VerifyRenderPassContext&, size_t);
4643 
4644 private:
4645 	const RenderAs						m_renderAs;
4646 	vk::Move<vk::VkPipeline>			m_pipeline;
4647 	vk::Move<vk::VkPipelineLayout>		m_pipelineLayout;
4648 	vk::VkDeviceSize					m_bufferSize;
4649 
getVertexShader(const vk::ProgramCollection<vk::ProgramBinary> & collections,RenderAs renderAs)4650 	static const vk::ProgramBinary&		getVertexShader		(const vk::ProgramCollection<vk::ProgramBinary>& collections, RenderAs renderAs)
4651 	{
4652 		switch (renderAs)
4653 		{
4654 			case RENDERAS_VERTEX_BUFFER:
4655 				return collections.get("vertex-buffer.vert");
4656 
4657 			case RENDERAS_INDEX_BUFFER:
4658 				return collections.get("index-buffer.vert");
4659 
4660 			default:
4661 				DE_FATAL("Unknown renderAs");
4662 				return collections.get("");
4663 		}
4664 	}
4665 };
4666 
logPrepare(TestLog & log,size_t commandIndex) const4667 void RenderBuffer::logPrepare (TestLog& log, size_t commandIndex) const
4668 {
4669 	log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render buffer as " << (m_renderAs == RENDERAS_VERTEX_BUFFER ? "vertex" : "index") << " buffer." << TestLog::EndMessage;
4670 }
4671 
logSubmit(TestLog & log,size_t commandIndex) const4672 void RenderBuffer::logSubmit (TestLog& log, size_t commandIndex) const
4673 {
4674 	log << TestLog::Message << commandIndex << ":" << getName() << " Render using buffer as " << (m_renderAs == RENDERAS_VERTEX_BUFFER ? "vertex" : "index") << " buffer." << TestLog::EndMessage;
4675 }
4676 
prepare(PrepareRenderPassContext & context)4677 void RenderBuffer::prepare (PrepareRenderPassContext& context)
4678 {
4679 	const vk::DeviceInterface&				vkd						= context.getContext().getDeviceInterface();
4680 	const vk::VkDevice						device					= context.getContext().getDevice();
4681 	const vk::VkRenderPass					renderPass				= context.getRenderPass();
4682 	const deUint32							subpass					= 0;
4683 	const vk::Unique<vk::VkShaderModule>	vertexShaderModule		(vk::createShaderModule(vkd, device, getVertexShader(context.getBinaryCollection(), m_renderAs), 0));
4684 	const vk::Unique<vk::VkShaderModule>	fragmentShaderModule	(vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-white.frag"), 0));
4685 
4686 	m_bufferSize = context.getBufferSize();
4687 
4688 	{
4689 		const vk::VkPipelineLayoutCreateInfo	createInfo	=
4690 		{
4691 			vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
4692 			DE_NULL,
4693 			0,
4694 			0,
4695 			DE_NULL,
4696 			0,
4697 			DE_NULL
4698 		};
4699 
4700 		m_pipelineLayout = vk::createPipelineLayout(vkd, device, &createInfo);
4701 	}
4702 
4703 	{
4704 		const vk::VkPipelineShaderStageCreateInfo			shaderStages[]					=
4705 		{
4706 			{
4707 				vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
4708 				DE_NULL,
4709 				0,
4710 				vk::VK_SHADER_STAGE_VERTEX_BIT,
4711 				*vertexShaderModule,
4712 				"main",
4713 				DE_NULL
4714 			},
4715 			{
4716 				vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
4717 				DE_NULL,
4718 				0,
4719 				vk::VK_SHADER_STAGE_FRAGMENT_BIT,
4720 				*fragmentShaderModule,
4721 				"main",
4722 				DE_NULL
4723 			}
4724 		};
4725 		const vk::VkPipelineDepthStencilStateCreateInfo		depthStencilState				=
4726 		{
4727 			vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
4728 			DE_NULL,
4729 			0u,
4730 			DE_FALSE,
4731 			DE_FALSE,
4732 			vk::VK_COMPARE_OP_ALWAYS,
4733 			DE_FALSE,
4734 			DE_FALSE,
4735 			{
4736 				vk::VK_STENCIL_OP_KEEP,
4737 				vk::VK_STENCIL_OP_KEEP,
4738 				vk::VK_STENCIL_OP_KEEP,
4739 				vk::VK_COMPARE_OP_ALWAYS,
4740 				0u,
4741 				0u,
4742 				0u,
4743 			},
4744 			{
4745 				vk::VK_STENCIL_OP_KEEP,
4746 				vk::VK_STENCIL_OP_KEEP,
4747 				vk::VK_STENCIL_OP_KEEP,
4748 				vk::VK_COMPARE_OP_ALWAYS,
4749 				0u,
4750 				0u,
4751 				0u,
4752 			},
4753 			-1.0f,
4754 			+1.0f
4755 		};
4756 		const vk::VkVertexInputBindingDescription			vertexBindingDescriptions[]		=
4757 		{
4758 			{
4759 				0,
4760 				2,
4761 				vk::VK_VERTEX_INPUT_RATE_VERTEX
4762 			}
4763 		};
4764 		const vk::VkVertexInputAttributeDescription			vertexAttributeDescriptions[]	=
4765 		{
4766 			{
4767 				0,
4768 				0,
4769 				vk::VK_FORMAT_R8G8_UNORM,
4770 				0
4771 			}
4772 		};
4773 		const vk::VkPipelineVertexInputStateCreateInfo		vertexInputState				=
4774 		{
4775 			vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
4776 			DE_NULL,
4777 			0u,
4778 
4779 			m_renderAs == RENDERAS_VERTEX_BUFFER ? DE_LENGTH_OF_ARRAY(vertexBindingDescriptions) : 0u,
4780 			m_renderAs == RENDERAS_VERTEX_BUFFER ? vertexBindingDescriptions : DE_NULL,
4781 
4782 			m_renderAs == RENDERAS_VERTEX_BUFFER ? DE_LENGTH_OF_ARRAY(vertexAttributeDescriptions) : 0u,
4783 			m_renderAs == RENDERAS_VERTEX_BUFFER ? vertexAttributeDescriptions : DE_NULL,
4784 		};
4785 		const vk::VkPipelineInputAssemblyStateCreateInfo	inputAssemblyState				=
4786 		{
4787 			vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
4788 			DE_NULL,
4789 			0,
4790 			vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
4791 			vk::VK_FALSE
4792 		};
4793 		const vk::VkViewport								viewports[]						=
4794 		{
4795 			{ 0.0f, 0.0f, (float)context.getTargetWidth(), (float)context.getTargetHeight(), 0.0f, 1.0f }
4796 		};
4797 		const vk::VkRect2D									scissors[]						=
4798 		{
4799 			{ { 0, 0 }, { (deUint32)context.getTargetWidth(), (deUint32)context.getTargetHeight() } }
4800 		};
4801 		const vk::VkPipelineViewportStateCreateInfo			viewportState					=
4802 		{
4803 			vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
4804 			DE_NULL,
4805 			0,
4806 			DE_LENGTH_OF_ARRAY(viewports),
4807 			viewports,
4808 			DE_LENGTH_OF_ARRAY(scissors),
4809 			scissors
4810 		};
4811 		const vk::VkPipelineRasterizationStateCreateInfo	rasterState						=
4812 		{
4813 			vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
4814 			DE_NULL,
4815 			0,
4816 
4817 			vk::VK_TRUE,
4818 			vk::VK_FALSE,
4819 			vk::VK_POLYGON_MODE_FILL,
4820 			vk::VK_CULL_MODE_NONE,
4821 			vk::VK_FRONT_FACE_COUNTER_CLOCKWISE,
4822 			vk::VK_FALSE,
4823 			0.0f,
4824 			0.0f,
4825 			0.0f,
4826 			1.0f
4827 		};
4828 		const vk::VkSampleMask								sampleMask						= ~0u;
4829 		const vk::VkPipelineMultisampleStateCreateInfo		multisampleState				=
4830 		{
4831 			vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
4832 			DE_NULL,
4833 			0,
4834 
4835 			vk::VK_SAMPLE_COUNT_1_BIT,
4836 			vk::VK_FALSE,
4837 			0.0f,
4838 			&sampleMask,
4839 			vk::VK_FALSE,
4840 			vk::VK_FALSE
4841 		};
4842 		const vk::VkPipelineColorBlendAttachmentState		attachments[]					=
4843 		{
4844 			{
4845 				vk::VK_FALSE,
4846 				vk::VK_BLEND_FACTOR_ONE,
4847 				vk::VK_BLEND_FACTOR_ZERO,
4848 				vk::VK_BLEND_OP_ADD,
4849 				vk::VK_BLEND_FACTOR_ONE,
4850 				vk::VK_BLEND_FACTOR_ZERO,
4851 				vk::VK_BLEND_OP_ADD,
4852 				(vk::VK_COLOR_COMPONENT_R_BIT|
4853 				 vk::VK_COLOR_COMPONENT_G_BIT|
4854 				 vk::VK_COLOR_COMPONENT_B_BIT|
4855 				 vk::VK_COLOR_COMPONENT_A_BIT)
4856 			}
4857 		};
4858 		const vk::VkPipelineColorBlendStateCreateInfo		colorBlendState					=
4859 		{
4860 			vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
4861 			DE_NULL,
4862 			0,
4863 
4864 			vk::VK_FALSE,
4865 			vk::VK_LOGIC_OP_COPY,
4866 			DE_LENGTH_OF_ARRAY(attachments),
4867 			attachments,
4868 			{ 0.0f, 0.0f, 0.0f, 0.0f }
4869 		};
4870 		const vk::VkGraphicsPipelineCreateInfo				createInfo						=
4871 		{
4872 			vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
4873 			DE_NULL,
4874 			0u,
4875 
4876 			DE_LENGTH_OF_ARRAY(shaderStages),
4877 			shaderStages,
4878 
4879 			&vertexInputState,
4880 			&inputAssemblyState,
4881 			DE_NULL,
4882 			&viewportState,
4883 			&rasterState,
4884 			&multisampleState,
4885 			&depthStencilState,
4886 			&colorBlendState,
4887 			DE_NULL,
4888 			*m_pipelineLayout,
4889 			renderPass,
4890 			subpass,
4891 			0,
4892 			0
4893 		};
4894 
4895 		m_pipeline = vk::createGraphicsPipeline(vkd, device, 0, &createInfo);
4896 	}
4897 }
4898 
submit(SubmitContext & context)4899 void RenderBuffer::submit (SubmitContext& context)
4900 {
4901 	const vk::DeviceInterface&	vkd				= context.getContext().getDeviceInterface();
4902 	const vk::VkCommandBuffer	commandBuffer	= context.getCommandBuffer();
4903 	const vk::VkDeviceSize		offset			= 0;
4904 	const vk::VkBuffer			buffer			= context.getBuffer();
4905 
4906 	vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
4907 
4908 	if (m_renderAs == RENDERAS_VERTEX_BUFFER)
4909 	{
4910 		vkd.cmdBindVertexBuffers(commandBuffer, 0, 1, &buffer, &offset);
4911 		vkd.cmdDraw(commandBuffer, (deUint32)(context.getBufferSize() / 2), 1, 0, 0);
4912 	}
4913 	else if (m_renderAs == RENDERAS_INDEX_BUFFER)
4914 	{
4915 		vkd.cmdBindIndexBuffer(commandBuffer, context.getBuffer(), 0, vk::VK_INDEX_TYPE_UINT16);
4916 		vkd.cmdDrawIndexed(commandBuffer, (deUint32)(context.getBufferSize() / 2), 1, 0, 0, 0);
4917 	}
4918 	else
4919 		DE_FATAL("Unknown renderAs");
4920 }
4921 
verify(VerifyRenderPassContext & context,size_t)4922 void RenderBuffer::verify (VerifyRenderPassContext& context, size_t)
4923 {
4924 	for (size_t pos = 0; pos < (size_t)m_bufferSize / 2; pos++)
4925 	{
4926 		const deUint8 x  = context.getReference().get(pos * 2);
4927 		const deUint8 y  = context.getReference().get((pos * 2) + 1);
4928 
4929 		context.getReferenceTarget().getAccess().setPixel(Vec4(1.0f, 1.0f, 1.0f, 1.0f), x, y);
4930 	}
4931 }
4932 
4933 enum Op
4934 {
4935 	OP_MAP,
4936 	OP_UNMAP,
4937 
4938 	OP_MAP_FLUSH,
4939 	OP_MAP_INVALIDATE,
4940 
4941 	OP_MAP_READ,
4942 	OP_MAP_WRITE,
4943 	OP_MAP_MODIFY,
4944 
4945 	OP_BUFFER_CREATE,
4946 	OP_BUFFER_DESTROY,
4947 	OP_BUFFER_BINDMEMORY,
4948 
4949 	OP_QUEUE_WAIT_FOR_IDLE,
4950 	OP_DEVICE_WAIT_FOR_IDLE,
4951 
4952 	OP_COMMAND_BUFFER_BEGIN,
4953 	OP_COMMAND_BUFFER_END,
4954 
4955 	// Buffer transfer operations
4956 	OP_BUFFER_FILL,
4957 	OP_BUFFER_UPDATE,
4958 
4959 	OP_BUFFER_COPY_TO_BUFFER,
4960 	OP_BUFFER_COPY_FROM_BUFFER,
4961 
4962 	OP_BUFFER_COPY_TO_IMAGE,
4963 	OP_BUFFER_COPY_FROM_IMAGE,
4964 
4965 	OP_IMAGE_CREATE,
4966 	OP_IMAGE_DESTROY,
4967 	OP_IMAGE_BINDMEMORY,
4968 
4969 	OP_IMAGE_TRANSITION_LAYOUT,
4970 
4971 	OP_IMAGE_COPY_TO_BUFFER,
4972 	OP_IMAGE_COPY_FROM_BUFFER,
4973 
4974 	OP_IMAGE_COPY_TO_IMAGE,
4975 	OP_IMAGE_COPY_FROM_IMAGE,
4976 
4977 	OP_IMAGE_BLIT_TO_IMAGE,
4978 	OP_IMAGE_BLIT_FROM_IMAGE,
4979 
4980 	OP_IMAGE_RESOLVE,
4981 
4982 	OP_PIPELINE_BARRIER_GLOBAL,
4983 	OP_PIPELINE_BARRIER_BUFFER,
4984 	OP_PIPELINE_BARRIER_IMAGE,
4985 
4986 	// Renderpass operations
4987 	OP_RENDERPASS_BEGIN,
4988 	OP_RENDERPASS_END,
4989 
4990 	// Commands inside render pass
4991 	OP_RENDER_VERTEX_BUFFER,
4992 	OP_RENDER_INDEX_BUFFER
4993 };
4994 
4995 enum Stage
4996 {
4997 	STAGE_HOST,
4998 	STAGE_COMMAND_BUFFER,
4999 
5000 	STAGE_RENDER_PASS
5001 };
5002 
getWriteAccessFlags(void)5003 vk::VkAccessFlags getWriteAccessFlags (void)
5004 {
5005 	return vk::VK_ACCESS_SHADER_WRITE_BIT
5006 		| vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
5007 		| vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
5008 		| vk::VK_ACCESS_TRANSFER_WRITE_BIT
5009 		| vk::VK_ACCESS_HOST_WRITE_BIT
5010 		| vk::VK_ACCESS_MEMORY_WRITE_BIT;
5011 }
5012 
isWriteAccess(vk::VkAccessFlagBits access)5013 bool isWriteAccess (vk::VkAccessFlagBits access)
5014 {
5015 	return (getWriteAccessFlags() & access) != 0;
5016 }
5017 
5018 class CacheState
5019 {
5020 public:
5021 									CacheState				(vk::VkPipelineStageFlags allowedStages, vk::VkAccessFlags allowedAccesses);
5022 
5023 	bool							isValid					(vk::VkPipelineStageFlagBits	stage,
5024 															 vk::VkAccessFlagBits			access) const;
5025 
5026 	void							perform					(vk::VkPipelineStageFlagBits	stage,
5027 															 vk::VkAccessFlagBits			access);
5028 
5029 	void							submitCommandBuffer		(void);
5030 	void							waitForIdle				(void);
5031 
5032 	void							getFullBarrier			(vk::VkPipelineStageFlags&	srcStages,
5033 															 vk::VkAccessFlags&			srcAccesses,
5034 															 vk::VkPipelineStageFlags&	dstStages,
5035 															 vk::VkAccessFlags&			dstAccesses) const;
5036 
5037 	void							barrier					(vk::VkPipelineStageFlags	srcStages,
5038 															 vk::VkAccessFlags			srcAccesses,
5039 															 vk::VkPipelineStageFlags	dstStages,
5040 															 vk::VkAccessFlags			dstAccesses);
5041 
5042 	void							imageLayoutBarrier		(vk::VkPipelineStageFlags	srcStages,
5043 															 vk::VkAccessFlags			srcAccesses,
5044 															 vk::VkPipelineStageFlags	dstStages,
5045 															 vk::VkAccessFlags			dstAccesses);
5046 
5047 	void							checkImageLayoutBarrier	(vk::VkPipelineStageFlags	srcStages,
5048 															 vk::VkAccessFlags			srcAccesses,
5049 															 vk::VkPipelineStageFlags	dstStages,
5050 															 vk::VkAccessFlags			dstAccesses);
5051 
5052 	// Everything is clean and there is no need for barriers
5053 	bool							isClean					(void) const;
5054 
getAllowedStages(void) const5055 	vk::VkPipelineStageFlags		getAllowedStages		(void) const { return m_allowedStages; }
getAllowedAcceses(void) const5056 	vk::VkAccessFlags				getAllowedAcceses		(void) const { return m_allowedAccesses; }
5057 private:
5058 	// Limit which stages and accesses are used by the CacheState tracker
5059 	const vk::VkPipelineStageFlags	m_allowedStages;
5060 	const vk::VkAccessFlags			m_allowedAccesses;
5061 
5062 	// [dstStage][srcStage] = srcAccesses
5063 	// In stage dstStage write srcAccesses from srcStage are not yet available
5064 	vk::VkAccessFlags				m_unavailableWriteOperations[PIPELINESTAGE_LAST][PIPELINESTAGE_LAST];
5065 	// Latest pipeline transition is not available in stage
5066 	bool							m_unavailableLayoutTransition[PIPELINESTAGE_LAST];
5067 	// [dstStage] = dstAccesses
5068 	// In stage dstStage ops with dstAccesses are not yet visible
5069 	vk::VkAccessFlags				m_invisibleOperations[PIPELINESTAGE_LAST];
5070 
5071 	// [dstStage] = srcStage
5072 	// Memory operation in srcStage have not completed before dstStage
5073 	vk::VkPipelineStageFlags		m_incompleteOperations[PIPELINESTAGE_LAST];
5074 };
5075 
CacheState(vk::VkPipelineStageFlags allowedStages,vk::VkAccessFlags allowedAccesses)5076 CacheState::CacheState (vk::VkPipelineStageFlags allowedStages, vk::VkAccessFlags allowedAccesses)
5077 	: m_allowedStages	(allowedStages)
5078 	, m_allowedAccesses	(allowedAccesses)
5079 {
5080 	for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
5081 	{
5082 		const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
5083 
5084 		if ((dstStage_ & m_allowedStages) == 0)
5085 			continue;
5086 
5087 		// All operations are initially visible
5088 		m_invisibleOperations[dstStage] = 0;
5089 
5090 		// There are no incomplete read operations initially
5091 		m_incompleteOperations[dstStage] = 0;
5092 
5093 		// There are no incomplete layout transitions
5094 		m_unavailableLayoutTransition[dstStage] = false;
5095 
5096 		for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
5097 		{
5098 			const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
5099 
5100 			if ((srcStage_ & m_allowedStages) == 0)
5101 				continue;
5102 
5103 			// There are no write operations that are not yet available
5104 			// initially.
5105 			m_unavailableWriteOperations[dstStage][srcStage] = 0;
5106 		}
5107 	}
5108 }
5109 
isValid(vk::VkPipelineStageFlagBits stage,vk::VkAccessFlagBits access) const5110 bool CacheState::isValid (vk::VkPipelineStageFlagBits	stage,
5111 						  vk::VkAccessFlagBits			access) const
5112 {
5113 	DE_ASSERT((access & (~m_allowedAccesses)) == 0);
5114 	DE_ASSERT((stage & (~m_allowedStages)) == 0);
5115 
5116 	const PipelineStage	dstStage	= pipelineStageFlagToPipelineStage(stage);
5117 
5118 	// Previous operations are not visible to access on stage
5119 	if (m_unavailableLayoutTransition[dstStage] || (m_invisibleOperations[dstStage] & access) != 0)
5120 		return false;
5121 
5122 	if (isWriteAccess(access))
5123 	{
5124 		// Memory operations from other stages have not completed before
5125 		// dstStage
5126 		if (m_incompleteOperations[dstStage] != 0)
5127 			return false;
5128 	}
5129 
5130 	return true;
5131 }
5132 
perform(vk::VkPipelineStageFlagBits stage,vk::VkAccessFlagBits access)5133 void CacheState::perform (vk::VkPipelineStageFlagBits	stage,
5134 						  vk::VkAccessFlagBits			access)
5135 {
5136 	DE_ASSERT((access & (~m_allowedAccesses)) == 0);
5137 	DE_ASSERT((stage & (~m_allowedStages)) == 0);
5138 
5139 	const PipelineStage srcStage = pipelineStageFlagToPipelineStage(stage);
5140 
5141 	for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
5142 	{
5143 		const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
5144 
5145 		if ((dstStage_ & m_allowedStages) == 0)
5146 			continue;
5147 
5148 		// Mark stage as incomplete for all stages
5149 		m_incompleteOperations[dstStage] |= stage;
5150 
5151 		if (isWriteAccess(access))
5152 		{
5153 			// Mark all accesses from all stages invisible
5154 			m_invisibleOperations[dstStage] |= m_allowedAccesses;
5155 
5156 			// Mark write access from srcStage unavailable to all stages
5157 			m_unavailableWriteOperations[dstStage][srcStage] |= access;
5158 		}
5159 	}
5160 }
5161 
submitCommandBuffer(void)5162 void CacheState::submitCommandBuffer (void)
5163 {
5164 	// Flush all host writes and reads
5165 	barrier(m_allowedStages & vk::VK_PIPELINE_STAGE_HOST_BIT,
5166 			m_allowedAccesses & (vk::VK_ACCESS_HOST_READ_BIT | vk::VK_ACCESS_HOST_WRITE_BIT),
5167 			m_allowedStages,
5168 			m_allowedAccesses);
5169 }
5170 
waitForIdle(void)5171 void CacheState::waitForIdle (void)
5172 {
5173 	// Make all writes available
5174 	barrier(m_allowedStages,
5175 			m_allowedAccesses & getWriteAccessFlags(),
5176 			m_allowedStages,
5177 			0);
5178 
5179 	// Make all writes visible on device side
5180 	barrier(m_allowedStages,
5181 			0,
5182 			m_allowedStages & (~vk::VK_PIPELINE_STAGE_HOST_BIT),
5183 			m_allowedAccesses);
5184 }
5185 
getFullBarrier(vk::VkPipelineStageFlags & srcStages,vk::VkAccessFlags & srcAccesses,vk::VkPipelineStageFlags & dstStages,vk::VkAccessFlags & dstAccesses) const5186 void CacheState::getFullBarrier (vk::VkPipelineStageFlags&	srcStages,
5187 								 vk::VkAccessFlags&			srcAccesses,
5188 								 vk::VkPipelineStageFlags&	dstStages,
5189 								 vk::VkAccessFlags&			dstAccesses) const
5190 {
5191 	srcStages	= 0;
5192 	srcAccesses	= 0;
5193 	dstStages	= 0;
5194 	dstAccesses	= 0;
5195 
5196 	for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
5197 	{
5198 		const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
5199 
5200 		if ((dstStage_ & m_allowedStages) == 0)
5201 			continue;
5202 
5203 		// Make sure all previous operation are complete in all stages
5204 		if (m_incompleteOperations[dstStage])
5205 		{
5206 			dstStages |= dstStage_;
5207 			srcStages |= m_incompleteOperations[dstStage];
5208 		}
5209 
5210 		// Make sure all read operations are visible in dstStage
5211 		if (m_invisibleOperations[dstStage])
5212 		{
5213 			dstStages |= dstStage_;
5214 			dstAccesses |= m_invisibleOperations[dstStage];
5215 		}
5216 
5217 		// Make sure all write operations fro mall stages are available
5218 		for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
5219 		{
5220 			const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
5221 
5222 			if ((srcStage_ & m_allowedStages) == 0)
5223 				continue;
5224 
5225 			if (m_unavailableWriteOperations[dstStage][srcStage])
5226 			{
5227 				dstStages |= dstStage_;
5228 				srcStages |= dstStage_;
5229 				srcAccesses |= m_unavailableWriteOperations[dstStage][srcStage];
5230 			}
5231 
5232 			if (m_unavailableLayoutTransition[dstStage] && !m_unavailableLayoutTransition[srcStage])
5233 			{
5234 				// Add dependency between srcStage and dstStage if layout transition has not completed in dstStage,
5235 				// but has completed in srcStage.
5236 				dstStages |= dstStage_;
5237 				srcStages |= dstStage_;
5238 			}
5239 		}
5240 	}
5241 
5242 	DE_ASSERT((srcStages & (~m_allowedStages)) == 0);
5243 	DE_ASSERT((srcAccesses & (~m_allowedAccesses)) == 0);
5244 	DE_ASSERT((dstStages & (~m_allowedStages)) == 0);
5245 	DE_ASSERT((dstAccesses & (~m_allowedAccesses)) == 0);
5246 }
5247 
checkImageLayoutBarrier(vk::VkPipelineStageFlags srcStages,vk::VkAccessFlags srcAccesses,vk::VkPipelineStageFlags dstStages,vk::VkAccessFlags dstAccesses)5248 void CacheState::checkImageLayoutBarrier (vk::VkPipelineStageFlags	srcStages,
5249 										 vk::VkAccessFlags			srcAccesses,
5250 										 vk::VkPipelineStageFlags	dstStages,
5251 										 vk::VkAccessFlags			dstAccesses)
5252 {
5253 	DE_ASSERT((srcStages & (~m_allowedStages)) == 0);
5254 	DE_ASSERT((srcAccesses & (~m_allowedAccesses)) == 0);
5255 	DE_ASSERT((dstStages & (~m_allowedStages)) == 0);
5256 	DE_ASSERT((dstAccesses & (~m_allowedAccesses)) == 0);
5257 
5258 	DE_UNREF(srcStages);
5259 	DE_UNREF(srcAccesses);
5260 
5261 	DE_UNREF(dstStages);
5262 	DE_UNREF(dstAccesses);
5263 
5264 #if defined(DE_DEBUG)
5265 	// Check that all stages have completed before srcStages or are in srcStages.
5266 	{
5267 		vk::VkPipelineStageFlags completedStages = srcStages;
5268 
5269 		for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= srcStages; srcStage_ <<= 1)
5270 		{
5271 			const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
5272 
5273 			if ((srcStage_ & srcStages) == 0)
5274 				continue;
5275 
5276 			completedStages |= (~m_incompleteOperations[srcStage]);
5277 		}
5278 
5279 		DE_ASSERT((completedStages & m_allowedStages) == m_allowedStages);
5280 	}
5281 
5282 	// Check that any write is available at least in one stage. Since all stages are complete even single flush is enough.
5283 	if ((getWriteAccessFlags() & m_allowedAccesses) != 0 && (srcAccesses & getWriteAccessFlags()) == 0)
5284 	{
5285 		bool anyWriteAvailable = false;
5286 
5287 		for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
5288 		{
5289 			const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
5290 
5291 			if ((dstStage_ & m_allowedStages) == 0)
5292 				continue;
5293 
5294 			for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
5295 			{
5296 				const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
5297 
5298 				if ((srcStage_ & m_allowedStages) == 0)
5299 					continue;
5300 
5301 				if (m_unavailableWriteOperations[dstStage][srcStage] != (getWriteAccessFlags() & m_allowedAccesses))
5302 				{
5303 					anyWriteAvailable = true;
5304 					break;
5305 				}
5306 			}
5307 		}
5308 
5309 		DE_ASSERT(anyWriteAvailable);
5310 	}
5311 #endif
5312 }
5313 
imageLayoutBarrier(vk::VkPipelineStageFlags srcStages,vk::VkAccessFlags srcAccesses,vk::VkPipelineStageFlags dstStages,vk::VkAccessFlags dstAccesses)5314 void CacheState::imageLayoutBarrier (vk::VkPipelineStageFlags	srcStages,
5315 									 vk::VkAccessFlags			srcAccesses,
5316 									 vk::VkPipelineStageFlags	dstStages,
5317 									 vk::VkAccessFlags			dstAccesses)
5318 {
5319 	checkImageLayoutBarrier(srcStages, srcAccesses, dstStages, dstAccesses);
5320 
5321 	for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
5322 	{
5323 		const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
5324 
5325 		if ((dstStage_ & m_allowedStages) == 0)
5326 			continue;
5327 
5328 		// All stages are incomplete after the barrier except each dstStage in it self.
5329 		m_incompleteOperations[dstStage] = m_allowedStages & (~dstStage_);
5330 
5331 		// All memory operations are invisible unless they are listed in dstAccess
5332 		m_invisibleOperations[dstStage] = m_allowedAccesses & (~dstAccesses);
5333 
5334 		// Layout transition is unavailable in stage unless it was listed in dstStages
5335 		m_unavailableLayoutTransition[dstStage]= (dstStage_ & dstStages) == 0;
5336 
5337 		for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
5338 		{
5339 			const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
5340 
5341 			if ((srcStage_ & m_allowedStages) == 0)
5342 				continue;
5343 
5344 			// All write operations are available after layout transition
5345 			m_unavailableWriteOperations[dstStage][srcStage] = 0;
5346 		}
5347 	}
5348 }
5349 
barrier(vk::VkPipelineStageFlags srcStages,vk::VkAccessFlags srcAccesses,vk::VkPipelineStageFlags dstStages,vk::VkAccessFlags dstAccesses)5350 void CacheState::barrier (vk::VkPipelineStageFlags	srcStages,
5351 						  vk::VkAccessFlags			srcAccesses,
5352 						  vk::VkPipelineStageFlags	dstStages,
5353 						  vk::VkAccessFlags			dstAccesses)
5354 {
5355 	DE_ASSERT((srcStages & (~m_allowedStages)) == 0);
5356 	DE_ASSERT((srcAccesses & (~m_allowedAccesses)) == 0);
5357 	DE_ASSERT((dstStages & (~m_allowedStages)) == 0);
5358 	DE_ASSERT((dstAccesses & (~m_allowedAccesses)) == 0);
5359 
5360 	// Transitivity
5361 	{
5362 		vk::VkPipelineStageFlags		oldIncompleteOperations[PIPELINESTAGE_LAST];
5363 		vk::VkAccessFlags				oldUnavailableWriteOperations[PIPELINESTAGE_LAST][PIPELINESTAGE_LAST];
5364 		bool							oldUnavailableLayoutTransition[PIPELINESTAGE_LAST];
5365 
5366 		deMemcpy(oldIncompleteOperations, m_incompleteOperations, sizeof(oldIncompleteOperations));
5367 		deMemcpy(oldUnavailableWriteOperations, m_unavailableWriteOperations, sizeof(oldUnavailableWriteOperations));
5368 		deMemcpy(oldUnavailableLayoutTransition, m_unavailableLayoutTransition, sizeof(oldUnavailableLayoutTransition));
5369 
5370 		for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= srcStages; srcStage_ <<= 1)
5371 		{
5372 			const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
5373 
5374 			if ((srcStage_ & srcStages) == 0)
5375 				continue;
5376 
5377 			for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= dstStages; dstStage_ <<= 1)
5378 			{
5379 				const PipelineStage	dstStage			= pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
5380 
5381 				if ((dstStage_ & dstStages) == 0)
5382 					continue;
5383 
5384 				// Stages that have completed before srcStage have also completed before dstStage
5385 				m_incompleteOperations[dstStage] &= oldIncompleteOperations[srcStage];
5386 
5387 				// Image layout transition in srcStage are now available in dstStage
5388 				m_unavailableLayoutTransition[dstStage] &= oldUnavailableLayoutTransition[srcStage];
5389 
5390 				for (vk::VkPipelineStageFlags sharedStage_ = 1; sharedStage_ <= m_allowedStages; sharedStage_ <<= 1)
5391 				{
5392 					const PipelineStage	sharedStage			= pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)sharedStage_);
5393 
5394 					if ((sharedStage_ & m_allowedStages) == 0)
5395 						continue;
5396 
5397 					// Writes that are available in srcStage are also available in dstStage
5398 					m_unavailableWriteOperations[dstStage][sharedStage] &= oldUnavailableWriteOperations[srcStage][sharedStage];
5399 				}
5400 			}
5401 		}
5402 	}
5403 
5404 	// Barrier
5405 	for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= dstStages; dstStage_ <<= 1)
5406 	{
5407 		const PipelineStage	dstStage			= pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
5408 		bool				allWritesAvailable	= true;
5409 
5410 		if ((dstStage_ & dstStages) == 0)
5411 			continue;
5412 
5413 		// Operations in srcStages have completed before any stage in dstStages
5414 		m_incompleteOperations[dstStage] &= ~srcStages;
5415 
5416 		for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
5417 		{
5418 			const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
5419 
5420 			if ((srcStage_ & m_allowedStages) == 0)
5421 				continue;
5422 
5423 			// Make srcAccesses from srcStage available in dstStage
5424 			if ((srcStage_ & srcStages) != 0)
5425 				m_unavailableWriteOperations[dstStage][srcStage] &= ~srcAccesses;
5426 
5427 			if (m_unavailableWriteOperations[dstStage][srcStage] != 0)
5428 				allWritesAvailable = false;
5429 		}
5430 
5431 		// If all writes are available in dstStage make dstAccesses also visible
5432 		if (allWritesAvailable)
5433 			m_invisibleOperations[dstStage] &= ~dstAccesses;
5434 	}
5435 }
5436 
isClean(void) const5437 bool CacheState::isClean (void) const
5438 {
5439 	for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
5440 	{
5441 		const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
5442 
5443 		if ((dstStage_ & m_allowedStages) == 0)
5444 			continue;
5445 
5446 		// Some operations are not visible to some stages
5447 		if (m_invisibleOperations[dstStage] != 0)
5448 			return false;
5449 
5450 		// There are operation that have not completed yet
5451 		if (m_incompleteOperations[dstStage] != 0)
5452 			return false;
5453 
5454 		// Layout transition has not completed yet
5455 		if (m_unavailableLayoutTransition[dstStage])
5456 			return false;
5457 
5458 		for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
5459 		{
5460 			const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
5461 
5462 			if ((srcStage_ & m_allowedStages) == 0)
5463 				continue;
5464 
5465 			// Some write operations are not available yet
5466 			if (m_unavailableWriteOperations[dstStage][srcStage] != 0)
5467 				return false;
5468 		}
5469 	}
5470 
5471 	return true;
5472 }
5473 
5474 struct State
5475 {
Statevkt::memory::__anon09d9cc850111::State5476 	State (Usage usage, deUint32 seed)
5477 		: stage					(STAGE_HOST)
5478 		, cache					(usageToStageFlags(usage), usageToAccessFlags(usage))
5479 		, rng					(seed)
5480 		, mapped				(false)
5481 		, hostInvalidated		(true)
5482 		, hostFlushed			(true)
5483 		, memoryDefined			(false)
5484 		, hasBuffer				(false)
5485 		, hasBoundBufferMemory	(false)
5486 		, hasImage				(false)
5487 		, hasBoundImageMemory	(false)
5488 		, imageLayout			(vk::VK_IMAGE_LAYOUT_UNDEFINED)
5489 		, imageDefined			(false)
5490 		, queueIdle				(true)
5491 		, deviceIdle			(true)
5492 		, commandBufferIsEmpty	(true)
5493 	{
5494 	}
5495 
5496 	Stage				stage;
5497 	CacheState			cache;
5498 	de::Random			rng;
5499 
5500 	bool				mapped;
5501 	bool				hostInvalidated;
5502 	bool				hostFlushed;
5503 	bool				memoryDefined;
5504 
5505 	bool				hasBuffer;
5506 	bool				hasBoundBufferMemory;
5507 
5508 	bool				hasImage;
5509 	bool				hasBoundImageMemory;
5510 	vk::VkImageLayout	imageLayout;
5511 	bool				imageDefined;
5512 
5513 	bool				queueIdle;
5514 	bool				deviceIdle;
5515 
5516 	bool				commandBufferIsEmpty;
5517 };
5518 
getAvailableOps(const State & state,bool supportsBuffers,bool supportsImages,Usage usage,vector<Op> & ops)5519 void getAvailableOps (const State& state, bool supportsBuffers, bool supportsImages, Usage usage, vector<Op>& ops)
5520 {
5521 	if (state.stage == STAGE_HOST)
5522 	{
5523 		if (usage & (USAGE_HOST_READ | USAGE_HOST_WRITE))
5524 		{
5525 			// Host memory operations
5526 			if (state.mapped)
5527 			{
5528 				ops.push_back(OP_UNMAP);
5529 
5530 				// Avoid flush and finish if they are not needed
5531 				if (!state.hostFlushed)
5532 					ops.push_back(OP_MAP_FLUSH);
5533 
5534 				if (!state.hostInvalidated
5535 					&& state.queueIdle
5536 					&& ((usage & USAGE_HOST_READ) == 0
5537 						|| state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_READ_BIT))
5538 					&& ((usage & USAGE_HOST_WRITE) == 0
5539 						|| state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_WRITE_BIT)))
5540 				{
5541 					ops.push_back(OP_MAP_INVALIDATE);
5542 				}
5543 
5544 				if (usage & USAGE_HOST_READ
5545 					&& usage & USAGE_HOST_WRITE
5546 					&& state.memoryDefined
5547 					&& state.hostInvalidated
5548 					&& state.queueIdle
5549 					&& state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_WRITE_BIT)
5550 					&& state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_READ_BIT))
5551 				{
5552 					ops.push_back(OP_MAP_MODIFY);
5553 				}
5554 
5555 				if (usage & USAGE_HOST_READ
5556 					&& state.memoryDefined
5557 					&& state.hostInvalidated
5558 					&& state.queueIdle
5559 					&& state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_READ_BIT))
5560 				{
5561 					ops.push_back(OP_MAP_READ);
5562 				}
5563 
5564 				if (usage & USAGE_HOST_WRITE
5565 					&& state.hostInvalidated
5566 					&& state.queueIdle
5567 					&& state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_WRITE_BIT))
5568 				{
5569 					ops.push_back(OP_MAP_WRITE);
5570 				}
5571 			}
5572 			else
5573 				ops.push_back(OP_MAP);
5574 		}
5575 
5576 		if (state.hasBoundBufferMemory && state.queueIdle)
5577 		{
5578 			// \note Destroy only buffers after they have been bound
5579 			ops.push_back(OP_BUFFER_DESTROY);
5580 		}
5581 		else
5582 		{
5583 			if (state.hasBuffer)
5584 			{
5585 				if (!state.hasBoundBufferMemory)
5586 					ops.push_back(OP_BUFFER_BINDMEMORY);
5587 			}
5588 			else if (!state.hasImage && supportsBuffers)	// Avoid creating buffer if there is already image
5589 				ops.push_back(OP_BUFFER_CREATE);
5590 		}
5591 
5592 		if (state.hasBoundImageMemory && state.queueIdle)
5593 		{
5594 			// \note Destroy only image after they have been bound
5595 			ops.push_back(OP_IMAGE_DESTROY);
5596 		}
5597 		else
5598 		{
5599 			if (state.hasImage)
5600 			{
5601 				if (!state.hasBoundImageMemory)
5602 					ops.push_back(OP_IMAGE_BINDMEMORY);
5603 			}
5604 			else if (!state.hasBuffer && supportsImages)	// Avoid creating image if there is already buffer
5605 				ops.push_back(OP_IMAGE_CREATE);
5606 		}
5607 
5608 		// Host writes must be flushed before GPU commands and there must be
5609 		// buffer or image for GPU commands
5610 		if (state.hostFlushed
5611 			&& (state.memoryDefined || supportsDeviceBufferWrites(usage) || state.imageDefined || supportsDeviceImageWrites(usage))
5612 			&& (state.hasBoundBufferMemory || state.hasBoundImageMemory) // Avoid command buffers if there is no object to use
5613 			&& (usageToStageFlags(usage) & (~vk::VK_PIPELINE_STAGE_HOST_BIT)) != 0) // Don't start command buffer if there are no ways to use memory from gpu
5614 		{
5615 			ops.push_back(OP_COMMAND_BUFFER_BEGIN);
5616 		}
5617 
5618 		if (!state.deviceIdle)
5619 			ops.push_back(OP_DEVICE_WAIT_FOR_IDLE);
5620 
5621 		if (!state.queueIdle)
5622 			ops.push_back(OP_QUEUE_WAIT_FOR_IDLE);
5623 	}
5624 	else if (state.stage == STAGE_COMMAND_BUFFER)
5625 	{
5626 		if (!state.cache.isClean())
5627 		{
5628 			ops.push_back(OP_PIPELINE_BARRIER_GLOBAL);
5629 
5630 			if (state.hasImage)
5631 				ops.push_back(OP_PIPELINE_BARRIER_IMAGE);
5632 
5633 			if (state.hasBuffer)
5634 				ops.push_back(OP_PIPELINE_BARRIER_BUFFER);
5635 		}
5636 
5637 		if (state.hasBoundBufferMemory)
5638 		{
5639 			if (usage & USAGE_TRANSFER_DST
5640 				&& state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT))
5641 			{
5642 				ops.push_back(OP_BUFFER_FILL);
5643 				ops.push_back(OP_BUFFER_UPDATE);
5644 				ops.push_back(OP_BUFFER_COPY_FROM_BUFFER);
5645 				ops.push_back(OP_BUFFER_COPY_FROM_IMAGE);
5646 			}
5647 
5648 			if (usage & USAGE_TRANSFER_SRC
5649 				&& state.memoryDefined
5650 				&& state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT))
5651 			{
5652 				ops.push_back(OP_BUFFER_COPY_TO_BUFFER);
5653 				ops.push_back(OP_BUFFER_COPY_TO_IMAGE);
5654 			}
5655 		}
5656 
5657 		if (state.hasBoundImageMemory)
5658 		{
5659 			ops.push_back(OP_IMAGE_TRANSITION_LAYOUT);
5660 
5661 			{
5662 				if (usage & USAGE_TRANSFER_DST
5663 					&& (state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL
5664 						|| state.imageLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
5665 					&& state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT))
5666 				{
5667 					ops.push_back(OP_IMAGE_COPY_FROM_BUFFER);
5668 					ops.push_back(OP_IMAGE_COPY_FROM_IMAGE);
5669 					ops.push_back(OP_IMAGE_BLIT_FROM_IMAGE);
5670 				}
5671 
5672 				if (usage & USAGE_TRANSFER_SRC
5673 					&& (state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL
5674 						|| state.imageLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
5675 					&& state.imageDefined
5676 					&& state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT))
5677 				{
5678 					ops.push_back(OP_IMAGE_COPY_TO_BUFFER);
5679 					ops.push_back(OP_IMAGE_COPY_TO_IMAGE);
5680 					ops.push_back(OP_IMAGE_BLIT_TO_IMAGE);
5681 				}
5682 			}
5683 		}
5684 
5685 		// \todo [2016-03-09 mika] Add other usages?
5686 		if (((usage & USAGE_VERTEX_BUFFER) && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT))
5687 			|| ((usage & USAGE_INDEX_BUFFER) && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_INDEX_READ_BIT)))
5688 			ops.push_back(OP_RENDERPASS_BEGIN);
5689 
5690 		// \note This depends on previous operations and has to be always the
5691 		// last command buffer operation check
5692 		if (ops.empty() || !state.commandBufferIsEmpty)
5693 			ops.push_back(OP_COMMAND_BUFFER_END);
5694 	}
5695 	else if (state.stage == STAGE_RENDER_PASS)
5696 	{
5697 		if (usage & USAGE_VERTEX_BUFFER
5698 			&& state.memoryDefined
5699 			&& state.hasBoundBufferMemory
5700 			&& state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT))
5701 		{
5702 			ops.push_back(OP_RENDER_VERTEX_BUFFER);
5703 		}
5704 
5705 		if (usage & USAGE_INDEX_BUFFER
5706 			&& state.memoryDefined
5707 			&& state.hasBoundBufferMemory
5708 			&& state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_INDEX_READ_BIT))
5709 		{
5710 			ops.push_back(OP_RENDER_INDEX_BUFFER);
5711 		}
5712 
5713 		ops.push_back(OP_RENDERPASS_END);
5714 	}
5715 	else
5716 		DE_FATAL("Unknown stage");
5717 }
5718 
layoutSupportedByUsage(Usage usage,vk::VkImageLayout layout)5719 bool layoutSupportedByUsage (Usage usage, vk::VkImageLayout layout)
5720 {
5721 	switch (layout)
5722 	{
5723 		case vk::VK_IMAGE_LAYOUT_GENERAL:
5724 			return true;
5725 
5726 		case vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
5727 			return (usage & USAGE_COLOR_ATTACHMENT) != 0;
5728 
5729 		case vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
5730 			return (usage & USAGE_DEPTH_STENCIL_ATTACHMENT) != 0;
5731 
5732 		case vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
5733 			return (usage & USAGE_DEPTH_STENCIL_ATTACHMENT) != 0;
5734 
5735 		case vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
5736 			// \todo [2016-03-09 mika] Should include input attachment
5737 			return (usage & USAGE_TEXTURE_SAMPLED) != 0;
5738 
5739 		case vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
5740 			return (usage & USAGE_TRANSFER_SRC) != 0;
5741 
5742 		case vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
5743 			return (usage & USAGE_TRANSFER_DST) != 0;
5744 
5745 		case vk::VK_IMAGE_LAYOUT_PREINITIALIZED:
5746 			return true;
5747 
5748 		default:
5749 			DE_FATAL("Unknown layout");
5750 			return false;
5751 	}
5752 }
5753 
getRandomNextLayout(de::Random & rng,Usage usage,vk::VkImageLayout previousLayout)5754 vk::VkImageLayout getRandomNextLayout (de::Random&			rng,
5755 									   Usage				usage,
5756 									   vk::VkImageLayout	previousLayout)
5757 {
5758 	const vk::VkImageLayout layouts[] =
5759 	{
5760 		vk::VK_IMAGE_LAYOUT_GENERAL,
5761 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
5762 		vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
5763 		vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
5764 		vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
5765 		vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
5766 		vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
5767 	};
5768 	size_t possibleLayoutCount = 0;
5769 
5770 	for (size_t layoutNdx = 0; layoutNdx < DE_LENGTH_OF_ARRAY(layouts); layoutNdx++)
5771 	{
5772 		const vk::VkImageLayout layout = layouts[layoutNdx];
5773 
5774 		if (layoutSupportedByUsage(usage, layout) && layout != previousLayout)
5775 			possibleLayoutCount++;
5776 	}
5777 
5778 	size_t nextLayoutNdx = ((size_t)rng.getUint64()) % possibleLayoutCount;
5779 
5780 	for (size_t layoutNdx = 0; layoutNdx < DE_LENGTH_OF_ARRAY(layouts); layoutNdx++)
5781 	{
5782 		const vk::VkImageLayout layout = layouts[layoutNdx];
5783 
5784 		if (layoutSupportedByUsage(usage, layout) && layout != previousLayout)
5785 		{
5786 			if (nextLayoutNdx == 0)
5787 				return layout;
5788 			else
5789 				nextLayoutNdx--;
5790 		}
5791 	}
5792 
5793 	DE_FATAL("Unreachable");
5794 	return vk::VK_IMAGE_LAYOUT_UNDEFINED;
5795 }
5796 
applyOp(State & state,const Memory & memory,Op op,Usage usage)5797 void applyOp (State& state, const Memory& memory, Op op, Usage usage)
5798 {
5799 	switch (op)
5800 	{
5801 		case OP_MAP:
5802 			DE_ASSERT(state.stage == STAGE_HOST);
5803 			DE_ASSERT(!state.mapped);
5804 			state.mapped = true;
5805 			break;
5806 
5807 		case OP_UNMAP:
5808 			DE_ASSERT(state.stage == STAGE_HOST);
5809 			DE_ASSERT(state.mapped);
5810 			state.mapped = false;
5811 			break;
5812 
5813 		case OP_MAP_FLUSH:
5814 			DE_ASSERT(state.stage == STAGE_HOST);
5815 			DE_ASSERT(!state.hostFlushed);
5816 			state.hostFlushed = true;
5817 			break;
5818 
5819 		case OP_MAP_INVALIDATE:
5820 			DE_ASSERT(state.stage == STAGE_HOST);
5821 			DE_ASSERT(!state.hostInvalidated);
5822 			state.hostInvalidated = true;
5823 			break;
5824 
5825 		case OP_MAP_READ:
5826 			DE_ASSERT(state.stage == STAGE_HOST);
5827 			DE_ASSERT(state.hostInvalidated);
5828 			state.rng.getUint32();
5829 			break;
5830 
5831 		case OP_MAP_WRITE:
5832 			DE_ASSERT(state.stage == STAGE_HOST);
5833 			if ((memory.getMemoryType().propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
5834 				state.hostFlushed = false;
5835 
5836 			state.memoryDefined = true;
5837 			state.imageDefined = false;
5838 			state.imageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
5839 			state.rng.getUint32();
5840 			break;
5841 
5842 		case OP_MAP_MODIFY:
5843 			DE_ASSERT(state.stage == STAGE_HOST);
5844 			DE_ASSERT(state.hostInvalidated);
5845 
5846 			if ((memory.getMemoryType().propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
5847 				state.hostFlushed = false;
5848 
5849 			state.rng.getUint32();
5850 			break;
5851 
5852 		case OP_BUFFER_CREATE:
5853 			DE_ASSERT(state.stage == STAGE_HOST);
5854 			DE_ASSERT(!state.hasBuffer);
5855 
5856 			state.hasBuffer = true;
5857 			break;
5858 
5859 		case OP_BUFFER_DESTROY:
5860 			DE_ASSERT(state.stage == STAGE_HOST);
5861 			DE_ASSERT(state.hasBuffer);
5862 			DE_ASSERT(state.hasBoundBufferMemory);
5863 
5864 			state.hasBuffer = false;
5865 			state.hasBoundBufferMemory = false;
5866 			break;
5867 
5868 		case OP_BUFFER_BINDMEMORY:
5869 			DE_ASSERT(state.stage == STAGE_HOST);
5870 			DE_ASSERT(state.hasBuffer);
5871 			DE_ASSERT(!state.hasBoundBufferMemory);
5872 
5873 			state.hasBoundBufferMemory = true;
5874 			break;
5875 
5876 		case OP_IMAGE_CREATE:
5877 			DE_ASSERT(state.stage == STAGE_HOST);
5878 			DE_ASSERT(!state.hasImage);
5879 			DE_ASSERT(!state.hasBuffer);
5880 
5881 			state.hasImage = true;
5882 			break;
5883 
5884 		case OP_IMAGE_DESTROY:
5885 			DE_ASSERT(state.stage == STAGE_HOST);
5886 			DE_ASSERT(state.hasImage);
5887 			DE_ASSERT(state.hasBoundImageMemory);
5888 
5889 			state.hasImage = false;
5890 			state.hasBoundImageMemory = false;
5891 			state.imageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
5892 			state.imageDefined = false;
5893 			break;
5894 
5895 		case OP_IMAGE_BINDMEMORY:
5896 			DE_ASSERT(state.stage == STAGE_HOST);
5897 			DE_ASSERT(state.hasImage);
5898 			DE_ASSERT(!state.hasBoundImageMemory);
5899 
5900 			state.hasBoundImageMemory = true;
5901 			break;
5902 
5903 		case OP_IMAGE_TRANSITION_LAYOUT:
5904 		{
5905 			DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
5906 			DE_ASSERT(state.hasImage);
5907 			DE_ASSERT(state.hasBoundImageMemory);
5908 
5909 			// \todo [2016-03-09 mika] Support linear tiling and predefined data
5910 			const vk::VkImageLayout		srcLayout	= state.rng.getFloat() < 0.9f ? state.imageLayout : vk::VK_IMAGE_LAYOUT_UNDEFINED;
5911 			const vk::VkImageLayout		dstLayout	= getRandomNextLayout(state.rng, usage, srcLayout);
5912 
5913 			vk::VkPipelineStageFlags	dirtySrcStages;
5914 			vk::VkAccessFlags			dirtySrcAccesses;
5915 			vk::VkPipelineStageFlags	dirtyDstStages;
5916 			vk::VkAccessFlags			dirtyDstAccesses;
5917 
5918 			vk::VkPipelineStageFlags	srcStages;
5919 			vk::VkAccessFlags			srcAccesses;
5920 			vk::VkPipelineStageFlags	dstStages;
5921 			vk::VkAccessFlags			dstAccesses;
5922 
5923 			state.cache.getFullBarrier(dirtySrcStages, dirtySrcAccesses, dirtyDstStages, dirtyDstAccesses);
5924 
5925 			// Try masking some random bits
5926 			srcStages	= dirtySrcStages;
5927 			srcAccesses	= dirtySrcAccesses;
5928 
5929 			dstStages	= state.cache.getAllowedStages() & state.rng.getUint32();
5930 			dstAccesses	= state.cache.getAllowedAcceses() & state.rng.getUint32();
5931 
5932 			// If there are no bits in dst stage mask use all stages
5933 			dstStages	= dstStages ? dstStages : state.cache.getAllowedStages();
5934 
5935 			if (!srcStages)
5936 				srcStages = dstStages;
5937 
5938 			if (srcLayout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
5939 				state.imageDefined = false;
5940 
5941 			state.commandBufferIsEmpty = false;
5942 			state.imageLayout = dstLayout;
5943 			state.memoryDefined = false;
5944 			state.cache.imageLayoutBarrier(srcStages, srcAccesses, dstStages, dstAccesses);
5945 			break;
5946 		}
5947 
5948 		case OP_QUEUE_WAIT_FOR_IDLE:
5949 			DE_ASSERT(state.stage == STAGE_HOST);
5950 			DE_ASSERT(!state.queueIdle);
5951 
5952 			state.queueIdle = true;
5953 
5954 			state.cache.waitForIdle();
5955 			break;
5956 
5957 		case OP_DEVICE_WAIT_FOR_IDLE:
5958 			DE_ASSERT(state.stage == STAGE_HOST);
5959 			DE_ASSERT(!state.deviceIdle);
5960 
5961 			state.queueIdle = true;
5962 			state.deviceIdle = true;
5963 
5964 			state.cache.waitForIdle();
5965 			break;
5966 
5967 		case OP_COMMAND_BUFFER_BEGIN:
5968 			DE_ASSERT(state.stage == STAGE_HOST);
5969 			state.stage = STAGE_COMMAND_BUFFER;
5970 			state.commandBufferIsEmpty = true;
5971 			// Makes host writes visible to command buffer
5972 			state.cache.submitCommandBuffer();
5973 			break;
5974 
5975 		case OP_COMMAND_BUFFER_END:
5976 			DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
5977 			state.stage = STAGE_HOST;
5978 			state.queueIdle = false;
5979 			state.deviceIdle = false;
5980 			break;
5981 
5982 		case OP_BUFFER_COPY_FROM_BUFFER:
5983 		case OP_BUFFER_COPY_FROM_IMAGE:
5984 		case OP_BUFFER_UPDATE:
5985 		case OP_BUFFER_FILL:
5986 			state.rng.getUint32();
5987 			DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
5988 
5989 			if ((memory.getMemoryType().propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
5990 				state.hostInvalidated = false;
5991 
5992 			state.commandBufferIsEmpty = false;
5993 			state.memoryDefined = true;
5994 			state.imageDefined = false;
5995 			state.imageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
5996 			state.cache.perform(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT);
5997 			break;
5998 
5999 		case OP_BUFFER_COPY_TO_BUFFER:
6000 		case OP_BUFFER_COPY_TO_IMAGE:
6001 			DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
6002 
6003 			state.commandBufferIsEmpty = false;
6004 			state.cache.perform(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT);
6005 			break;
6006 
6007 		case OP_IMAGE_BLIT_FROM_IMAGE:
6008 			state.rng.getBool();
6009 			// Fall through
6010 		case OP_IMAGE_COPY_FROM_BUFFER:
6011 		case OP_IMAGE_COPY_FROM_IMAGE:
6012 			state.rng.getUint32();
6013 			DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
6014 
6015 			if ((memory.getMemoryType().propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
6016 				state.hostInvalidated = false;
6017 
6018 			state.commandBufferIsEmpty = false;
6019 			state.memoryDefined = false;
6020 			state.imageDefined = true;
6021 			state.cache.perform(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT);
6022 			break;
6023 
6024 		case OP_IMAGE_BLIT_TO_IMAGE:
6025 			state.rng.getBool();
6026 			// Fall through
6027 		case OP_IMAGE_COPY_TO_BUFFER:
6028 		case OP_IMAGE_COPY_TO_IMAGE:
6029 			DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
6030 
6031 			state.commandBufferIsEmpty = false;
6032 			state.cache.perform(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT);
6033 			break;
6034 
6035 		case OP_PIPELINE_BARRIER_GLOBAL:
6036 		case OP_PIPELINE_BARRIER_BUFFER:
6037 		case OP_PIPELINE_BARRIER_IMAGE:
6038 		{
6039 			DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
6040 
6041 			vk::VkPipelineStageFlags	dirtySrcStages;
6042 			vk::VkAccessFlags			dirtySrcAccesses;
6043 			vk::VkPipelineStageFlags	dirtyDstStages;
6044 			vk::VkAccessFlags			dirtyDstAccesses;
6045 
6046 			vk::VkPipelineStageFlags	srcStages;
6047 			vk::VkAccessFlags			srcAccesses;
6048 			vk::VkPipelineStageFlags	dstStages;
6049 			vk::VkAccessFlags			dstAccesses;
6050 
6051 			state.cache.getFullBarrier(dirtySrcStages, dirtySrcAccesses, dirtyDstStages, dirtyDstAccesses);
6052 
6053 			// Try masking some random bits
6054 			srcStages	= dirtySrcStages & state.rng.getUint32();
6055 			srcAccesses	= dirtySrcAccesses & state.rng.getUint32();
6056 
6057 			dstStages	= dirtyDstStages & state.rng.getUint32();
6058 			dstAccesses	= dirtyDstAccesses & state.rng.getUint32();
6059 
6060 			// If there are no bits in stage mask use the original dirty stages
6061 			srcStages	= srcStages ? srcStages : dirtySrcStages;
6062 			dstStages	= dstStages ? dstStages : dirtyDstStages;
6063 
6064 			if (!srcStages)
6065 				srcStages = dstStages;
6066 
6067 			state.commandBufferIsEmpty = false;
6068 			state.cache.barrier(srcStages, srcAccesses, dstStages, dstAccesses);
6069 			break;
6070 		}
6071 
6072 		case OP_RENDERPASS_BEGIN:
6073 		{
6074 			DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
6075 
6076 			state.stage = STAGE_RENDER_PASS;
6077 			break;
6078 		}
6079 
6080 		case OP_RENDERPASS_END:
6081 		{
6082 			DE_ASSERT(state.stage == STAGE_RENDER_PASS);
6083 
6084 			state.stage = STAGE_COMMAND_BUFFER;
6085 			break;
6086 		}
6087 
6088 		case OP_RENDER_VERTEX_BUFFER:
6089 		{
6090 			DE_ASSERT(state.stage == STAGE_RENDER_PASS);
6091 
6092 			state.cache.perform(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT);
6093 			break;
6094 		}
6095 
6096 		case OP_RENDER_INDEX_BUFFER:
6097 		{
6098 			DE_ASSERT(state.stage == STAGE_RENDER_PASS);
6099 
6100 			state.cache.perform(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_INDEX_READ_BIT);
6101 			break;
6102 		}
6103 
6104 		default:
6105 			DE_FATAL("Unknown op");
6106 	}
6107 }
6108 
createHostCommand(Op op,de::Random & rng,Usage usage,vk::VkSharingMode sharing)6109 de::MovePtr<Command> createHostCommand (Op					op,
6110 										de::Random&			rng,
6111 										Usage				usage,
6112 										vk::VkSharingMode	sharing)
6113 {
6114 	switch (op)
6115 	{
6116 		case OP_MAP:					return de::MovePtr<Command>(new Map());
6117 		case OP_UNMAP:					return de::MovePtr<Command>(new UnMap());
6118 
6119 		case OP_MAP_FLUSH:				return de::MovePtr<Command>(new Flush());
6120 		case OP_MAP_INVALIDATE:			return de::MovePtr<Command>(new Invalidate());
6121 
6122 		case OP_MAP_READ:				return de::MovePtr<Command>(new HostMemoryAccess(true, false, rng.getUint32()));
6123 		case OP_MAP_WRITE:				return de::MovePtr<Command>(new HostMemoryAccess(false, true, rng.getUint32()));
6124 		case OP_MAP_MODIFY:				return de::MovePtr<Command>(new HostMemoryAccess(true, true, rng.getUint32()));
6125 
6126 		case OP_BUFFER_CREATE:			return de::MovePtr<Command>(new CreateBuffer(usageToBufferUsageFlags(usage), sharing));
6127 		case OP_BUFFER_DESTROY:			return de::MovePtr<Command>(new DestroyBuffer());
6128 		case OP_BUFFER_BINDMEMORY:		return de::MovePtr<Command>(new BindBufferMemory());
6129 
6130 		case OP_IMAGE_CREATE:			return de::MovePtr<Command>(new CreateImage(usageToImageUsageFlags(usage), sharing));
6131 		case OP_IMAGE_DESTROY:			return de::MovePtr<Command>(new DestroyImage());
6132 		case OP_IMAGE_BINDMEMORY:		return de::MovePtr<Command>(new BindImageMemory());
6133 
6134 		case OP_QUEUE_WAIT_FOR_IDLE:	return de::MovePtr<Command>(new QueueWaitIdle());
6135 		case OP_DEVICE_WAIT_FOR_IDLE:	return de::MovePtr<Command>(new DeviceWaitIdle());
6136 
6137 		default:
6138 			DE_FATAL("Unknown op");
6139 			return de::MovePtr<Command>(DE_NULL);
6140 	}
6141 }
6142 
createCmdCommand(de::Random & rng,const State & state,Op op,Usage usage)6143 de::MovePtr<CmdCommand> createCmdCommand (de::Random&	rng,
6144 										  const State&	state,
6145 										  Op			op,
6146 										  Usage			usage)
6147 {
6148 	switch (op)
6149 	{
6150 		case OP_BUFFER_FILL:					return de::MovePtr<CmdCommand>(new FillBuffer(rng.getUint32()));
6151 		case OP_BUFFER_UPDATE:					return de::MovePtr<CmdCommand>(new UpdateBuffer(rng.getUint32()));
6152 		case OP_BUFFER_COPY_TO_BUFFER:			return de::MovePtr<CmdCommand>(new BufferCopyToBuffer());
6153 		case OP_BUFFER_COPY_FROM_BUFFER:		return de::MovePtr<CmdCommand>(new BufferCopyFromBuffer(rng.getUint32()));
6154 
6155 		case OP_BUFFER_COPY_TO_IMAGE:			return de::MovePtr<CmdCommand>(new BufferCopyToImage());
6156 		case OP_BUFFER_COPY_FROM_IMAGE:			return de::MovePtr<CmdCommand>(new BufferCopyFromImage(rng.getUint32()));
6157 
6158 		case OP_IMAGE_TRANSITION_LAYOUT:
6159 		{
6160 			DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
6161 			DE_ASSERT(state.hasImage);
6162 			DE_ASSERT(state.hasBoundImageMemory);
6163 
6164 			const vk::VkImageLayout		srcLayout	= rng.getFloat() < 0.9f ? state.imageLayout : vk::VK_IMAGE_LAYOUT_UNDEFINED;
6165 			const vk::VkImageLayout		dstLayout	= getRandomNextLayout(rng, usage, srcLayout);
6166 
6167 			vk::VkPipelineStageFlags	dirtySrcStages;
6168 			vk::VkAccessFlags			dirtySrcAccesses;
6169 			vk::VkPipelineStageFlags	dirtyDstStages;
6170 			vk::VkAccessFlags			dirtyDstAccesses;
6171 
6172 			vk::VkPipelineStageFlags	srcStages;
6173 			vk::VkAccessFlags			srcAccesses;
6174 			vk::VkPipelineStageFlags	dstStages;
6175 			vk::VkAccessFlags			dstAccesses;
6176 
6177 			state.cache.getFullBarrier(dirtySrcStages, dirtySrcAccesses, dirtyDstStages, dirtyDstAccesses);
6178 
6179 			// Try masking some random bits
6180 			srcStages	= dirtySrcStages;
6181 			srcAccesses	= dirtySrcAccesses;
6182 
6183 			dstStages	= state.cache.getAllowedStages() & rng.getUint32();
6184 			dstAccesses	= state.cache.getAllowedAcceses() & rng.getUint32();
6185 
6186 			// If there are no bits in dst stage mask use all stages
6187 			dstStages	= dstStages ? dstStages : state.cache.getAllowedStages();
6188 
6189 			if (!srcStages)
6190 				srcStages = dstStages;
6191 
6192 			return de::MovePtr<CmdCommand>(new ImageTransition(srcStages, srcAccesses, dstStages, dstAccesses, srcLayout, dstLayout));
6193 		}
6194 
6195 		case OP_IMAGE_COPY_TO_BUFFER:			return de::MovePtr<CmdCommand>(new ImageCopyToBuffer(state.imageLayout));
6196 		case OP_IMAGE_COPY_FROM_BUFFER:			return de::MovePtr<CmdCommand>(new ImageCopyFromBuffer(rng.getUint32(), state.imageLayout));
6197 		case OP_IMAGE_COPY_TO_IMAGE:			return de::MovePtr<CmdCommand>(new ImageCopyToImage(state.imageLayout));
6198 		case OP_IMAGE_COPY_FROM_IMAGE:			return de::MovePtr<CmdCommand>(new ImageCopyFromImage(rng.getUint32(), state.imageLayout));
6199 		case OP_IMAGE_BLIT_TO_IMAGE:
6200 		{
6201 			const BlitScale scale = rng.getBool() ? BLIT_SCALE_20 : BLIT_SCALE_10;
6202 			return de::MovePtr<CmdCommand>(new ImageBlitToImage(scale, state.imageLayout));
6203 		}
6204 
6205 		case OP_IMAGE_BLIT_FROM_IMAGE:
6206 		{
6207 			const BlitScale scale = rng.getBool() ? BLIT_SCALE_20 : BLIT_SCALE_10;
6208 			return de::MovePtr<CmdCommand>(new ImageBlitFromImage(rng.getUint32(), scale, state.imageLayout));
6209 		}
6210 
6211 		case OP_PIPELINE_BARRIER_GLOBAL:
6212 		case OP_PIPELINE_BARRIER_BUFFER:
6213 		case OP_PIPELINE_BARRIER_IMAGE:
6214 		{
6215 			vk::VkPipelineStageFlags	dirtySrcStages;
6216 			vk::VkAccessFlags			dirtySrcAccesses;
6217 			vk::VkPipelineStageFlags	dirtyDstStages;
6218 			vk::VkAccessFlags			dirtyDstAccesses;
6219 
6220 			vk::VkPipelineStageFlags	srcStages;
6221 			vk::VkAccessFlags			srcAccesses;
6222 			vk::VkPipelineStageFlags	dstStages;
6223 			vk::VkAccessFlags			dstAccesses;
6224 
6225 			state.cache.getFullBarrier(dirtySrcStages, dirtySrcAccesses, dirtyDstStages, dirtyDstAccesses);
6226 
6227 			// Try masking some random bits
6228 			srcStages	= dirtySrcStages & rng.getUint32();
6229 			srcAccesses	= dirtySrcAccesses & rng.getUint32();
6230 
6231 			dstStages	= dirtyDstStages & rng.getUint32();
6232 			dstAccesses	= dirtyDstAccesses & rng.getUint32();
6233 
6234 			// If there are no bits in stage mask use the original dirty stages
6235 			srcStages	= srcStages ? srcStages : dirtySrcStages;
6236 			dstStages	= dstStages ? dstStages : dirtyDstStages;
6237 
6238 			if (!srcStages)
6239 				srcStages = dstStages;
6240 
6241 			PipelineBarrier::Type type;
6242 
6243 			if (op == OP_PIPELINE_BARRIER_IMAGE)
6244 				type = PipelineBarrier::TYPE_IMAGE;
6245 			else if (op == OP_PIPELINE_BARRIER_BUFFER)
6246 				type = PipelineBarrier::TYPE_BUFFER;
6247 			else if (op == OP_PIPELINE_BARRIER_GLOBAL)
6248 				type = PipelineBarrier::TYPE_GLOBAL;
6249 			else
6250 			{
6251 				type = PipelineBarrier::TYPE_LAST;
6252 				DE_FATAL("Unknown op");
6253 			}
6254 
6255 			if (type == PipelineBarrier::TYPE_IMAGE)
6256 				return de::MovePtr<CmdCommand>(new PipelineBarrier(srcStages, srcAccesses, dstStages, dstAccesses, type, tcu::just(state.imageLayout)));
6257 			else
6258 				return de::MovePtr<CmdCommand>(new PipelineBarrier(srcStages, srcAccesses, dstStages, dstAccesses, type, tcu::nothing<vk::VkImageLayout>()));
6259 		}
6260 
6261 		default:
6262 			DE_FATAL("Unknown op");
6263 			return de::MovePtr<CmdCommand>(DE_NULL);
6264 	}
6265 }
6266 
createRenderPassCommand(de::Random &,const State &,Op op)6267 de::MovePtr<RenderPassCommand> createRenderPassCommand (de::Random&,
6268 														const State&,
6269 														Op				op)
6270 {
6271 	switch (op)
6272 	{
6273 		case OP_RENDER_VERTEX_BUFFER:	return de::MovePtr<RenderPassCommand>(new RenderBuffer(RenderBuffer::RENDERAS_VERTEX_BUFFER));
6274 		case OP_RENDER_INDEX_BUFFER:	return de::MovePtr<RenderPassCommand>(new RenderBuffer(RenderBuffer::RENDERAS_INDEX_BUFFER));
6275 
6276 		default:
6277 			DE_FATAL("Unknown op");
6278 			return de::MovePtr<RenderPassCommand>(DE_NULL);
6279 	}
6280 }
6281 
createRenderPassCommands(const Memory & memory,de::Random & nextOpRng,State & state,Usage usage,size_t & opNdx,size_t opCount)6282 de::MovePtr<CmdCommand> createRenderPassCommands (const Memory&	memory,
6283 												  de::Random&	nextOpRng,
6284 												  State&		state,
6285 												  Usage			usage,
6286 												  size_t&		opNdx,
6287 												  size_t		opCount)
6288 {
6289 	vector<RenderPassCommand*>	commands;
6290 
6291 	try
6292 	{
6293 		for (; opNdx < opCount; opNdx++)
6294 		{
6295 			vector<Op>	ops;
6296 
6297 			getAvailableOps(state, memory.getSupportBuffers(), memory.getSupportImages(), usage, ops);
6298 
6299 			DE_ASSERT(!ops.empty());
6300 
6301 			{
6302 				const Op op = nextOpRng.choose<Op>(ops.begin(), ops.end());
6303 
6304 				if (op == OP_RENDERPASS_END)
6305 				{
6306 					break;
6307 				}
6308 				else
6309 				{
6310 					de::Random	rng	(state.rng);
6311 
6312 					commands.push_back(createRenderPassCommand(rng, state, op).release());
6313 					applyOp(state, memory, op, usage);
6314 
6315 					DE_ASSERT(state.rng == rng);
6316 				}
6317 			}
6318 		}
6319 
6320 		applyOp(state, memory, OP_RENDERPASS_END, usage);
6321 		return de::MovePtr<CmdCommand>(new SubmitRenderPass(commands));
6322 	}
6323 	catch (...)
6324 	{
6325 		for (size_t commandNdx = 0; commandNdx < commands.size(); commandNdx++)
6326 			delete commands[commandNdx];
6327 
6328 		throw;
6329 	}
6330 }
6331 
createCmdCommands(const Memory & memory,de::Random & nextOpRng,State & state,Usage usage,size_t & opNdx,size_t opCount)6332 de::MovePtr<Command> createCmdCommands (const Memory&	memory,
6333 										de::Random&		nextOpRng,
6334 										State&			state,
6335 										Usage			usage,
6336 										size_t&			opNdx,
6337 										size_t			opCount)
6338 {
6339 	vector<CmdCommand*>	commands;
6340 
6341 	try
6342 	{
6343 		for (; opNdx < opCount; opNdx++)
6344 		{
6345 			vector<Op>	ops;
6346 
6347 			getAvailableOps(state, memory.getSupportBuffers(), memory.getSupportImages(), usage, ops);
6348 
6349 			DE_ASSERT(!ops.empty());
6350 
6351 			{
6352 				const Op op = nextOpRng.choose<Op>(ops.begin(), ops.end());
6353 
6354 				if (op == OP_COMMAND_BUFFER_END)
6355 				{
6356 					break;
6357 				}
6358 				else
6359 				{
6360 					// \note Command needs to known the state before the operation
6361 					if (op == OP_RENDERPASS_BEGIN)
6362 					{
6363 						applyOp(state, memory, op, usage);
6364 						commands.push_back(createRenderPassCommands(memory, nextOpRng, state, usage, opNdx, opCount).release());
6365 					}
6366 					else
6367 					{
6368 						de::Random	rng	(state.rng);
6369 
6370 						commands.push_back(createCmdCommand(rng, state, op, usage).release());
6371 						applyOp(state, memory, op, usage);
6372 
6373 						DE_ASSERT(state.rng == rng);
6374 					}
6375 
6376 				}
6377 			}
6378 		}
6379 
6380 		applyOp(state, memory, OP_COMMAND_BUFFER_END, usage);
6381 		return de::MovePtr<Command>(new SubmitCommandBuffer(commands));
6382 	}
6383 	catch (...)
6384 	{
6385 		for (size_t commandNdx = 0; commandNdx < commands.size(); commandNdx++)
6386 			delete commands[commandNdx];
6387 
6388 		throw;
6389 	}
6390 }
6391 
createCommands(vector<Command * > & commands,deUint32 seed,const Memory & memory,Usage usage,vk::VkSharingMode sharingMode)6392 void createCommands (vector<Command*>&			commands,
6393 					 deUint32					seed,
6394 					 const Memory&				memory,
6395 					 Usage						usage,
6396 					 vk::VkSharingMode			sharingMode)
6397 {
6398 	const size_t		opCount		= 100;
6399 	State				state		(usage, seed);
6400 	// Used to select next operation only
6401 	de::Random			nextOpRng	(seed ^ 12930809);
6402 
6403 	commands.reserve(opCount);
6404 
6405 	for (size_t opNdx = 0; opNdx < opCount; opNdx++)
6406 	{
6407 		vector<Op>	ops;
6408 
6409 		getAvailableOps(state, memory.getSupportBuffers(), memory.getSupportImages(), usage, ops);
6410 
6411 		DE_ASSERT(!ops.empty());
6412 
6413 		{
6414 			const Op	op	= nextOpRng.choose<Op>(ops.begin(), ops.end());
6415 
6416 			if (op == OP_COMMAND_BUFFER_BEGIN)
6417 			{
6418 				applyOp(state, memory, op, usage);
6419 				commands.push_back(createCmdCommands(memory, nextOpRng, state, usage, opNdx, opCount).release());
6420 			}
6421 			else
6422 			{
6423 				de::Random	rng	(state.rng);
6424 
6425 				commands.push_back(createHostCommand(op, rng, usage, sharingMode).release());
6426 				applyOp(state, memory, op, usage);
6427 
6428 				// Make sure that random generator is in sync
6429 				DE_ASSERT(state.rng == rng);
6430 			}
6431 		}
6432 	}
6433 
6434 	// Clean up resources
6435 	if (state.hasBuffer && state.hasImage)
6436 	{
6437 		if (!state.queueIdle)
6438 			commands.push_back(new QueueWaitIdle());
6439 
6440 		if (state.hasBuffer)
6441 			commands.push_back(new DestroyBuffer());
6442 
6443 		if (state.hasImage)
6444 			commands.push_back(new DestroyImage());
6445 	}
6446 }
6447 
testCommand(TestLog & log,tcu::ResultCollector & resultCollector,const vk::ProgramCollection<vk::ProgramBinary> & binaryCollection,const vk::InstanceInterface & vki,const vk::DeviceInterface & vkd,vk::VkPhysicalDevice physicalDevice,vk::VkDevice device,vk::VkDeviceSize size,deUint32 memoryTypeIndex,Usage usage,vk::VkSharingMode sharingMode,vk::VkQueue executionQueue,deUint32 executionQueueFamily,const vector<deUint32> & queueFamilies,const vk::VkDeviceSize maxBufferSize,const IVec2 maxImageSize)6448 void testCommand (TestLog&											log,
6449 				  tcu::ResultCollector&								resultCollector,
6450 				  const vk::ProgramCollection<vk::ProgramBinary>&	binaryCollection,
6451 				  const vk::InstanceInterface&						vki,
6452 				  const vk::DeviceInterface&						vkd,
6453 				  vk::VkPhysicalDevice								physicalDevice,
6454 				  vk::VkDevice										device,
6455 				  vk::VkDeviceSize									size,
6456 				  deUint32											memoryTypeIndex,
6457 				  Usage												usage,
6458 				  vk::VkSharingMode									sharingMode,
6459 				  vk::VkQueue										executionQueue,
6460 				  deUint32											executionQueueFamily,
6461 				  const vector<deUint32>&							queueFamilies,
6462 				  const vk::VkDeviceSize							maxBufferSize,
6463 				  const IVec2										maxImageSize)
6464 {
6465 	const deUint32							seed			= 2830980989u;
6466 	Memory									memory			(vki, vkd, physicalDevice, device, size, memoryTypeIndex, maxBufferSize, maxImageSize[0], maxImageSize[1]);
6467 	vector<Command*>						commands;
6468 	vector<pair<deUint32, vk::VkQueue> >	queues;
6469 
6470 	try
6471 	{
6472 		log << TestLog::Message << "Create commands" << TestLog::EndMessage;
6473 		createCommands(commands, seed, memory, usage, sharingMode);
6474 
6475 		for (size_t queueNdx = 0; queueNdx < queueFamilies.size(); queueNdx++)
6476 		{
6477 			vk::VkQueue queue;
6478 
6479 			vkd.getDeviceQueue(device, queueFamilies[queueNdx], 0, &queue);
6480 			queues.push_back(std::make_pair(queueFamilies[queueNdx], queue));
6481 		}
6482 
6483 		{
6484 			const tcu::ScopedLogSection section (log, "LogPrepare", "LogPrepare");
6485 
6486 			for (size_t cmdNdx = 0; cmdNdx < commands.size(); cmdNdx++)
6487 				commands[cmdNdx]->logPrepare(log, cmdNdx);
6488 		}
6489 
6490 		{
6491 			const tcu::ScopedLogSection section (log, "LogExecute", "LogExecute");
6492 
6493 			for (size_t cmdNdx = 0; cmdNdx < commands.size(); cmdNdx++)
6494 				commands[cmdNdx]->logExecute(log, cmdNdx);
6495 		}
6496 
6497 		{
6498 			const Context context (vki, vkd, physicalDevice, device, executionQueue, executionQueueFamily, queues, binaryCollection);
6499 
6500 			try
6501 			{
6502 				{
6503 					PrepareContext	prepareContext	(context, memory);
6504 
6505 					log << TestLog::Message << "Begin prepare" << TestLog::EndMessage;
6506 
6507 					for (size_t cmdNdx = 0; cmdNdx < commands.size(); cmdNdx++)
6508 					{
6509 						Command& command = *commands[cmdNdx];
6510 
6511 						try
6512 						{
6513 							command.prepare(prepareContext);
6514 						}
6515 						catch (...)
6516 						{
6517 							resultCollector.fail(de::toString(cmdNdx) + ":" + command.getName() + " failed to prepare for execution");
6518 							throw;
6519 						}
6520 					}
6521 
6522 					ExecuteContext	executeContext	(context);
6523 
6524 					log << TestLog::Message << "Begin execution" << TestLog::EndMessage;
6525 
6526 					for (size_t cmdNdx = 0; cmdNdx < commands.size(); cmdNdx++)
6527 					{
6528 						Command& command = *commands[cmdNdx];
6529 
6530 						try
6531 						{
6532 							command.execute(executeContext);
6533 						}
6534 						catch (...)
6535 						{
6536 							resultCollector.fail(de::toString(cmdNdx) + ":" + command.getName() + " failed to execute");
6537 							throw;
6538 						}
6539 					}
6540 
6541 					VK_CHECK(vkd.deviceWaitIdle(device));
6542 				}
6543 
6544 				{
6545 					const tcu::ScopedLogSection	section			(log, "Verify", "Verify");
6546 					VerifyContext				verifyContext	(log, resultCollector, context, size);
6547 
6548 					log << TestLog::Message << "Begin verify" << TestLog::EndMessage;
6549 
6550 					for (size_t cmdNdx = 0; cmdNdx < commands.size(); cmdNdx++)
6551 					{
6552 						Command& command = *commands[cmdNdx];
6553 
6554 						try
6555 						{
6556 							command.verify(verifyContext, cmdNdx);
6557 						}
6558 						catch (...)
6559 						{
6560 							resultCollector.fail(de::toString(cmdNdx) + ":" + command.getName() + " failed verification");
6561 							throw;
6562 						}
6563 					}
6564 				}
6565 
6566 				for (size_t commandNdx = 0; commandNdx < commands.size(); commandNdx++)
6567 				{
6568 					delete commands[commandNdx];
6569 					commands[commandNdx] = DE_NULL;
6570 				}
6571 			}
6572 			catch (...)
6573 			{
6574 				for (size_t commandNdx = 0; commandNdx < commands.size(); commandNdx++)
6575 				{
6576 					delete commands[commandNdx];
6577 					commands[commandNdx] = DE_NULL;
6578 				}
6579 
6580 				throw;
6581 			}
6582 		}
6583 	}
6584 	catch (...)
6585 	{
6586 		for (size_t commandNdx = 0; commandNdx < commands.size(); commandNdx++)
6587 		{
6588 			delete commands[commandNdx];
6589 			commands[commandNdx] = DE_NULL;
6590 		}
6591 
6592 		throw;
6593 	}
6594 }
6595 class MemoryTestInstance : public TestInstance
6596 {
6597 public:
6598 
6599 						MemoryTestInstance	(::vkt::Context& context, const TestConfig& config);
6600 
6601 	tcu::TestStatus		iterate				(void);
6602 
6603 private:
6604 	const TestConfig							m_config;
6605 	const vk::VkPhysicalDeviceMemoryProperties	m_memoryProperties;
6606 	deUint32									m_memoryTypeNdx;
6607 	tcu::ResultCollector						m_resultCollector;
6608 };
6609 
MemoryTestInstance(::vkt::Context & context,const TestConfig & config)6610 MemoryTestInstance::MemoryTestInstance (::vkt::Context& context, const TestConfig& config)
6611 	: TestInstance			(context)
6612 	, m_config				(config)
6613 	, m_memoryProperties	(vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()))
6614 	, m_memoryTypeNdx		(0)
6615 	, m_resultCollector		(context.getTestContext().getLog())
6616 {
6617 	TestLog&	log		= context.getTestContext().getLog();
6618 	{
6619 		const tcu::ScopedLogSection section (log, "TestCaseInfo", "Test Case Info");
6620 
6621 		log << TestLog::Message << "Buffer size: " << config.size << TestLog::EndMessage;
6622 		log << TestLog::Message << "Sharing: " << config.sharing << TestLog::EndMessage;
6623 		log << TestLog::Message << "Access: " << config.usage << TestLog::EndMessage;
6624 	}
6625 
6626 	{
6627 		const tcu::ScopedLogSection section (log, "MemoryProperties", "Memory Properties");
6628 
6629 		for (deUint32 heapNdx = 0; heapNdx < m_memoryProperties.memoryHeapCount; heapNdx++)
6630 		{
6631 			const tcu::ScopedLogSection heapSection (log, "Heap" + de::toString(heapNdx), "Heap " + de::toString(heapNdx));
6632 
6633 			log << TestLog::Message << "Size: " << m_memoryProperties.memoryHeaps[heapNdx].size << TestLog::EndMessage;
6634 			log << TestLog::Message << "Flags: " << m_memoryProperties.memoryHeaps[heapNdx].flags << TestLog::EndMessage;
6635 		}
6636 
6637 		for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < m_memoryProperties.memoryTypeCount; memoryTypeNdx++)
6638 		{
6639 			const tcu::ScopedLogSection memoryTypeSection (log, "MemoryType" + de::toString(memoryTypeNdx), "Memory type " + de::toString(memoryTypeNdx));
6640 
6641 			log << TestLog::Message << "Properties: " << m_memoryProperties.memoryTypes[memoryTypeNdx].propertyFlags << TestLog::EndMessage;
6642 			log << TestLog::Message << "Heap: " << m_memoryProperties.memoryTypes[memoryTypeNdx].heapIndex << TestLog::EndMessage;
6643 		}
6644 	}
6645 }
6646 
iterate(void)6647 tcu::TestStatus MemoryTestInstance::iterate (void)
6648 {
6649 	// \todo [2016-03-09 mika] Split different stages over multiple iterations
6650 	if (m_memoryTypeNdx < m_memoryProperties.memoryTypeCount)
6651 	{
6652 		TestLog&									log					= m_context.getTestContext().getLog();
6653 		const tcu::ScopedLogSection					section				(log, "MemoryType" + de::toString(m_memoryTypeNdx), "Memory type " + de::toString(m_memoryTypeNdx));
6654 		const vk::InstanceInterface&				vki					= m_context.getInstanceInterface();
6655 		const vk::VkPhysicalDevice					physicalDevice		= m_context.getPhysicalDevice();
6656 		const vk::DeviceInterface&					vkd					= m_context.getDeviceInterface();
6657 		const vk::VkDevice							device				= m_context.getDevice();
6658 		const vk::VkQueue							queue				= m_context.getUniversalQueue();
6659 		const deUint32								queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
6660 		const vk::VkPhysicalDeviceMemoryProperties	memoryProperties	= vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice);
6661 		vector<deUint32>							queues;
6662 
6663 		queues.push_back(queueFamilyIndex);
6664 
6665 		if (m_config.usage & (USAGE_HOST_READ|USAGE_HOST_WRITE)
6666 			&& !(memoryProperties.memoryTypes[m_memoryTypeNdx].propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
6667 		{
6668 			log << TestLog::Message << "Memory type not supported" << TestLog::EndMessage;
6669 
6670 			m_memoryTypeNdx++;
6671 			return tcu::TestStatus::incomplete();
6672 		}
6673 		else
6674 		{
6675 			try
6676 			{
6677 				const vk::VkBufferUsageFlags	bufferUsage		= usageToBufferUsageFlags(m_config.usage);
6678 				const vk::VkImageUsageFlags		imageUsage		= usageToImageUsageFlags(m_config.usage);
6679 				const vk::VkDeviceSize			maxBufferSize	= bufferUsage != 0
6680 																? roundBufferSizeToWxHx4(findMaxBufferSize(vkd, device, bufferUsage, m_config.sharing, queues, m_config.size, m_memoryTypeNdx))
6681 																: 0;
6682 				const IVec2						maxImageSize	= imageUsage != 0
6683 																? findMaxRGBA8ImageSize(vkd, device, imageUsage, m_config.sharing, queues, m_config.size, m_memoryTypeNdx)
6684 																: IVec2(0, 0);
6685 
6686 				log << TestLog::Message << "Max buffer size: " << maxBufferSize << TestLog::EndMessage;
6687 				log << TestLog::Message << "Max RGBA8 image size: " << maxImageSize << TestLog::EndMessage;
6688 
6689 				// Skip tests if there are no supported operations
6690 				if (maxBufferSize == 0
6691 					&& maxImageSize[0] == 0
6692 					&& (m_config.usage & (USAGE_HOST_READ|USAGE_HOST_WRITE)) == 0)
6693 				{
6694 					log << TestLog::Message << "Skipping memory type. None of the usages are supported." << TestLog::EndMessage;
6695 				}
6696 				else
6697 				{
6698 					testCommand(log, m_resultCollector, m_context.getBinaryCollection(), vki, vkd, physicalDevice, device, m_config.size, m_memoryTypeNdx, m_config.usage, m_config.sharing, queue, queueFamilyIndex, queues, maxBufferSize, maxImageSize);
6699 				}
6700 			}
6701 			catch (const tcu::TestError& e)
6702 			{
6703 				m_resultCollector.fail("Failed, got exception: " + string(e.getMessage()));
6704 			}
6705 
6706 			m_memoryTypeNdx++;
6707 			return tcu::TestStatus::incomplete();
6708 		}
6709 	}
6710 	else
6711 		return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
6712 }
6713 
6714 struct AddPrograms
6715 {
initvkt::memory::__anon09d9cc850111::AddPrograms6716 	void init (vk::SourceCollections& sources, TestConfig config) const
6717 	{
6718 		// Vertex buffer rendering
6719 		if (config.usage & USAGE_VERTEX_BUFFER)
6720 		{
6721 			const char* const vertexShader =
6722 				"#version 310 es\n"
6723 				"layout(location = 0) in highp vec2 a_position;\n"
6724 				"void main (void) {\n"
6725 				"\tgl_PointSize = 1.0;\n"
6726 				"\tgl_Position = vec4(1.998 * a_position - vec2(0.999), 0.0, 1.0);\n"
6727 				"}\n";
6728 
6729 			sources.glslSources.add("vertex-buffer.vert")
6730 				<< glu::VertexSource(vertexShader);
6731 		}
6732 
6733 		// Index buffer rendering
6734 		if (config.usage & USAGE_INDEX_BUFFER)
6735 		{
6736 			const char* const vertexShader =
6737 				"#version 310 es\n"
6738 				"highp float;\n"
6739 				"void main (void) {\n"
6740 				"\tgl_PointSize = 1.0;\n"
6741 				"\thighp vec2 pos = vec2(gl_VertexIndex % 256, gl_VertexIndex / 256) / vec2(255.0);\n"
6742 				"\tgl_Position = vec4(1.998 * pos - vec2(0.999), 0.0, 1.0);\n"
6743 				"}\n";
6744 
6745 			sources.glslSources.add("index-buffer.vert")
6746 				<< glu::VertexSource(vertexShader);
6747 		}
6748 
6749 		{
6750 			const char* const fragmentShader =
6751 				"#version 310 es\n"
6752 				"layout(location = 0) out highp vec4 o_color;\n"
6753 				"void main (void) {\n"
6754 				"\to_color = vec4(1.0);\n"
6755 				"}\n";
6756 
6757 			sources.glslSources.add("render-white.frag")
6758 				<< glu::FragmentSource(fragmentShader);
6759 		}
6760 	}
6761 };
6762 
6763 } // anonymous
6764 
createPipelineBarrierTests(tcu::TestContext & testCtx)6765 tcu::TestCaseGroup* createPipelineBarrierTests (tcu::TestContext& testCtx)
6766 {
6767 	de::MovePtr<tcu::TestCaseGroup>	group			(new tcu::TestCaseGroup(testCtx, "pipeline_barrier", "Pipeline barrier tests."));
6768 	const vk::VkDeviceSize			sizes[]			=
6769 	{
6770 		1024,			// 1K
6771 		8*1024,			// 8K
6772 		64*1024,		// 64K
6773 		1024*1024,		// 1M
6774 	};
6775 	const Usage						usages[]		=
6776 	{
6777 		USAGE_HOST_READ,
6778 		USAGE_HOST_WRITE,
6779 		USAGE_TRANSFER_SRC,
6780 		USAGE_TRANSFER_DST,
6781 		USAGE_VERTEX_BUFFER,
6782 		USAGE_INDEX_BUFFER
6783 	};
6784 	const Usage						readUsages[]		=
6785 	{
6786 		USAGE_HOST_READ,
6787 		USAGE_TRANSFER_SRC,
6788 		USAGE_VERTEX_BUFFER,
6789 		USAGE_INDEX_BUFFER
6790 	};
6791 
6792 	const Usage						writeUsages[]	=
6793 	{
6794 		USAGE_HOST_WRITE,
6795 		USAGE_TRANSFER_DST
6796 	};
6797 
6798 	for (size_t writeUsageNdx = 0; writeUsageNdx < DE_LENGTH_OF_ARRAY(writeUsages); writeUsageNdx++)
6799 	{
6800 		const Usage	writeUsage	= writeUsages[writeUsageNdx];
6801 
6802 		for (size_t readUsageNdx = 0; readUsageNdx < DE_LENGTH_OF_ARRAY(readUsages); readUsageNdx++)
6803 		{
6804 			const Usage						readUsage		= readUsages[readUsageNdx];
6805 			const Usage						usage			= writeUsage | readUsage;
6806 			const string					usageGroupName	(usageToName(usage));
6807 			de::MovePtr<tcu::TestCaseGroup>	usageGroup		(new tcu::TestCaseGroup(testCtx, usageGroupName.c_str(), usageGroupName.c_str()));
6808 
6809 			for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); sizeNdx++)
6810 			{
6811 				const vk::VkDeviceSize	size		= sizes[sizeNdx];
6812 				const string			testName	(de::toString((deUint64)(size)));
6813 				const TestConfig		config		=
6814 				{
6815 					usage,
6816 					size,
6817 					vk::VK_SHARING_MODE_EXCLUSIVE
6818 				};
6819 
6820 				usageGroup->addChild(new InstanceFactory1<MemoryTestInstance, TestConfig, AddPrograms>(testCtx,tcu::NODETYPE_SELF_VALIDATE,  testName, testName, AddPrograms(), config));
6821 			}
6822 
6823 			group->addChild(usageGroup.get());
6824 			usageGroup.release();
6825 		}
6826 	}
6827 
6828 	{
6829 		Usage all = (Usage)0;
6830 
6831 		for (size_t usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usages); usageNdx++)
6832 			all = all | usages[usageNdx];
6833 
6834 		{
6835 			const string					usageGroupName	("all");
6836 			de::MovePtr<tcu::TestCaseGroup>	usageGroup		(new tcu::TestCaseGroup(testCtx, usageGroupName.c_str(), usageGroupName.c_str()));
6837 
6838 			for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); sizeNdx++)
6839 			{
6840 				const vk::VkDeviceSize	size		= sizes[sizeNdx];
6841 				const string			testName	(de::toString((deUint64)(size)));
6842 				const TestConfig		config		=
6843 				{
6844 					all,
6845 					size,
6846 					vk::VK_SHARING_MODE_EXCLUSIVE
6847 				};
6848 
6849 				usageGroup->addChild(new InstanceFactory1<MemoryTestInstance, TestConfig, AddPrograms>(testCtx,tcu::NODETYPE_SELF_VALIDATE,  testName, testName, AddPrograms(), config));
6850 			}
6851 
6852 			group->addChild(usageGroup.get());
6853 			usageGroup.release();
6854 		}
6855 
6856 		{
6857 			const string					usageGroupName	("all_device");
6858 			de::MovePtr<tcu::TestCaseGroup>	usageGroup		(new tcu::TestCaseGroup(testCtx, usageGroupName.c_str(), usageGroupName.c_str()));
6859 
6860 			for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); sizeNdx++)
6861 			{
6862 				const vk::VkDeviceSize	size		= sizes[sizeNdx];
6863 				const string			testName	(de::toString((deUint64)(size)));
6864 				const TestConfig		config		=
6865 				{
6866 					(Usage)(all & (~(USAGE_HOST_READ|USAGE_HOST_WRITE))),
6867 					size,
6868 					vk::VK_SHARING_MODE_EXCLUSIVE
6869 				};
6870 
6871 				usageGroup->addChild(new InstanceFactory1<MemoryTestInstance, TestConfig, AddPrograms>(testCtx,tcu::NODETYPE_SELF_VALIDATE,  testName, testName, AddPrograms(), config));
6872 			}
6873 
6874 			group->addChild(usageGroup.get());
6875 			usageGroup.release();
6876 		}
6877 	}
6878 
6879 	return group.release();
6880 }
6881 
6882 } // memory
6883 } // vkt
6884