7108c43454d7d00bc1af1f001a36442ebee755dd
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / memory / vktMemoryPipelineBarrierTests.cpp
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
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
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
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
252 Usage operator| (Usage a, Usage b)
253 {
254         return (Usage)((deUint32)a | (deUint32)b);
255 }
256
257 Usage operator& (Usage a, Usage b)
258 {
259         return (Usage)((deUint32)a & (deUint32)b);
260 }
261
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
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
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
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
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
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
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
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
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
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
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
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
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
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
726         size_t  getSize                 (void) const { return m_data.size(); }
727
728 private:
729         vector<deUint8>         m_data;
730         vector<deUint64>        m_defined;
731 };
732
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
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
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
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
764 deUint8 ReferenceMemory::get (size_t pos) const
765 {
766         DE_ASSERT(isDefined(pos));
767         return m_data[pos];
768 }
769
770 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
788         vk::VkDeviceSize                getSize                         (void) const { return m_size; }
789         vk::VkDeviceSize                getMaxBufferSize        (void) const { return m_maxBufferSize; }
790         bool                                    getSupportBuffers       (void) const { return m_maxBufferSize > 0; }
791
792         deInt32                                 getMaxImageWidth        (void) const { return m_maxImageWidth; }
793         deInt32                                 getMaxImageHeight       (void) const { return m_maxImageHeight; }
794         bool                                    getSupportImages        (void) const { return m_maxImageWidth > 0; }
795
796         const vk::VkMemoryType& getMemoryType           (void) const { return m_memoryType; }
797         deUint32                                getMemoryTypeIndex      (void) const { return m_memoryTypeIndex; }
798         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
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
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
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
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
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
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:
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
1019         const vk::InstanceInterface&                                    getInstanceInterface    (void) const { return m_vki; }
1020         vk::VkPhysicalDevice                                                    getPhysicalDevice               (void) const { return m_physicalDevice; }
1021         vk::VkDevice                                                                    getDevice                               (void) const { return m_device; }
1022         const vk::DeviceInterface&                                              getDeviceInterface              (void) const { return m_vkd; }
1023         vk::VkQueue                                                                             getQueue                                (void) const { return m_queue; }
1024         deUint32                                                                                getQueueFamily                  (void) const { return m_queueFamilyIndex; }
1025         const vector<pair<deUint32, vk::VkQueue> >&             getQueues                               (void) const { return m_queues; }
1026         const vector<deUint32>                                                  getQueueFamilies                (void) const { return m_queueFamilies; }
1027         vk::VkCommandPool                                                               getCommandPool                  (void) const { return *m_commandPool; }
1028         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:
1046                                                         PrepareContext  (const Context& context,
1047                                                                                          const Memory&  memory)
1048                 : m_context     (context)
1049                 , m_memory      (memory)
1050         {
1051         }
1052
1053         const Memory&                                                                   getMemory                               (void) const { return m_memory; }
1054         const Context&                                                                  getContext                              (void) const { return m_context; }
1055         const vk::ProgramCollection<vk::ProgramBinary>& getBinaryCollection             (void) const { return m_context.getBinaryCollection(); }
1056
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
1067         vk::VkBuffer                    getBuffer               (void) const { return *m_currentBuffer; }
1068         vk::VkDeviceSize                getBufferSize   (void) const
1069         {
1070                 DE_ASSERT(m_currentBuffer);
1071                 return m_currentBufferSize;
1072         }
1073
1074         void                                    releaseBuffer   (void) { m_currentBuffer.disown(); }
1075
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
1092         void                            setImageLayout  (vk::VkImageLayout layout)
1093         {
1094                 DE_ASSERT(m_currentImage);
1095                 m_currentImageLayout = layout;
1096         }
1097
1098         vk::VkImage                     getImage                (void) const { return *m_currentImage; }
1099         deInt32                         getImageWidth   (void) const
1100         {
1101                 DE_ASSERT(m_currentImage);
1102                 return m_currentImageWidth;
1103         }
1104         deInt32                         getImageHeight  (void) const
1105         {
1106                 DE_ASSERT(m_currentImage);
1107                 return m_currentImageHeight;
1108         }
1109         vk::VkDeviceSize        getImageMemorySize      (void) const
1110         {
1111                 DE_ASSERT(m_currentImage);
1112                 return m_currentImageMemorySize;
1113         }
1114
1115         void                                    releaseImage    (void) { m_currentImage.disown(); }
1116
1117         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:
1140                                         ExecuteContext  (const Context& context)
1141                 : m_context     (context)
1142         {
1143         }
1144
1145         const Context&  getContext              (void) const { return m_context; }
1146         void                    setMapping              (void* ptr) { m_mapping = ptr; }
1147         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:
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
1168         const Context&                  getContext                      (void) const { return m_context; }
1169         TestLog&                                getLog                          (void) const { return m_log; }
1170         tcu::ResultCollector&   getResultCollector      (void) const { return m_resultCollector; }
1171
1172         ReferenceMemory&                getReference            (void) { return m_reference; }
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.
1187         virtual                         ~Command        (void) {}
1188
1189         // Get name of the command
1190         virtual const char*     getName         (void) const = 0;
1191
1192         // Log prepare operations
1193         virtual void            logPrepare      (TestLog&, size_t) const {}
1194         // Log executed operations
1195         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.
1200         virtual void            prepare         (PrepareContext&) {}
1201
1202         // Execute command. Write or read mapped memory, submit commands to queue
1203         // etc.
1204         virtual void            execute         (ExecuteContext&) {}
1205
1206         // Verify that results are correct.
1207         virtual void            verify          (VerifyContext&, size_t) {}
1208
1209 protected:
1210         // Allow only inheritance
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:
1222                                                 Map                     (void) {}
1223                                                 ~Map            (void) {}
1224         const char*                     getName         (void) const { return "Map"; }
1225
1226
1227         void                            logExecute      (TestLog& log, size_t commandIndex) const
1228         {
1229                 log << TestLog::Message << commandIndex << ":" << getName() << " Map memory" << TestLog::EndMessage;
1230         }
1231
1232         void                            prepare         (PrepareContext& context)
1233         {
1234                 m_memory        = context.getMemory().getMemory();
1235                 m_size          = context.getMemory().getSize();
1236         }
1237
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:
1254                                                 UnMap           (void) {}
1255                                                 ~UnMap          (void) {}
1256         const char*                     getName         (void) const { return "UnMap"; }
1257
1258         void                            logExecute      (TestLog& log, size_t commandIndex) const
1259         {
1260                 log << TestLog::Message << commandIndex << ": Unmap memory" << TestLog::EndMessage;
1261         }
1262
1263         void                            prepare         (PrepareContext& context)
1264         {
1265                 m_memory        = context.getMemory().getMemory();
1266         }
1267
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:
1284                                                 Invalidate      (void) {}
1285                                                 ~Invalidate     (void) {}
1286         const char*                     getName         (void) const { return "Invalidate"; }
1287
1288         void                            logExecute      (TestLog& log, size_t commandIndex) const
1289         {
1290                 log << TestLog::Message << commandIndex << ": Invalidate mapped memory" << TestLog::EndMessage;
1291         }
1292
1293         void                            prepare         (PrepareContext& context)
1294         {
1295                 m_memory        = context.getMemory().getMemory();
1296                 m_size          = context.getMemory().getSize();
1297         }
1298
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:
1315                                                 Flush           (void) {}
1316                                                 ~Flush          (void) {}
1317         const char*                     getName         (void) const { return "Flush"; }
1318
1319         void                            logExecute      (TestLog& log, size_t commandIndex) const
1320         {
1321                 log << TestLog::Message << commandIndex << ": Flush mapped memory" << TestLog::EndMessage;
1322         }
1323
1324         void                            prepare         (PrepareContext& context)
1325         {
1326                 m_memory        = context.getMemory().getMemory();
1327                 m_size          = context.getMemory().getSize();
1328         }
1329
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);
1348                                         ~HostMemoryAccess       (void) {}
1349         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
1366 HostMemoryAccess::HostMemoryAccess (bool read, bool write, deUint32 seed)
1367         : m_read        (read)
1368         , m_write       (write)
1369         , m_seed        (seed)
1370 {
1371 }
1372
1373 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
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
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
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);
1497                                                                         ~CreateBuffer   (void) {}
1498         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
1508 CreateBuffer::CreateBuffer (vk::VkBufferUsageFlags      usage,
1509                                                         vk::VkSharingMode               sharing)
1510         : m_usage       (usage)
1511         , m_sharing     (sharing)
1512 {
1513 }
1514
1515 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
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);
1534                                                         ~DestroyBuffer  (void) {}
1535         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
1545 DestroyBuffer::DestroyBuffer (void)
1546 {
1547 }
1548
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
1555 void DestroyBuffer::logExecute (TestLog& log, size_t commandIndex) const
1556 {
1557         log << TestLog::Message << commandIndex << ":" << getName() << " Destroy buffer" << TestLog::EndMessage;
1558 }
1559
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:
1571                                 BindBufferMemory        (void) {}
1572                                 ~BindBufferMemory       (void) {}
1573         const char*     getName                         (void) const { return "BindBufferMemory"; }
1574
1575         void            logPrepare                      (TestLog& log, size_t commandIndex) const;
1576         void            prepare                         (PrepareContext& context);
1577 };
1578
1579 void BindBufferMemory::logPrepare (TestLog& log, size_t commandIndex) const
1580 {
1581         log << TestLog::Message << commandIndex << ":" << getName() << " Bind memory to buffer" << TestLog::EndMessage;
1582 }
1583
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);
1597                                                                         ~CreateImage    (void) {}
1598         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
1611 CreateImage::CreateImage (vk::VkImageUsageFlags usage,
1612                                                   vk::VkSharingMode             sharing)
1613         : m_usage       (usage)
1614         , m_sharing     (sharing)
1615 {
1616 }
1617
1618 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
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
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);
1671                                                         ~DestroyImage   (void) {}
1672         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
1682 DestroyImage::DestroyImage (void)
1683 {
1684 }
1685
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
1693 void DestroyImage::logExecute (TestLog& log, size_t commandIndex) const
1694 {
1695         log << TestLog::Message << commandIndex << ":" << getName() << " Destroy image" << TestLog::EndMessage;
1696 }
1697
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:
1709                                 BindImageMemory         (void) {}
1710                                 ~BindImageMemory        (void) {}
1711         const char*     getName                         (void) const { return "BindImageMemory"; }
1712
1713         void            logPrepare                      (TestLog& log, size_t commandIndex) const;
1714         void            prepare                         (PrepareContext& context);
1715 };
1716
1717 void BindImageMemory::logPrepare (TestLog& log, size_t commandIndex) const
1718 {
1719         log << TestLog::Message << commandIndex << ":" << getName() << " Bind memory to image" << TestLog::EndMessage;
1720 }
1721
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:
1733                                 QueueWaitIdle   (void) {}
1734                                 ~QueueWaitIdle  (void) {}
1735         const char*     getName                 (void) const { return "QueuetWaitIdle"; }
1736
1737         void            logExecute              (TestLog& log, size_t commandIndex) const;
1738         void            execute                 (ExecuteContext& context);
1739 };
1740
1741 void QueueWaitIdle::logExecute (TestLog& log, size_t commandIndex) const
1742 {
1743         log << TestLog::Message << commandIndex << ":" << getName() << " Queue wait idle" << TestLog::EndMessage;
1744 }
1745
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:
1757                                 DeviceWaitIdle  (void) {}
1758                                 ~DeviceWaitIdle (void) {}
1759         const char*     getName                 (void) const { return "DeviceWaitIdle"; }
1760
1761         void            logExecute              (TestLog& log, size_t commandIndex) const;
1762         void            execute                 (ExecuteContext& context);
1763 };
1764
1765 void DeviceWaitIdle::logExecute (TestLog& log, size_t commandIndex) const
1766 {
1767         log << TestLog::Message << commandIndex << ":" << getName() << " Device wait idle" << TestLog::EndMessage;
1768 }
1769
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:
1781                                                                 SubmitContext           (const PrepareContext&          context,
1782                                                                                                          const vk::VkCommandBuffer      commandBuffer)
1783                 : m_context                     (context)
1784                 , m_commandBuffer       (commandBuffer)
1785         {
1786         }
1787
1788         const Memory&                           getMemory                       (void) const { return m_context.getMemory(); }
1789         const Context&                          getContext                      (void) const { return m_context.getContext(); }
1790         vk::VkCommandBuffer                     getCommandBuffer        (void) const { return m_commandBuffer; }
1791
1792         vk::VkBuffer                            getBuffer                       (void) const { return m_context.getBuffer(); }
1793         vk::VkDeviceSize                        getBufferSize           (void) const { return m_context.getBufferSize(); }
1794
1795         vk::VkImage                                     getImage                        (void) const { return m_context.getImage(); }
1796         deInt32                                         getImageWidth           (void) const { return m_context.getImageWidth(); }
1797         deInt32                                         getImageHeight          (void) const { return m_context.getImageHeight(); }
1798         vk::VkImageLayout                       getImageLayout          (void) const { return m_context.getImageLayout(); }
1799
1800 private:
1801         const PrepareContext&           m_context;
1802         const vk::VkCommandBuffer       m_commandBuffer;
1803 };
1804
1805 class CmdCommand
1806 {
1807 public:
1808         virtual                         ~CmdCommand     (void) {}
1809         virtual const char*     getName         (void) const = 0;
1810
1811         // Log things that are done during prepare
1812         virtual void            logPrepare      (TestLog&, size_t) const {}
1813         // Log submitted calls etc.
1814         virtual void            logSubmit       (TestLog&, size_t) const {}
1815
1816         // Allocate vulkan resources and prepare for submit.
1817         virtual void            prepare         (PrepareContext&) {}
1818
1819         // Submit commands to command buffer.
1820         virtual void            submit          (SubmitContext&) {}
1821
1822         // Verify results
1823         virtual void            verify          (VerifyContext&, size_t) {}
1824 };
1825
1826 class SubmitCommandBuffer : public Command
1827 {
1828 public:
1829                                         SubmitCommandBuffer             (const vector<CmdCommand*>& commands);
1830                                         ~SubmitCommandBuffer    (void);
1831
1832         const char*             getName                                 (void) const { return "SubmitCommandBuffer"; }
1833         void                    logExecute                              (TestLog& log, size_t commandIndex) const;
1834         void                    logPrepare                              (TestLog& log, size_t commandIndex) const;
1835
1836         // Allocate command buffer and submit commands to command buffer
1837         void                    prepare                                 (PrepareContext& context);
1838         void                    execute                                 (ExecuteContext& context);
1839
1840         // Verify that results are correct.
1841         void                    verify                                  (VerifyContext& context, size_t commandIndex);
1842
1843 private:
1844         vector<CmdCommand*>                             m_commands;
1845         vk::Move<vk::VkCommandBuffer>   m_commandBuffer;
1846 };
1847
1848 SubmitCommandBuffer::SubmitCommandBuffer (const vector<CmdCommand*>& commands)
1849         : m_commands    (commands)
1850 {
1851 }
1852
1853 SubmitCommandBuffer::~SubmitCommandBuffer (void)
1854 {
1855         for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
1856                 delete m_commands[cmdNdx];
1857 }
1858
1859 void SubmitCommandBuffer::prepare (PrepareContext& context)
1860 {
1861         const vk::DeviceInterface&      vkd                     = context.getContext().getDeviceInterface();
1862         const vk::VkDevice                      device          = context.getContext().getDevice();
1863         const vk::VkCommandPool         commandPool     = context.getContext().getCommandPool();
1864
1865         m_commandBuffer = createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1866
1867         for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
1868         {
1869                 CmdCommand& command = *m_commands[cmdNdx];
1870
1871                 command.prepare(context);
1872         }
1873
1874         {
1875                 SubmitContext submitContext (context, *m_commandBuffer);
1876
1877                 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
1878                 {
1879                         CmdCommand& command = *m_commands[cmdNdx];
1880
1881                         command.submit(submitContext);
1882                 }
1883
1884                 VK_CHECK(vkd.endCommandBuffer(*m_commandBuffer));
1885         }
1886 }
1887
1888 void SubmitCommandBuffer::execute (ExecuteContext& context)
1889 {
1890         const vk::DeviceInterface&      vkd             = context.getContext().getDeviceInterface();
1891         const vk::VkCommandBuffer       cmd             = *m_commandBuffer;
1892         const vk::VkQueue                       queue   = context.getContext().getQueue();
1893         const vk::VkSubmitInfo          submit  =
1894         {
1895                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1896                 DE_NULL,
1897
1898                 0,
1899                 DE_NULL,
1900                 (const vk::VkPipelineStageFlags*)DE_NULL,
1901
1902                 1,
1903                 &cmd,
1904
1905                 0,
1906                 DE_NULL
1907         };
1908
1909         vkd.queueSubmit(queue, 1, &submit, 0);
1910 }
1911
1912 void SubmitCommandBuffer::verify (VerifyContext& context, size_t commandIndex)
1913 {
1914         const string                            sectionName     (de::toString(commandIndex) + ":" + getName());
1915         const tcu::ScopedLogSection     section         (context.getLog(), sectionName, sectionName);
1916
1917         for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
1918                 m_commands[cmdNdx]->verify(context, cmdNdx);
1919 }
1920
1921 void SubmitCommandBuffer::logPrepare (TestLog& log, size_t commandIndex) const
1922 {
1923         const string                            sectionName     (de::toString(commandIndex) + ":" + getName());
1924         const tcu::ScopedLogSection     section         (log, sectionName, sectionName);
1925
1926         for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
1927                 m_commands[cmdNdx]->logPrepare(log, cmdNdx);
1928 }
1929
1930 void SubmitCommandBuffer::logExecute (TestLog& log, size_t commandIndex) const
1931 {
1932         const string                            sectionName     (de::toString(commandIndex) + ":" + getName());
1933         const tcu::ScopedLogSection     section         (log, sectionName, sectionName);
1934
1935         for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
1936                 m_commands[cmdNdx]->logSubmit(log, cmdNdx);
1937 }
1938
1939 class PipelineBarrier : public CmdCommand
1940 {
1941 public:
1942         enum Type
1943         {
1944                 TYPE_GLOBAL = 0,
1945                 TYPE_BUFFER,
1946                 TYPE_IMAGE,
1947                 TYPE_LAST
1948         };
1949                                                                         PipelineBarrier         (const vk::VkPipelineStageFlags srcStages,
1950                                                                                                                  const vk::VkAccessFlags                srcAccesses,
1951                                                                                                                  const vk::VkPipelineStageFlags dstStages,
1952                                                                                                                  const vk::VkAccessFlags                dstAccesses,
1953                                                                                                                  Type                                                   type);
1954                                                                         ~PipelineBarrier        (void) {}
1955         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 };
1967
1968 PipelineBarrier::PipelineBarrier (const vk::VkPipelineStageFlags        srcStages,
1969                                                                   const vk::VkAccessFlags                       srcAccesses,
1970                                                                   const vk::VkPipelineStageFlags        dstStages,
1971                                                                   const vk::VkAccessFlags                       dstAccesses,
1972                                                                   Type                                                          type)
1973         : m_srcStages   (srcStages)
1974         , m_srcAccesses (srcAccesses)
1975         , m_dstStages   (dstStages)
1976         , m_dstAccesses (dstAccesses)
1977         , m_type                (type)
1978 {
1979 }
1980
1981 void PipelineBarrier::logSubmit (TestLog& log, size_t commandIndex) const
1982 {
1983         log << TestLog::Message << commandIndex << ":" << getName()
1984                 << " " << (m_type == TYPE_GLOBAL ? "Global pipeline barrier"
1985                                         : m_type == TYPE_BUFFER ? "Buffer pipeline barrier"
1986                                         : "Image pipeline barrier")
1987                 << ", srcStages: " << vk::getPipelineStageFlagsStr(m_srcStages) << ", srcAccesses: " << vk::getAccessFlagsStr(m_srcAccesses)
1988                 << ", dstStages: " << vk::getPipelineStageFlagsStr(m_dstStages) << ", dstAccesses: " << vk::getAccessFlagsStr(m_dstAccesses) << TestLog::EndMessage;
1989 }
1990
1991 void PipelineBarrier::submit (SubmitContext& context)
1992 {
1993         const vk::DeviceInterface&      vkd     = context.getContext().getDeviceInterface();
1994         const vk::VkCommandBuffer       cmd     = context.getCommandBuffer();
1995
1996         // \todo [2016-01-08 pyry] This could be cleaned up thanks to latest API changes
1997
1998         switch (m_type)
1999         {
2000                 case TYPE_GLOBAL:
2001                 {
2002                         const vk::VkMemoryBarrier       barrier         =
2003                         {
2004                                 vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,
2005                                 DE_NULL,
2006
2007                                 m_srcAccesses,
2008                                 m_dstAccesses
2009                         };
2010
2011                         vkd.cmdPipelineBarrier(cmd, m_srcStages, m_dstStages, (vk::VkDependencyFlags)0, 1, &barrier, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
2012                         break;
2013                 }
2014
2015                 case TYPE_BUFFER:
2016                 {
2017                         const vk::VkBufferMemoryBarrier barrier         =
2018                         {
2019                                 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2020                                 DE_NULL,
2021
2022                                 m_srcAccesses,
2023                                 m_dstAccesses,
2024
2025                                 vk::VK_QUEUE_FAMILY_IGNORED,
2026                                 vk::VK_QUEUE_FAMILY_IGNORED,
2027
2028                                 context.getBuffer(),
2029                                 0,
2030                                 vk::VK_WHOLE_SIZE
2031                         };
2032
2033                         vkd.cmdPipelineBarrier(cmd, m_srcStages, m_dstStages, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 1, &barrier, 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
2034                         break;
2035                 }
2036
2037                 case TYPE_IMAGE:
2038                 {
2039                         const vk::VkImageMemoryBarrier  barrier         =
2040                         {
2041                                 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2042                                 DE_NULL,
2043
2044                                 m_srcAccesses,
2045                                 m_dstAccesses,
2046
2047                                 context.getImageLayout(),
2048                                 context.getImageLayout(),
2049
2050                                 vk::VK_QUEUE_FAMILY_IGNORED,
2051                                 vk::VK_QUEUE_FAMILY_IGNORED,
2052
2053                                 context.getImage(),
2054                                 {
2055                                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
2056                                         0, 1,
2057                                         0, 1
2058                                 }
2059                         };
2060
2061                         vkd.cmdPipelineBarrier(cmd, m_srcStages, m_dstStages, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
2062                         break;
2063                 }
2064
2065                 default:
2066                         DE_FATAL("Unknown pipeline barrier type");
2067         }
2068 }
2069
2070 class ImageTransition : public CmdCommand
2071 {
2072 public:
2073                                                 ImageTransition         (vk::VkPipelineStageFlags       srcStages,
2074                                                                                          vk::VkAccessFlags                      srcAccesses,
2075
2076                                                                                          vk::VkPipelineStageFlags       dstStages,
2077                                                                                          vk::VkAccessFlags                      dstAccesses,
2078
2079                                                                                          vk::VkImageLayout                      srcLayout,
2080                                                                                          vk::VkImageLayout                      dstLayout);
2081
2082                                                 ~ImageTransition        (void) {}
2083         const char*                     getName                         (void) const { return "ImageTransition"; }
2084
2085         void                            prepare                         (PrepareContext& context);
2086         void                            logSubmit                       (TestLog& log, size_t commandIndex) const;
2087         void                            submit                          (SubmitContext& context);
2088         void                            verify                          (VerifyContext& context, size_t);
2089
2090 private:
2091         const vk::VkPipelineStageFlags  m_srcStages;
2092         const vk::VkAccessFlags                 m_srcAccesses;
2093         const vk::VkPipelineStageFlags  m_dstStages;
2094         const vk::VkAccessFlags                 m_dstAccesses;
2095         const vk::VkImageLayout                 m_srcLayout;
2096         const vk::VkImageLayout                 m_dstLayout;
2097
2098         vk::VkDeviceSize                                m_imageMemorySize;
2099 };
2100
2101 ImageTransition::ImageTransition (vk::VkPipelineStageFlags      srcStages,
2102                                                                   vk::VkAccessFlags                     srcAccesses,
2103
2104                                                                   vk::VkPipelineStageFlags      dstStages,
2105                                                                   vk::VkAccessFlags                     dstAccesses,
2106
2107                                                                   vk::VkImageLayout                     srcLayout,
2108                                                                   vk::VkImageLayout                     dstLayout)
2109         : m_srcStages           (srcStages)
2110         , m_srcAccesses         (srcAccesses)
2111         , m_dstStages           (dstStages)
2112         , m_dstAccesses         (dstAccesses)
2113         , m_srcLayout           (srcLayout)
2114         , m_dstLayout           (dstLayout)
2115 {
2116 }
2117
2118 void ImageTransition::logSubmit (TestLog& log, size_t commandIndex) const
2119 {
2120         log << TestLog::Message << commandIndex << ":" << getName()
2121                 << " Image transition pipeline barrier"
2122                 << ", srcStages: " << vk::getPipelineStageFlagsStr(m_srcStages) << ", srcAccesses: " << vk::getAccessFlagsStr(m_srcAccesses)
2123                 << ", dstStages: " << vk::getPipelineStageFlagsStr(m_dstStages) << ", dstAccesses: " << vk::getAccessFlagsStr(m_dstAccesses)
2124                 << ", srcLayout: " << m_srcLayout << ", dstLayout: " << m_dstLayout << TestLog::EndMessage;
2125 }
2126
2127 void ImageTransition::prepare (PrepareContext& context)
2128 {
2129         DE_ASSERT(context.getImageLayout() == vk::VK_IMAGE_LAYOUT_UNDEFINED || m_srcLayout == vk::VK_IMAGE_LAYOUT_UNDEFINED || context.getImageLayout() == m_srcLayout);
2130
2131         context.setImageLayout(m_dstLayout);
2132         m_imageMemorySize = context.getImageMemorySize();
2133 }
2134
2135 void ImageTransition::submit (SubmitContext& context)
2136 {
2137         const vk::DeviceInterface&              vkd                     = context.getContext().getDeviceInterface();
2138         const vk::VkCommandBuffer               cmd                     = context.getCommandBuffer();
2139         const vk::VkImageMemoryBarrier  barrier         =
2140         {
2141                 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2142                 DE_NULL,
2143
2144                 m_srcAccesses,
2145                 m_dstAccesses,
2146
2147                 m_srcLayout,
2148                 m_dstLayout,
2149
2150                 vk::VK_QUEUE_FAMILY_IGNORED,
2151                 vk::VK_QUEUE_FAMILY_IGNORED,
2152
2153                 context.getImage(),
2154                 {
2155                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
2156                         0u, 1u,
2157                         0u, 1u
2158                 }
2159         };
2160
2161         vkd.cmdPipelineBarrier(cmd, m_srcStages, m_dstStages, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
2162 }
2163
2164 void ImageTransition::verify (VerifyContext& context, size_t)
2165 {
2166         context.getReference().setUndefined(0, (size_t)m_imageMemorySize);
2167 }
2168
2169 class FillBuffer : public CmdCommand
2170 {
2171 public:
2172                                                 FillBuffer      (deUint32 value) : m_value(value) {}
2173                                                 ~FillBuffer     (void) {}
2174         const char*                     getName         (void) const { return "FillBuffer"; }
2175
2176         void                            logSubmit       (TestLog& log, size_t commandIndex) const;
2177         void                            submit          (SubmitContext& context);
2178         void                            verify          (VerifyContext& context, size_t commandIndex);
2179
2180 private:
2181         const deUint32          m_value;
2182         vk::VkDeviceSize        m_bufferSize;
2183 };
2184
2185 void FillBuffer::logSubmit (TestLog& log, size_t commandIndex) const
2186 {
2187         log << TestLog::Message << commandIndex << ":" << getName() << " Fill value: " << m_value << TestLog::EndMessage;
2188 }
2189
2190 void FillBuffer::submit (SubmitContext& context)
2191 {
2192         const vk::DeviceInterface&      vkd                     = context.getContext().getDeviceInterface();
2193         const vk::VkCommandBuffer       cmd                     = context.getCommandBuffer();
2194         const vk::VkBuffer                      buffer          = context.getBuffer();
2195         const vk::VkDeviceSize          sizeMask        = ~(0x3ull); // \note Round down to multiple of 4
2196
2197         m_bufferSize = sizeMask & context.getBufferSize();
2198         vkd.cmdFillBuffer(cmd, buffer, 0, m_bufferSize, m_value);
2199 }
2200
2201 void FillBuffer::verify (VerifyContext& context, size_t)
2202 {
2203         ReferenceMemory&        reference       = context.getReference();
2204
2205         for (size_t ndx = 0; ndx < m_bufferSize; ndx++)
2206         {
2207 #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
2208                 reference.set(ndx, (deUint8)(0xffu & (m_value >> (8*(ndx % 4)))));
2209 #else
2210                 reference.set(ndx, (deUint8)(0xffu & (m_value >> (8*(3 - (ndx % 4))))));
2211 #endif
2212         }
2213 }
2214
2215 class UpdateBuffer : public CmdCommand
2216 {
2217 public:
2218                                                 UpdateBuffer    (deUint32 seed) : m_seed(seed) {}
2219                                                 ~UpdateBuffer   (void) {}
2220         const char*                     getName                 (void) const { return "UpdateBuffer"; }
2221
2222         void                            logSubmit               (TestLog& log, size_t commandIndex) const;
2223         void                            submit                  (SubmitContext& context);
2224         void                            verify                  (VerifyContext& context, size_t commandIndex);
2225
2226 private:
2227         const deUint32          m_seed;
2228         vk::VkDeviceSize        m_bufferSize;
2229 };
2230
2231 void UpdateBuffer::logSubmit (TestLog& log, size_t commandIndex) const
2232 {
2233         log << TestLog::Message << commandIndex << ":" << getName() << " Update buffer, seed: " << m_seed << TestLog::EndMessage;
2234 }
2235
2236 void UpdateBuffer::submit (SubmitContext& context)
2237 {
2238         const vk::DeviceInterface&      vkd                     = context.getContext().getDeviceInterface();
2239         const vk::VkCommandBuffer       cmd                     = context.getCommandBuffer();
2240         const vk::VkBuffer                      buffer          = context.getBuffer();
2241         const size_t                            blockSize       = 65536;
2242         std::vector<deUint8>            data            (blockSize, 0);
2243         de::Random                                      rng                     (m_seed);
2244
2245         m_bufferSize = context.getBufferSize();
2246
2247         for (size_t updated = 0; updated < m_bufferSize; updated += blockSize)
2248         {
2249                 for (size_t ndx = 0; ndx < data.size(); ndx++)
2250                         data[ndx] = rng.getUint8();
2251
2252                 if (m_bufferSize - updated > blockSize)
2253                         vkd.cmdUpdateBuffer(cmd, buffer, updated, blockSize, (const deUint32*)(&data[0]));
2254                 else
2255                         vkd.cmdUpdateBuffer(cmd, buffer, updated, m_bufferSize - updated, (const deUint32*)(&data[0]));
2256         }
2257 }
2258
2259 void UpdateBuffer::verify (VerifyContext& context, size_t)
2260 {
2261         ReferenceMemory&        reference       = context.getReference();
2262         const size_t            blockSize       = 65536;
2263         vector<deUint8>         data            (blockSize, 0);
2264         de::Random                      rng                     (m_seed);
2265
2266         for (size_t updated = 0; updated < m_bufferSize; updated += blockSize)
2267         {
2268                 for (size_t ndx = 0; ndx < data.size(); ndx++)
2269                         data[ndx] = rng.getUint8();
2270
2271                 if (m_bufferSize - updated > blockSize)
2272                         reference.setData(updated, blockSize, &data[0]);
2273                 else
2274                         reference.setData(updated, (size_t)(m_bufferSize - updated), &data[0]);
2275         }
2276 }
2277
2278 class BufferCopyToBuffer : public CmdCommand
2279 {
2280 public:
2281                                                                         BufferCopyToBuffer      (void) {}
2282                                                                         ~BufferCopyToBuffer     (void) {}
2283         const char*                                             getName                         (void) const { return "BufferCopyToBuffer"; }
2284
2285         void                                                    logPrepare                      (TestLog& log, size_t commandIndex) const;
2286         void                                                    prepare                         (PrepareContext& context);
2287         void                                                    logSubmit                       (TestLog& log, size_t commandIndex) const;
2288         void                                                    submit                          (SubmitContext& context);
2289         void                                                    verify                          (VerifyContext& context, size_t commandIndex);
2290
2291 private:
2292         vk::VkDeviceSize                                m_bufferSize;
2293         vk::Move<vk::VkBuffer>                  m_dstBuffer;
2294         vk::Move<vk::VkDeviceMemory>    m_memory;
2295 };
2296
2297 void BufferCopyToBuffer::logPrepare (TestLog& log, size_t commandIndex) const
2298 {
2299         log << TestLog::Message << commandIndex << ":" << getName() << " Allocate destination buffer for buffer to buffer copy." << TestLog::EndMessage;
2300 }
2301
2302 void BufferCopyToBuffer::prepare (PrepareContext& context)
2303 {
2304         const vk::InstanceInterface&    vki                             = context.getContext().getInstanceInterface();
2305         const vk::DeviceInterface&              vkd                             = context.getContext().getDeviceInterface();
2306         const vk::VkPhysicalDevice              physicalDevice  = context.getContext().getPhysicalDevice();
2307         const vk::VkDevice                              device                  = context.getContext().getDevice();
2308         const vector<deUint32>&                 queueFamilies   = context.getContext().getQueueFamilies();
2309
2310         m_bufferSize = context.getBufferSize();
2311
2312         m_dstBuffer     = createBuffer(vkd, device, m_bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies);
2313         m_memory        = bindBufferMemory(vki, vkd, physicalDevice, device, *m_dstBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
2314 }
2315
2316 void BufferCopyToBuffer::logSubmit (TestLog& log, size_t commandIndex) const
2317 {
2318         log << TestLog::Message << commandIndex << ":" << getName() << " Copy buffer to another buffer" << TestLog::EndMessage;
2319 }
2320
2321 void BufferCopyToBuffer::submit (SubmitContext& context)
2322 {
2323         const vk::DeviceInterface&      vkd                             = context.getContext().getDeviceInterface();
2324         const vk::VkCommandBuffer       commandBuffer   = context.getCommandBuffer();
2325         const vk::VkBufferCopy          range                   =
2326         {
2327                 0, 0, // Offsets
2328                 m_bufferSize
2329         };
2330
2331         vkd.cmdCopyBuffer(commandBuffer, context.getBuffer(), *m_dstBuffer, 1, &range);
2332 }
2333
2334 void BufferCopyToBuffer::verify (VerifyContext& context, size_t commandIndex)
2335 {
2336         tcu::ResultCollector&                                   resultCollector (context.getResultCollector());
2337         ReferenceMemory&                                                reference               (context.getReference());
2338         const vk::DeviceInterface&                              vkd                             = context.getContext().getDeviceInterface();
2339         const vk::VkDevice                                              device                  = context.getContext().getDevice();
2340         const vk::VkQueue                                               queue                   = context.getContext().getQueue();
2341         const vk::VkCommandPool                                 commandPool             = context.getContext().getCommandPool();
2342         const vk::Unique<vk::VkCommandBuffer>   commandBuffer   (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2343         const vk::VkBufferMemoryBarrier                 barrier                 =
2344         {
2345                 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2346                 DE_NULL,
2347
2348                 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2349                 vk::VK_ACCESS_HOST_READ_BIT,
2350
2351                 vk::VK_QUEUE_FAMILY_IGNORED,
2352                 vk::VK_QUEUE_FAMILY_IGNORED,
2353                 *m_dstBuffer,
2354                 0,
2355                 vk::VK_WHOLE_SIZE
2356         };
2357
2358         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);
2359
2360         VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
2361         queueRun(vkd, queue, *commandBuffer);
2362
2363         {
2364                 void* const     ptr             = mapMemory(vkd, device, *m_memory, m_bufferSize);
2365                 bool            isOk    = true;
2366
2367                 vk::invalidateMappedMemoryRange(vkd, device, *m_memory, 0, m_bufferSize);
2368
2369                 {
2370                         const deUint8* const data = (const deUint8*)ptr;
2371
2372                         for (size_t pos = 0; pos < (size_t)m_bufferSize; pos++)
2373                         {
2374                                 if (reference.isDefined(pos))
2375                                 {
2376                                         if (data[pos] != reference.get(pos))
2377                                         {
2378                                                 resultCollector.fail(
2379                                                                 de::toString(commandIndex) + ":" + getName()
2380                                                                 + " Result differs from reference, Expected: "
2381                                                                 + de::toString(tcu::toHex<8>(reference.get(pos)))
2382                                                                 + ", Got: "
2383                                                                 + de::toString(tcu::toHex<8>(data[pos]))
2384                                                                 + ", At offset: "
2385                                                                 + de::toString(pos));
2386                                                 break;
2387                                         }
2388                                 }
2389                         }
2390                 }
2391
2392                 vkd.unmapMemory(device, *m_memory);
2393
2394                 if (!isOk)
2395                         context.getLog() << TestLog::Message << commandIndex << ": Buffer copy to buffer verification failed" << TestLog::EndMessage;
2396         }
2397 }
2398
2399 class BufferCopyFromBuffer : public CmdCommand
2400 {
2401 public:
2402                                                                         BufferCopyFromBuffer    (deUint32 seed) : m_seed(seed) {}
2403                                                                         ~BufferCopyFromBuffer   (void) {}
2404         const char*                                             getName                                 (void) const { return "BufferCopyFromBuffer"; }
2405
2406         void                                                    logPrepare                              (TestLog& log, size_t commandIndex) const;
2407         void                                                    prepare                                 (PrepareContext& context);
2408         void                                                    logSubmit                               (TestLog& log, size_t commandIndex) const;
2409         void                                                    submit                                  (SubmitContext& context);
2410         void                                                    verify                                  (VerifyContext& context, size_t commandIndex);
2411
2412 private:
2413         const deUint32                                  m_seed;
2414         vk::VkDeviceSize                                m_bufferSize;
2415         vk::Move<vk::VkBuffer>                  m_srcBuffer;
2416         vk::Move<vk::VkDeviceMemory>    m_memory;
2417 };
2418
2419 void BufferCopyFromBuffer::logPrepare (TestLog& log, size_t commandIndex) const
2420 {
2421         log << TestLog::Message << commandIndex << ":" << getName() << " Allocate source buffer for buffer to buffer copy. Seed: " << m_seed << TestLog::EndMessage;
2422 }
2423
2424 void BufferCopyFromBuffer::prepare (PrepareContext& context)
2425 {
2426         const vk::InstanceInterface&    vki                             = context.getContext().getInstanceInterface();
2427         const vk::DeviceInterface&              vkd                             = context.getContext().getDeviceInterface();
2428         const vk::VkPhysicalDevice              physicalDevice  = context.getContext().getPhysicalDevice();
2429         const vk::VkDevice                              device                  = context.getContext().getDevice();
2430         const vector<deUint32>&                 queueFamilies   = context.getContext().getQueueFamilies();
2431
2432         m_bufferSize    = context.getBufferSize();
2433         m_srcBuffer             = createBuffer(vkd, device, m_bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies);
2434         m_memory                = bindBufferMemory(vki, vkd, physicalDevice, device, *m_srcBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
2435
2436         {
2437                 void* const     ptr     = mapMemory(vkd, device, *m_memory, m_bufferSize);
2438                 de::Random      rng     (m_seed);
2439
2440                 {
2441                         deUint8* const  data = (deUint8*)ptr;
2442
2443                         for (size_t ndx = 0; ndx < (size_t)m_bufferSize; ndx++)
2444                                 data[ndx] = rng.getUint8();
2445                 }
2446
2447                 vk::flushMappedMemoryRange(vkd, device, *m_memory, 0, m_bufferSize);
2448                 vkd.unmapMemory(device, *m_memory);
2449         }
2450 }
2451
2452 void BufferCopyFromBuffer::logSubmit (TestLog& log, size_t commandIndex) const
2453 {
2454         log << TestLog::Message << commandIndex << ":" << getName() << " Copy buffer data from another buffer" << TestLog::EndMessage;
2455 }
2456
2457 void BufferCopyFromBuffer::submit (SubmitContext& context)
2458 {
2459         const vk::DeviceInterface&      vkd                             = context.getContext().getDeviceInterface();
2460         const vk::VkCommandBuffer       commandBuffer   = context.getCommandBuffer();
2461         const vk::VkBufferCopy          range                   =
2462         {
2463                 0, 0, // Offsets
2464                 m_bufferSize
2465         };
2466
2467         vkd.cmdCopyBuffer(commandBuffer, *m_srcBuffer, context.getBuffer(), 1, &range);
2468 }
2469
2470 void BufferCopyFromBuffer::verify (VerifyContext& context, size_t)
2471 {
2472         ReferenceMemory&        reference       (context.getReference());
2473         de::Random                      rng                     (m_seed);
2474
2475         for (size_t ndx = 0; ndx < (size_t)m_bufferSize; ndx++)
2476                 reference.set(ndx, rng.getUint8());
2477 }
2478
2479 class BufferCopyToImage : public CmdCommand
2480 {
2481 public:
2482                                                                         BufferCopyToImage       (void) {}
2483                                                                         ~BufferCopyToImage      (void) {}
2484         const char*                                             getName                         (void) const { return "BufferCopyToImage"; }
2485
2486         void                                                    logPrepare                      (TestLog& log, size_t commandIndex) const;
2487         void                                                    prepare                         (PrepareContext& context);
2488         void                                                    logSubmit                       (TestLog& log, size_t commandIndex) const;
2489         void                                                    submit                          (SubmitContext& context);
2490         void                                                    verify                          (VerifyContext& context, size_t commandIndex);
2491
2492 private:
2493         deInt32                                                 m_imageWidth;
2494         deInt32                                                 m_imageHeight;
2495         vk::Move<vk::VkImage>                   m_dstImage;
2496         vk::Move<vk::VkDeviceMemory>    m_memory;
2497 };
2498
2499 void BufferCopyToImage::logPrepare (TestLog& log, size_t commandIndex) const
2500 {
2501         log << TestLog::Message << commandIndex << ":" << getName() << " Allocate destination image for buffer to image copy." << TestLog::EndMessage;
2502 }
2503
2504 void BufferCopyToImage::prepare (PrepareContext& context)
2505 {
2506         const vk::InstanceInterface&    vki                             = context.getContext().getInstanceInterface();
2507         const vk::DeviceInterface&              vkd                             = context.getContext().getDeviceInterface();
2508         const vk::VkPhysicalDevice              physicalDevice  = context.getContext().getPhysicalDevice();
2509         const vk::VkDevice                              device                  = context.getContext().getDevice();
2510         const vk::VkQueue                               queue                   = context.getContext().getQueue();
2511         const vk::VkCommandPool                 commandPool             = context.getContext().getCommandPool();
2512         const vector<deUint32>&                 queueFamilies   = context.getContext().getQueueFamilies();
2513         const IVec2                                             imageSize               = findImageSizeWxHx4(context.getBufferSize());
2514
2515         m_imageWidth    = imageSize[0];
2516         m_imageHeight   = imageSize[1];
2517
2518         {
2519                 const vk::VkImageCreateInfo     createInfo =
2520                 {
2521                         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
2522                         DE_NULL,
2523
2524                         0,
2525                         vk::VK_IMAGE_TYPE_2D,
2526                         vk::VK_FORMAT_R8G8B8A8_UNORM,
2527                         {
2528                                 (deUint32)m_imageWidth,
2529                                 (deUint32)m_imageHeight,
2530                                 1u,
2531                         },
2532                         1, 1, // mipLevels, arrayLayers
2533                         vk::VK_SAMPLE_COUNT_1_BIT,
2534
2535                         vk::VK_IMAGE_TILING_OPTIMAL,
2536                         vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
2537                         vk::VK_SHARING_MODE_EXCLUSIVE,
2538
2539                         (deUint32)queueFamilies.size(),
2540                         &queueFamilies[0],
2541                         vk::VK_IMAGE_LAYOUT_UNDEFINED
2542                 };
2543
2544                 m_dstImage = vk::createImage(vkd, device, &createInfo);
2545         }
2546
2547         m_memory = bindImageMemory(vki, vkd, physicalDevice, device, *m_dstImage, 0);
2548
2549         {
2550                 const vk::Unique<vk::VkCommandBuffer>   commandBuffer   (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2551                 const vk::VkImageMemoryBarrier                  barrier                 =
2552                 {
2553                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2554                         DE_NULL,
2555
2556                         0,
2557                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2558
2559                         vk::VK_IMAGE_LAYOUT_UNDEFINED,
2560                         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2561
2562                         vk::VK_QUEUE_FAMILY_IGNORED,
2563                         vk::VK_QUEUE_FAMILY_IGNORED,
2564
2565                         *m_dstImage,
2566                         {
2567                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
2568                                 0,      // Mip level
2569                                 1,      // Mip level count
2570                                 0,      // Layer
2571                                 1       // Layer count
2572                         }
2573                 };
2574
2575                 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);
2576
2577                 VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
2578                 queueRun(vkd, queue, *commandBuffer);
2579         }
2580 }
2581
2582 void BufferCopyToImage::logSubmit (TestLog& log, size_t commandIndex) const
2583 {
2584         log << TestLog::Message << commandIndex << ":" << getName() << " Copy buffer to image" << TestLog::EndMessage;
2585 }
2586
2587 void BufferCopyToImage::submit (SubmitContext& context)
2588 {
2589         const vk::DeviceInterface&      vkd                             = context.getContext().getDeviceInterface();
2590         const vk::VkCommandBuffer       commandBuffer   = context.getCommandBuffer();
2591         const vk::VkBufferImageCopy     region                  =
2592         {
2593                 0,
2594                 0, 0,
2595                 {
2596                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
2597                         0,      // mipLevel
2598                         0,      // arrayLayer
2599                         1       // layerCount
2600                 },
2601                 { 0, 0, 0 },
2602                 {
2603                         (deUint32)m_imageWidth,
2604                         (deUint32)m_imageHeight,
2605                         1u
2606                 }
2607         };
2608
2609         vkd.cmdCopyBufferToImage(commandBuffer, context.getBuffer(), *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
2610 }
2611
2612 void BufferCopyToImage::verify (VerifyContext& context, size_t commandIndex)
2613 {
2614         tcu::ResultCollector&                                   resultCollector (context.getResultCollector());
2615         ReferenceMemory&                                                reference               (context.getReference());
2616         const vk::InstanceInterface&                    vki                             = context.getContext().getInstanceInterface();
2617         const vk::DeviceInterface&                              vkd                             = context.getContext().getDeviceInterface();
2618         const vk::VkPhysicalDevice                              physicalDevice  = context.getContext().getPhysicalDevice();
2619         const vk::VkDevice                                              device                  = context.getContext().getDevice();
2620         const vk::VkQueue                                               queue                   = context.getContext().getQueue();
2621         const vk::VkCommandPool                                 commandPool             = context.getContext().getCommandPool();
2622         const vk::Unique<vk::VkCommandBuffer>   commandBuffer   (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2623         const vector<deUint32>&                                 queueFamilies   = context.getContext().getQueueFamilies();
2624         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));
2625         const vk::Unique<vk::VkDeviceMemory>    memory                  (bindBufferMemory(vki, vkd, physicalDevice, device, *dstBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
2626         {
2627                 const vk::VkImageMemoryBarrier          imageBarrier    =
2628                 {
2629                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2630                         DE_NULL,
2631
2632                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2633                         vk::VK_ACCESS_TRANSFER_READ_BIT,
2634
2635                         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2636                         vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2637
2638                         vk::VK_QUEUE_FAMILY_IGNORED,
2639                         vk::VK_QUEUE_FAMILY_IGNORED,
2640
2641                         *m_dstImage,
2642                         {
2643                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
2644                                 0,      // Mip level
2645                                 1,      // Mip level count
2646                                 0,      // Layer
2647                                 1       // Layer count
2648                         }
2649                 };
2650                 const vk::VkBufferMemoryBarrier bufferBarrier =
2651                 {
2652                         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2653                         DE_NULL,
2654
2655                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2656                         vk::VK_ACCESS_HOST_READ_BIT,
2657
2658                         vk::VK_QUEUE_FAMILY_IGNORED,
2659                         vk::VK_QUEUE_FAMILY_IGNORED,
2660                         *dstBuffer,
2661                         0,
2662                         vk::VK_WHOLE_SIZE
2663                 };
2664
2665                 const vk::VkBufferImageCopy     region =
2666                 {
2667                         0,
2668                         0, 0,
2669                         {
2670                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
2671                                 0,      // mipLevel
2672                                 0,      // arrayLayer
2673                                 1       // layerCount
2674                         },
2675                         { 0, 0, 0 },
2676                         {
2677                                 (deUint32)m_imageWidth,
2678                                 (deUint32)m_imageHeight,
2679                                 1u
2680                         }
2681                 };
2682
2683                 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);
2684                 vkd.cmdCopyImageToBuffer(*commandBuffer, *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dstBuffer, 1, &region);
2685                 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);
2686         }
2687
2688         VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
2689         queueRun(vkd, queue, *commandBuffer);
2690
2691         {
2692                 void* const     ptr             = mapMemory(vkd, device, *memory, 4 * m_imageWidth * m_imageHeight);
2693
2694                 vk::invalidateMappedMemoryRange(vkd, device, *memory, 0,  4 * m_imageWidth * m_imageHeight);
2695
2696                 {
2697                         const deUint8* const    data = (const deUint8*)ptr;
2698
2699                         for (size_t pos = 0; pos < (size_t)( 4 * m_imageWidth * m_imageHeight); pos++)
2700                         {
2701                                 if (reference.isDefined(pos))
2702                                 {
2703                                         if (data[pos] != reference.get(pos))
2704                                         {
2705                                                 resultCollector.fail(
2706                                                                 de::toString(commandIndex) + ":" + getName()
2707                                                                 + " Result differs from reference, Expected: "
2708                                                                 + de::toString(tcu::toHex<8>(reference.get(pos)))
2709                                                                 + ", Got: "
2710                                                                 + de::toString(tcu::toHex<8>(data[pos]))
2711                                                                 + ", At offset: "
2712                                                                 + de::toString(pos));
2713                                                 break;
2714                                         }
2715                                 }
2716                         }
2717                 }
2718
2719                 vkd.unmapMemory(device, *memory);
2720         }
2721 }
2722
2723 class BufferCopyFromImage : public CmdCommand
2724 {
2725 public:
2726                                                                         BufferCopyFromImage             (deUint32 seed) : m_seed(seed) {}
2727                                                                         ~BufferCopyFromImage    (void) {}
2728         const char*                                             getName                                 (void) const { return "BufferCopyFromImage"; }
2729
2730         void                                                    logPrepare                              (TestLog& log, size_t commandIndex) const;
2731         void                                                    prepare                                 (PrepareContext& context);
2732         void                                                    logSubmit                               (TestLog& log, size_t commandIndex) const;
2733         void                                                    submit                                  (SubmitContext& context);
2734         void                                                    verify                                  (VerifyContext& context, size_t commandIndex);
2735
2736 private:
2737         const deUint32                                  m_seed;
2738         deInt32                                                 m_imageWidth;
2739         deInt32                                                 m_imageHeight;
2740         vk::Move<vk::VkImage>                   m_srcImage;
2741         vk::Move<vk::VkDeviceMemory>    m_memory;
2742 };
2743
2744 void BufferCopyFromImage::logPrepare (TestLog& log, size_t commandIndex) const
2745 {
2746         log << TestLog::Message << commandIndex << ":" << getName() << " Allocate source image for image to buffer copy." << TestLog::EndMessage;
2747 }
2748
2749 void BufferCopyFromImage::prepare (PrepareContext& context)
2750 {
2751         const vk::InstanceInterface&    vki                             = context.getContext().getInstanceInterface();
2752         const vk::DeviceInterface&              vkd                             = context.getContext().getDeviceInterface();
2753         const vk::VkPhysicalDevice              physicalDevice  = context.getContext().getPhysicalDevice();
2754         const vk::VkDevice                              device                  = context.getContext().getDevice();
2755         const vk::VkQueue                               queue                   = context.getContext().getQueue();
2756         const vk::VkCommandPool                 commandPool             = context.getContext().getCommandPool();
2757         const vector<deUint32>&                 queueFamilies   = context.getContext().getQueueFamilies();
2758         const IVec2                                             imageSize               = findImageSizeWxHx4(context.getBufferSize());
2759
2760         m_imageWidth    = imageSize[0];
2761         m_imageHeight   = imageSize[1];
2762
2763         {
2764                 const vk::VkImageCreateInfo     createInfo =
2765                 {
2766                         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
2767                         DE_NULL,
2768
2769                         0,
2770                         vk::VK_IMAGE_TYPE_2D,
2771                         vk::VK_FORMAT_R8G8B8A8_UNORM,
2772                         {
2773                                 (deUint32)m_imageWidth,
2774                                 (deUint32)m_imageHeight,
2775                                 1u,
2776                         },
2777                         1, 1, // mipLevels, arrayLayers
2778                         vk::VK_SAMPLE_COUNT_1_BIT,
2779
2780                         vk::VK_IMAGE_TILING_OPTIMAL,
2781                         vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
2782                         vk::VK_SHARING_MODE_EXCLUSIVE,
2783
2784                         (deUint32)queueFamilies.size(),
2785                         &queueFamilies[0],
2786                         vk::VK_IMAGE_LAYOUT_UNDEFINED
2787                 };
2788
2789                 m_srcImage = vk::createImage(vkd, device, &createInfo);
2790         }
2791
2792         m_memory = bindImageMemory(vki, vkd, physicalDevice, device, *m_srcImage, 0);
2793
2794         {
2795                 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));
2796                 const vk::Unique<vk::VkDeviceMemory>    memory                  (bindBufferMemory(vki, vkd, physicalDevice, device, *srcBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
2797                 const vk::Unique<vk::VkCommandBuffer>   commandBuffer   (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2798                 const vk::VkImageMemoryBarrier                  preImageBarrier =
2799                 {
2800                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2801                         DE_NULL,
2802
2803                         0,
2804                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2805
2806                         vk::VK_IMAGE_LAYOUT_UNDEFINED,
2807                         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2808
2809                         vk::VK_QUEUE_FAMILY_IGNORED,
2810                         vk::VK_QUEUE_FAMILY_IGNORED,
2811
2812                         *m_srcImage,
2813                         {
2814                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
2815                                 0,      // Mip level
2816                                 1,      // Mip level count
2817                                 0,      // Layer
2818                                 1       // Layer count
2819                         }
2820                 };
2821                 const vk::VkImageMemoryBarrier                  postImageBarrier =
2822                 {
2823                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2824                         DE_NULL,
2825
2826                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,
2827                         0,
2828
2829                         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2830                         vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2831
2832                         vk::VK_QUEUE_FAMILY_IGNORED,
2833                         vk::VK_QUEUE_FAMILY_IGNORED,
2834
2835                         *m_srcImage,
2836                         {
2837                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
2838                                 0,      // Mip level
2839                                 1,      // Mip level count
2840                                 0,      // Layer
2841                                 1       // Layer count
2842                         }
2843                 };
2844                 const vk::VkBufferImageCopy                             region                          =
2845                 {
2846                         0,
2847                         0, 0,
2848                         {
2849                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
2850                                 0,      // mipLevel
2851                                 0,      // arrayLayer
2852                                 1       // layerCount
2853                         },
2854                         { 0, 0, 0 },
2855                         {
2856                                 (deUint32)m_imageWidth,
2857                                 (deUint32)m_imageHeight,
2858                                 1u
2859                         }
2860                 };
2861
2862                 {
2863                         void* const     ptr     = mapMemory(vkd, device, *memory, 4 * m_imageWidth * m_imageHeight);
2864                         de::Random      rng     (m_seed);
2865
2866                         {
2867                                 deUint8* const  data = (deUint8*)ptr;
2868
2869                                 for (size_t ndx = 0; ndx < (size_t)(4 * m_imageWidth * m_imageHeight); ndx++)
2870                                         data[ndx] = rng.getUint8();
2871                         }
2872
2873                         vk::flushMappedMemoryRange(vkd, device, *memory, 0, 4 * m_imageWidth * m_imageHeight);
2874                         vkd.unmapMemory(device, *memory);
2875                 }
2876
2877                 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);
2878                 vkd.cmdCopyBufferToImage(*commandBuffer, *srcBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
2879                 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);
2880
2881                 VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
2882                 queueRun(vkd, queue, *commandBuffer);
2883         }
2884 }
2885
2886 void BufferCopyFromImage::logSubmit (TestLog& log, size_t commandIndex) const
2887 {
2888         log << TestLog::Message << commandIndex << ":" << getName() << " Copy buffer data from image" << TestLog::EndMessage;
2889 }
2890
2891 void BufferCopyFromImage::submit (SubmitContext& context)
2892 {
2893         const vk::DeviceInterface&      vkd                             = context.getContext().getDeviceInterface();
2894         const vk::VkCommandBuffer       commandBuffer   = context.getCommandBuffer();
2895         const vk::VkBufferImageCopy     region                  =
2896         {
2897                 0,
2898                 0, 0,
2899                 {
2900                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
2901                         0,      // mipLevel
2902                         0,      // arrayLayer
2903                         1       // layerCount
2904                 },
2905                 { 0, 0, 0 },
2906                 {
2907                         (deUint32)m_imageWidth,
2908                         (deUint32)m_imageHeight,
2909                         1u
2910                 }
2911         };
2912
2913         vkd.cmdCopyImageToBuffer(commandBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, context.getBuffer(), 1, &region);
2914 }
2915
2916 void BufferCopyFromImage::verify (VerifyContext& context, size_t)
2917 {
2918         ReferenceMemory&        reference               (context.getReference());
2919         de::Random                      rng     (m_seed);
2920
2921         for (size_t ndx = 0; ndx < (size_t)(4 * m_imageWidth * m_imageHeight); ndx++)
2922                 reference.set(ndx, rng.getUint8());
2923 }
2924
2925 class ImageCopyToBuffer : public CmdCommand
2926 {
2927 public:
2928                                                                         ImageCopyToBuffer       (void) {}
2929                                                                         ~ImageCopyToBuffer      (void) {}
2930         const char*                                             getName                         (void) const { return "BufferCopyToImage"; }
2931
2932         void                                                    logPrepare                      (TestLog& log, size_t commandIndex) const;
2933         void                                                    prepare                         (PrepareContext& context);
2934         void                                                    logSubmit                       (TestLog& log, size_t commandIndex) const;
2935         void                                                    submit                          (SubmitContext& context);
2936         void                                                    verify                          (VerifyContext& context, size_t commandIndex);
2937
2938 private:
2939         vk::VkDeviceSize                                m_bufferSize;
2940         vk::Move<vk::VkBuffer>                  m_dstBuffer;
2941         vk::Move<vk::VkDeviceMemory>    m_memory;
2942         vk::VkDeviceSize                                m_imageMemorySize;
2943         deInt32                                                 m_imageWidth;
2944         deInt32                                                 m_imageHeight;
2945 };
2946
2947 void ImageCopyToBuffer::logPrepare (TestLog& log, size_t commandIndex) const
2948 {
2949         log << TestLog::Message << commandIndex << ":" << getName() << " Allocate destination buffer for image to buffer copy." << TestLog::EndMessage;
2950 }
2951
2952 void ImageCopyToBuffer::prepare (PrepareContext& context)
2953 {
2954         const vk::InstanceInterface&    vki                             = context.getContext().getInstanceInterface();
2955         const vk::DeviceInterface&              vkd                             = context.getContext().getDeviceInterface();
2956         const vk::VkPhysicalDevice              physicalDevice  = context.getContext().getPhysicalDevice();
2957         const vk::VkDevice                              device                  = context.getContext().getDevice();
2958         const vector<deUint32>&                 queueFamilies   = context.getContext().getQueueFamilies();
2959
2960         m_imageWidth            = context.getImageWidth();
2961         m_imageHeight           = context.getImageHeight();
2962         m_bufferSize            = 4 * m_imageWidth * m_imageHeight;
2963         m_imageMemorySize       = context.getImageMemorySize();
2964         m_dstBuffer                     = createBuffer(vkd, device, m_bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies);
2965         m_memory                        = bindBufferMemory(vki, vkd, physicalDevice, device, *m_dstBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
2966 }
2967
2968 void ImageCopyToBuffer::logSubmit (TestLog& log, size_t commandIndex) const
2969 {
2970         log << TestLog::Message << commandIndex << ":" << getName() << " Copy image to buffer" << TestLog::EndMessage;
2971 }
2972
2973 void ImageCopyToBuffer::submit (SubmitContext& context)
2974 {
2975         const vk::DeviceInterface&      vkd                             = context.getContext().getDeviceInterface();
2976         const vk::VkCommandBuffer       commandBuffer   = context.getCommandBuffer();
2977         const vk::VkBufferImageCopy     region                  =
2978         {
2979                 0,
2980                 0, 0,
2981                 {
2982                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
2983                         0,      // mipLevel
2984                         0,      // arrayLayer
2985                         1       // layerCount
2986                 },
2987                 { 0, 0, 0 },
2988                 {
2989                         (deUint32)m_imageWidth,
2990                         (deUint32)m_imageHeight,
2991                         1u
2992                 }
2993         };
2994
2995         vkd.cmdCopyImageToBuffer(commandBuffer, context.getImage(), context.getImageLayout(), *m_dstBuffer, 1, &region);
2996 }
2997
2998 void ImageCopyToBuffer::verify (VerifyContext& context, size_t commandIndex)
2999 {
3000         tcu::ResultCollector&                                   resultCollector (context.getResultCollector());
3001         ReferenceMemory&                                                reference               (context.getReference());
3002         const vk::DeviceInterface&                              vkd                             = context.getContext().getDeviceInterface();
3003         const vk::VkDevice                                              device                  = context.getContext().getDevice();
3004         const vk::VkQueue                                               queue                   = context.getContext().getQueue();
3005         const vk::VkCommandPool                                 commandPool             = context.getContext().getCommandPool();
3006         const vk::Unique<vk::VkCommandBuffer>   commandBuffer   (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3007         const vk::VkBufferMemoryBarrier                 barrier                 =
3008         {
3009                 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
3010                 DE_NULL,
3011
3012                 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3013                 vk::VK_ACCESS_HOST_READ_BIT,
3014
3015                 vk::VK_QUEUE_FAMILY_IGNORED,
3016                 vk::VK_QUEUE_FAMILY_IGNORED,
3017                 *m_dstBuffer,
3018                 0,
3019                 vk::VK_WHOLE_SIZE
3020         };
3021
3022         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);
3023
3024         VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
3025         queueRun(vkd, queue, *commandBuffer);
3026
3027         reference.setUndefined(0, (size_t)m_imageMemorySize);
3028         {
3029                 void* const                                             ptr                             = mapMemory(vkd, device, *m_memory, m_bufferSize);
3030                 const ConstPixelBufferAccess    referenceImage  (context.getReferenceImage().getAccess());
3031                 const ConstPixelBufferAccess    resultImage             (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_imageWidth, m_imageHeight, 1, ptr);
3032
3033                 vk::invalidateMappedMemoryRange(vkd, device, *m_memory, 0, m_bufferSize);
3034
3035                 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))
3036                         resultCollector.fail(de::toString(commandIndex) + ":" + getName() + " Image comparison failed");
3037
3038                 vkd.unmapMemory(device, *m_memory);
3039         }
3040 }
3041
3042 class ImageCopyFromBuffer : public CmdCommand
3043 {
3044 public:
3045                                                                         ImageCopyFromBuffer             (deUint32 seed) : m_seed(seed) {}
3046                                                                         ~ImageCopyFromBuffer    (void) {}
3047         const char*                                             getName                                 (void) const { return "ImageCopyFromBuffer"; }
3048
3049         void                                                    logPrepare                              (TestLog& log, size_t commandIndex) const;
3050         void                                                    prepare                                 (PrepareContext& context);
3051         void                                                    logSubmit                               (TestLog& log, size_t commandIndex) const;
3052         void                                                    submit                                  (SubmitContext& context);
3053         void                                                    verify                                  (VerifyContext& context, size_t commandIndex);
3054
3055 private:
3056         const deUint32                                  m_seed;
3057         deInt32                                                 m_imageWidth;
3058         deInt32                                                 m_imageHeight;
3059         vk::VkDeviceSize                                m_imageMemorySize;
3060         vk::VkDeviceSize                                m_bufferSize;
3061         vk::Move<vk::VkBuffer>                  m_srcBuffer;
3062         vk::Move<vk::VkDeviceMemory>    m_memory;
3063 };
3064
3065 void ImageCopyFromBuffer::logPrepare (TestLog& log, size_t commandIndex) const
3066 {
3067         log << TestLog::Message << commandIndex << ":" << getName() << " Allocate source buffer for buffer to image copy. Seed: " << m_seed << TestLog::EndMessage;
3068 }
3069
3070 void ImageCopyFromBuffer::prepare (PrepareContext& context)
3071 {
3072         const vk::InstanceInterface&    vki                             = context.getContext().getInstanceInterface();
3073         const vk::DeviceInterface&              vkd                             = context.getContext().getDeviceInterface();
3074         const vk::VkPhysicalDevice              physicalDevice  = context.getContext().getPhysicalDevice();
3075         const vk::VkDevice                              device                  = context.getContext().getDevice();
3076         const vector<deUint32>&                 queueFamilies   = context.getContext().getQueueFamilies();
3077
3078         m_imageWidth            = context.getImageHeight();
3079         m_imageHeight           = context.getImageWidth();
3080         m_imageMemorySize       = context.getImageMemorySize();
3081         m_bufferSize            = m_imageWidth * m_imageHeight * 4;
3082         m_srcBuffer                     = createBuffer(vkd, device, m_bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vk::VK_SHARING_MODE_EXCLUSIVE, queueFamilies);
3083         m_memory                        = bindBufferMemory(vki, vkd, physicalDevice, device, *m_srcBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
3084
3085         {
3086                 void* const     ptr     = mapMemory(vkd, device, *m_memory, m_bufferSize);
3087                 de::Random      rng     (m_seed);
3088
3089                 {
3090                         deUint8* const  data = (deUint8*)ptr;
3091
3092                         for (size_t ndx = 0; ndx < (size_t)m_bufferSize; ndx++)
3093                                 data[ndx] = rng.getUint8();
3094                 }
3095
3096                 vk::flushMappedMemoryRange(vkd, device, *m_memory, 0, m_bufferSize);
3097                 vkd.unmapMemory(device, *m_memory);
3098         }
3099 }
3100
3101 void ImageCopyFromBuffer::logSubmit (TestLog& log, size_t commandIndex) const
3102 {
3103         log << TestLog::Message << commandIndex << ":" << getName() << " Copy image data from buffer" << TestLog::EndMessage;
3104 }
3105
3106 void ImageCopyFromBuffer::submit (SubmitContext& context)
3107 {
3108         const vk::DeviceInterface&      vkd                             = context.getContext().getDeviceInterface();
3109         const vk::VkCommandBuffer       commandBuffer   = context.getCommandBuffer();
3110         const vk::VkBufferImageCopy     region                  =
3111         {
3112                 0,
3113                 0, 0,
3114                 {
3115                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
3116                         0,      // mipLevel
3117                         0,      // arrayLayer
3118                         1       // layerCount
3119                 },
3120                 { 0, 0, 0 },
3121                 {
3122                         (deUint32)m_imageWidth,
3123                         (deUint32)m_imageHeight,
3124                         1u
3125                 }
3126         };
3127
3128         vkd.cmdCopyBufferToImage(commandBuffer, *m_srcBuffer, context.getImage(), context.getImageLayout(), 1, &region);
3129 }
3130
3131 void ImageCopyFromBuffer::verify (VerifyContext& context, size_t)
3132 {
3133         ReferenceMemory&        reference       (context.getReference());
3134         de::Random                      rng                     (m_seed);
3135
3136         reference.setUndefined(0, (size_t)m_imageMemorySize);
3137
3138         {
3139                 const PixelBufferAccess&        refAccess       (context.getReferenceImage().getAccess());
3140
3141                 for (deInt32 y = 0; y < m_imageHeight; y++)
3142                 for (deInt32 x = 0; x < m_imageWidth; x++)
3143                 {
3144                         const deUint8 r8 = rng.getUint8();
3145                         const deUint8 g8 = rng.getUint8();
3146                         const deUint8 b8 = rng.getUint8();
3147                         const deUint8 a8 = rng.getUint8();
3148
3149                         refAccess.setPixel(UVec4(r8, g8, b8, a8), x, y);
3150                 }
3151         }
3152 }
3153
3154 class ImageCopyFromImage : public CmdCommand
3155 {
3156 public:
3157                                                                         ImageCopyFromImage      (deUint32 seed) : m_seed(seed) {}
3158                                                                         ~ImageCopyFromImage     (void) {}
3159         const char*                                             getName                         (void) const { return "ImageCopyFromImage"; }
3160
3161         void                                                    logPrepare                      (TestLog& log, size_t commandIndex) const;
3162         void                                                    prepare                         (PrepareContext& context);
3163         void                                                    logSubmit                       (TestLog& log, size_t commandIndex) const;
3164         void                                                    submit                          (SubmitContext& context);
3165         void                                                    verify                          (VerifyContext& context, size_t commandIndex);
3166
3167 private:
3168         const deUint32                                  m_seed;
3169         deInt32                                                 m_imageWidth;
3170         deInt32                                                 m_imageHeight;
3171         vk::VkDeviceSize                                m_imageMemorySize;
3172         vk::Move<vk::VkImage>                   m_srcImage;
3173         vk::Move<vk::VkDeviceMemory>    m_memory;
3174 };
3175
3176 void ImageCopyFromImage::logPrepare (TestLog& log, size_t commandIndex) const
3177 {
3178         log << TestLog::Message << commandIndex << ":" << getName() << " Allocate source image for image to image copy." << TestLog::EndMessage;
3179 }
3180
3181 void ImageCopyFromImage::prepare (PrepareContext& context)
3182 {
3183         const vk::InstanceInterface&    vki                             = context.getContext().getInstanceInterface();
3184         const vk::DeviceInterface&              vkd                             = context.getContext().getDeviceInterface();
3185         const vk::VkPhysicalDevice              physicalDevice  = context.getContext().getPhysicalDevice();
3186         const vk::VkDevice                              device                  = context.getContext().getDevice();
3187         const vk::VkQueue                               queue                   = context.getContext().getQueue();
3188         const vk::VkCommandPool                 commandPool             = context.getContext().getCommandPool();
3189         const vector<deUint32>&                 queueFamilies   = context.getContext().getQueueFamilies();
3190
3191         m_imageWidth            = context.getImageWidth();
3192         m_imageHeight           = context.getImageHeight();
3193         m_imageMemorySize       = context.getImageMemorySize();
3194
3195         {
3196                 const vk::VkImageCreateInfo     createInfo =
3197                 {
3198                         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3199                         DE_NULL,
3200
3201                         0,
3202                         vk::VK_IMAGE_TYPE_2D,
3203                         vk::VK_FORMAT_R8G8B8A8_UNORM,
3204                         {
3205                                 (deUint32)m_imageWidth,
3206                                 (deUint32)m_imageHeight,
3207                                 1u,
3208                         },
3209                         1, 1, // mipLevels, arrayLayers
3210                         vk::VK_SAMPLE_COUNT_1_BIT,
3211
3212                         vk::VK_IMAGE_TILING_OPTIMAL,
3213                         vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3214                         vk::VK_SHARING_MODE_EXCLUSIVE,
3215
3216                         (deUint32)queueFamilies.size(),
3217                         &queueFamilies[0],
3218                         vk::VK_IMAGE_LAYOUT_UNDEFINED
3219                 };
3220
3221                 m_srcImage = vk::createImage(vkd, device, &createInfo);
3222         }
3223
3224         m_memory = bindImageMemory(vki, vkd, physicalDevice, device, *m_srcImage, 0);
3225
3226         {
3227                 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));
3228                 const vk::Unique<vk::VkDeviceMemory>    memory                  (bindBufferMemory(vki, vkd, physicalDevice, device, *srcBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
3229                 const vk::Unique<vk::VkCommandBuffer>   commandBuffer   (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3230                 const vk::VkImageMemoryBarrier                  preImageBarrier =
3231                 {
3232                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3233                         DE_NULL,
3234
3235                         0,
3236                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3237
3238                         vk::VK_IMAGE_LAYOUT_UNDEFINED,
3239                         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3240
3241                         vk::VK_QUEUE_FAMILY_IGNORED,
3242                         vk::VK_QUEUE_FAMILY_IGNORED,
3243
3244                         *m_srcImage,
3245                         {
3246                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3247                                 0,      // Mip level
3248                                 1,      // Mip level count
3249                                 0,      // Layer
3250                                 1       // Layer count
3251                         }
3252                 };
3253                 const vk::VkImageMemoryBarrier                  postImageBarrier =
3254                 {
3255                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3256                         DE_NULL,
3257
3258                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3259                         0,
3260
3261                         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3262                         vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3263
3264                         vk::VK_QUEUE_FAMILY_IGNORED,
3265                         vk::VK_QUEUE_FAMILY_IGNORED,
3266
3267                         *m_srcImage,
3268                         {
3269                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3270                                 0,      // Mip level
3271                                 1,      // Mip level count
3272                                 0,      // Layer
3273                                 1       // Layer count
3274                         }
3275                 };
3276                 const vk::VkBufferImageCopy                             region                          =
3277                 {
3278                         0,
3279                         0, 0,
3280                         {
3281                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3282                                 0,      // mipLevel
3283                                 0,      // arrayLayer
3284                                 1       // layerCount
3285                         },
3286                         { 0, 0, 0 },
3287                         {
3288                                 (deUint32)m_imageWidth,
3289                                 (deUint32)m_imageHeight,
3290                                 1u
3291                         }
3292                 };
3293
3294                 {
3295                         void* const     ptr     = mapMemory(vkd, device, *memory, 4 * m_imageWidth * m_imageHeight);
3296                         de::Random      rng     (m_seed);
3297
3298                         {
3299                                 deUint8* const  data = (deUint8*)ptr;
3300
3301                                 for (size_t ndx = 0; ndx < (size_t)(4 * m_imageWidth * m_imageHeight); ndx++)
3302                                         data[ndx] = rng.getUint8();
3303                         }
3304
3305                         vk::flushMappedMemoryRange(vkd, device, *memory, 0, 4 * m_imageWidth * m_imageHeight);
3306                         vkd.unmapMemory(device, *memory);
3307                 }
3308
3309                 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);
3310                 vkd.cmdCopyBufferToImage(*commandBuffer, *srcBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
3311                 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);
3312
3313                 VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
3314                 queueRun(vkd, queue, *commandBuffer);
3315         }
3316 }
3317
3318 void ImageCopyFromImage::logSubmit (TestLog& log, size_t commandIndex) const
3319 {
3320         log << TestLog::Message << commandIndex << ":" << getName() << " Copy image data from another image" << TestLog::EndMessage;
3321 }
3322
3323 void ImageCopyFromImage::submit (SubmitContext& context)
3324 {
3325         const vk::DeviceInterface&      vkd                             = context.getContext().getDeviceInterface();
3326         const vk::VkCommandBuffer       commandBuffer   = context.getCommandBuffer();
3327         const vk::VkImageCopy           region                  =
3328         {
3329                 {
3330                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
3331                         0,      // mipLevel
3332                         0,      // arrayLayer
3333                         1       // layerCount
3334                 },
3335                 { 0, 0, 0 },
3336
3337                 {
3338                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
3339                         0,      // mipLevel
3340                         0,      // arrayLayer
3341                         1       // layerCount
3342                 },
3343                 { 0, 0, 0 },
3344                 {
3345                         (deUint32)m_imageWidth,
3346                         (deUint32)m_imageHeight,
3347                         1u
3348                 }
3349         };
3350
3351         vkd.cmdCopyImage(commandBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, context.getImage(), context.getImageLayout(), 1, &region);
3352 }
3353
3354 void ImageCopyFromImage::verify (VerifyContext& context, size_t)
3355 {
3356         ReferenceMemory&        reference       (context.getReference());
3357         de::Random                      rng                     (m_seed);
3358
3359         reference.setUndefined(0, (size_t)m_imageMemorySize);
3360
3361         {
3362                 const PixelBufferAccess&        refAccess       (context.getReferenceImage().getAccess());
3363
3364                 for (deInt32 y = 0; y < m_imageHeight; y++)
3365                 for (deInt32 x = 0; x < m_imageWidth; x++)
3366                 {
3367                         const deUint8 r8 = rng.getUint8();
3368                         const deUint8 g8 = rng.getUint8();
3369                         const deUint8 b8 = rng.getUint8();
3370                         const deUint8 a8 = rng.getUint8();
3371
3372                         refAccess.setPixel(UVec4(r8, g8, b8, a8), x, y);
3373                 }
3374         }
3375 }
3376
3377 class ImageCopyToImage : public CmdCommand
3378 {
3379 public:
3380                                                                         ImageCopyToImage        (void) {}
3381                                                                         ~ImageCopyToImage       (void) {}
3382         const char*                                             getName                         (void) const { return "ImageCopyToImage"; }
3383
3384         void                                                    logPrepare                      (TestLog& log, size_t commandIndex) const;
3385         void                                                    prepare                         (PrepareContext& context);
3386         void                                                    logSubmit                       (TestLog& log, size_t commandIndex) const;
3387         void                                                    submit                          (SubmitContext& context);
3388         void                                                    verify                          (VerifyContext& context, size_t commandIndex);
3389
3390 private:
3391         deInt32                                                 m_imageWidth;
3392         deInt32                                                 m_imageHeight;
3393         vk::VkDeviceSize                                m_imageMemorySize;
3394         vk::Move<vk::VkImage>                   m_dstImage;
3395         vk::Move<vk::VkDeviceMemory>    m_memory;
3396 };
3397
3398 void ImageCopyToImage::logPrepare (TestLog& log, size_t commandIndex) const
3399 {
3400         log << TestLog::Message << commandIndex << ":" << getName() << " Allocate destination image for image to image copy." << TestLog::EndMessage;
3401 }
3402
3403 void ImageCopyToImage::prepare (PrepareContext& context)
3404 {
3405         const vk::InstanceInterface&    vki                             = context.getContext().getInstanceInterface();
3406         const vk::DeviceInterface&              vkd                             = context.getContext().getDeviceInterface();
3407         const vk::VkPhysicalDevice              physicalDevice  = context.getContext().getPhysicalDevice();
3408         const vk::VkDevice                              device                  = context.getContext().getDevice();
3409         const vk::VkQueue                               queue                   = context.getContext().getQueue();
3410         const vk::VkCommandPool                 commandPool             = context.getContext().getCommandPool();
3411         const vector<deUint32>&                 queueFamilies   = context.getContext().getQueueFamilies();
3412
3413         m_imageWidth            = context.getImageWidth();
3414         m_imageHeight           = context.getImageHeight();
3415         m_imageMemorySize       = context.getImageMemorySize();
3416
3417         {
3418                 const vk::VkImageCreateInfo     createInfo =
3419                 {
3420                         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3421                         DE_NULL,
3422
3423                         0,
3424                         vk::VK_IMAGE_TYPE_2D,
3425                         vk::VK_FORMAT_R8G8B8A8_UNORM,
3426                         {
3427                                 (deUint32)m_imageWidth,
3428                                 (deUint32)m_imageHeight,
3429                                 1u,
3430                         },
3431                         1, 1, // mipLevels, arrayLayers
3432                         vk::VK_SAMPLE_COUNT_1_BIT,
3433
3434                         vk::VK_IMAGE_TILING_OPTIMAL,
3435                         vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3436                         vk::VK_SHARING_MODE_EXCLUSIVE,
3437
3438                         (deUint32)queueFamilies.size(),
3439                         &queueFamilies[0],
3440                         vk::VK_IMAGE_LAYOUT_UNDEFINED
3441                 };
3442
3443                 m_dstImage = vk::createImage(vkd, device, &createInfo);
3444         }
3445
3446         m_memory = bindImageMemory(vki, vkd, physicalDevice, device, *m_dstImage, 0);
3447
3448         {
3449                 const vk::Unique<vk::VkCommandBuffer>   commandBuffer   (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3450                 const vk::VkImageMemoryBarrier                  barrier                 =
3451                 {
3452                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3453                         DE_NULL,
3454
3455                         0,
3456                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3457
3458                         vk::VK_IMAGE_LAYOUT_UNDEFINED,
3459                         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3460
3461                         vk::VK_QUEUE_FAMILY_IGNORED,
3462                         vk::VK_QUEUE_FAMILY_IGNORED,
3463
3464                         *m_dstImage,
3465                         {
3466                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3467                                 0,      // Mip level
3468                                 1,      // Mip level count
3469                                 0,      // Layer
3470                                 1       // Layer count
3471                         }
3472                 };
3473
3474                 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);
3475
3476                 VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
3477                 queueRun(vkd, queue, *commandBuffer);
3478         }
3479 }
3480
3481 void ImageCopyToImage::logSubmit (TestLog& log, size_t commandIndex) const
3482 {
3483         log << TestLog::Message << commandIndex << ":" << getName() << " Copy image to another image" << TestLog::EndMessage;
3484 }
3485
3486 void ImageCopyToImage::submit (SubmitContext& context)
3487 {
3488         const vk::DeviceInterface&      vkd                             = context.getContext().getDeviceInterface();
3489         const vk::VkCommandBuffer       commandBuffer   = context.getCommandBuffer();
3490         const vk::VkImageCopy           region                  =
3491         {
3492                 {
3493                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
3494                         0,      // mipLevel
3495                         0,      // arrayLayer
3496                         1       // layerCount
3497                 },
3498                 { 0, 0, 0 },
3499
3500                 {
3501                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
3502                         0,      // mipLevel
3503                         0,      // arrayLayer
3504                         1       // layerCount
3505                 },
3506                 { 0, 0, 0 },
3507                 {
3508                         (deUint32)m_imageWidth,
3509                         (deUint32)m_imageHeight,
3510                         1u
3511                 }
3512         };
3513
3514         vkd.cmdCopyImage(commandBuffer, context.getImage(), context.getImageLayout(), *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
3515 }
3516
3517 void ImageCopyToImage::verify (VerifyContext& context, size_t commandIndex)
3518 {
3519         tcu::ResultCollector&                                   resultCollector (context.getResultCollector());
3520         const vk::InstanceInterface&                    vki                             = context.getContext().getInstanceInterface();
3521         const vk::DeviceInterface&                              vkd                             = context.getContext().getDeviceInterface();
3522         const vk::VkPhysicalDevice                              physicalDevice  = context.getContext().getPhysicalDevice();
3523         const vk::VkDevice                                              device                  = context.getContext().getDevice();
3524         const vk::VkQueue                                               queue                   = context.getContext().getQueue();
3525         const vk::VkCommandPool                                 commandPool             = context.getContext().getCommandPool();
3526         const vk::Unique<vk::VkCommandBuffer>   commandBuffer   (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3527         const vector<deUint32>&                                 queueFamilies   = context.getContext().getQueueFamilies();
3528         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));
3529         const vk::Unique<vk::VkDeviceMemory>    memory                  (bindBufferMemory(vki, vkd, physicalDevice, device, *dstBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
3530         {
3531                 const vk::VkImageMemoryBarrier          imageBarrier    =
3532                 {
3533                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3534                         DE_NULL,
3535
3536                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3537                         vk::VK_ACCESS_TRANSFER_READ_BIT,
3538
3539                         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3540                         vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3541
3542                         vk::VK_QUEUE_FAMILY_IGNORED,
3543                         vk::VK_QUEUE_FAMILY_IGNORED,
3544
3545                         *m_dstImage,
3546                         {
3547                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3548                                 0,      // Mip level
3549                                 1,      // Mip level count
3550                                 0,      // Layer
3551                                 1       // Layer count
3552                         }
3553                 };
3554                 const vk::VkBufferMemoryBarrier bufferBarrier =
3555                 {
3556                         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
3557                         DE_NULL,
3558
3559                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3560                         vk::VK_ACCESS_HOST_READ_BIT,
3561
3562                         vk::VK_QUEUE_FAMILY_IGNORED,
3563                         vk::VK_QUEUE_FAMILY_IGNORED,
3564                         *dstBuffer,
3565                         0,
3566                         vk::VK_WHOLE_SIZE
3567                 };
3568                 const vk::VkBufferImageCopy     region =
3569                 {
3570                         0,
3571                         0, 0,
3572                         {
3573                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3574                                 0,      // mipLevel
3575                                 0,      // arrayLayer
3576                                 1       // layerCount
3577                         },
3578                         { 0, 0, 0 },
3579                         {
3580                                 (deUint32)m_imageWidth,
3581                                 (deUint32)m_imageHeight,
3582                                 1u
3583                         }
3584                 };
3585
3586                 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);
3587                 vkd.cmdCopyImageToBuffer(*commandBuffer, *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dstBuffer, 1, &region);
3588                 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);
3589         }
3590
3591         VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
3592         queueRun(vkd, queue, *commandBuffer);
3593
3594         {
3595                 void* const     ptr             = mapMemory(vkd, device, *memory, 4 * m_imageWidth * m_imageHeight);
3596
3597                 vk::invalidateMappedMemoryRange(vkd, device, *memory, 0,  4 * m_imageWidth * m_imageHeight);
3598
3599                 {
3600                         const deUint8* const                    data            = (const deUint8*)ptr;
3601                         const ConstPixelBufferAccess    resAccess       (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_imageWidth, m_imageHeight, 1, data);
3602                         const ConstPixelBufferAccess&   refAccess       (context.getReferenceImage().getAccess());
3603
3604                         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))
3605                                 resultCollector.fail(de::toString(commandIndex) + ":" + getName() + " Image comparison failed");
3606                 }
3607
3608                 vkd.unmapMemory(device, *memory);
3609         }
3610 }
3611
3612 enum BlitScale
3613 {
3614         BLIT_SCALE_20,
3615         BLIT_SCALE_10,
3616 };
3617
3618 class ImageBlitFromImage : public CmdCommand
3619 {
3620 public:
3621                                                                         ImageBlitFromImage      (deUint32 seed, BlitScale scale) : m_seed(seed), m_scale(scale) {}
3622                                                                         ~ImageBlitFromImage     (void) {}
3623         const char*                                             getName                         (void) const { return "ImageBlitFromImage"; }
3624
3625         void                                                    logPrepare                      (TestLog& log, size_t commandIndex) const;
3626         void                                                    prepare                         (PrepareContext& context);
3627         void                                                    logSubmit                       (TestLog& log, size_t commandIndex) const;
3628         void                                                    submit                          (SubmitContext& context);
3629         void                                                    verify                          (VerifyContext& context, size_t commandIndex);
3630
3631 private:
3632         const deUint32                                  m_seed;
3633         const BlitScale                                 m_scale;
3634         deInt32                                                 m_imageWidth;
3635         deInt32                                                 m_imageHeight;
3636         vk::VkDeviceSize                                m_imageMemorySize;
3637         deInt32                                                 m_srcImageWidth;
3638         deInt32                                                 m_srcImageHeight;
3639         vk::Move<vk::VkImage>                   m_srcImage;
3640         vk::Move<vk::VkDeviceMemory>    m_memory;
3641 };
3642
3643 void ImageBlitFromImage::logPrepare (TestLog& log, size_t commandIndex) const
3644 {
3645         log << TestLog::Message << commandIndex << ":" << getName() << " Allocate source image for image to image blit." << TestLog::EndMessage;
3646 }
3647
3648 void ImageBlitFromImage::prepare (PrepareContext& context)
3649 {
3650         const vk::InstanceInterface&    vki                             = context.getContext().getInstanceInterface();
3651         const vk::DeviceInterface&              vkd                             = context.getContext().getDeviceInterface();
3652         const vk::VkPhysicalDevice              physicalDevice  = context.getContext().getPhysicalDevice();
3653         const vk::VkDevice                              device                  = context.getContext().getDevice();
3654         const vk::VkQueue                               queue                   = context.getContext().getQueue();
3655         const vk::VkCommandPool                 commandPool             = context.getContext().getCommandPool();
3656         const vector<deUint32>&                 queueFamilies   = context.getContext().getQueueFamilies();
3657
3658         m_imageWidth            = context.getImageWidth();
3659         m_imageHeight           = context.getImageHeight();
3660         m_imageMemorySize       = context.getImageMemorySize();
3661
3662         if (m_scale == BLIT_SCALE_10)
3663         {
3664                 m_srcImageWidth                 = m_imageWidth;
3665                 m_srcImageHeight                = m_imageHeight;
3666         }
3667         else if (m_scale == BLIT_SCALE_20)
3668         {
3669                 m_srcImageWidth                 = m_imageWidth / 2;
3670                 m_srcImageHeight                = m_imageHeight / 2;
3671         }
3672         else
3673                 DE_FATAL("Unsupported scale");
3674
3675         {
3676                 const vk::VkImageCreateInfo     createInfo =
3677                 {
3678                         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3679                         DE_NULL,
3680
3681                         0,
3682                         vk::VK_IMAGE_TYPE_2D,
3683                         vk::VK_FORMAT_R8G8B8A8_UNORM,
3684                         {
3685                                 (deUint32)m_srcImageWidth,
3686                                 (deUint32)m_srcImageHeight,
3687                                 1u,
3688                         },
3689                         1, 1, // mipLevels, arrayLayers
3690                         vk::VK_SAMPLE_COUNT_1_BIT,
3691
3692                         vk::VK_IMAGE_TILING_OPTIMAL,
3693                         vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3694                         vk::VK_SHARING_MODE_EXCLUSIVE,
3695
3696                         (deUint32)queueFamilies.size(),
3697                         &queueFamilies[0],
3698                         vk::VK_IMAGE_LAYOUT_UNDEFINED
3699                 };
3700
3701                 m_srcImage = vk::createImage(vkd, device, &createInfo);
3702         }
3703
3704         m_memory = bindImageMemory(vki, vkd, physicalDevice, device, *m_srcImage, 0);
3705
3706         {
3707                 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));
3708                 const vk::Unique<vk::VkDeviceMemory>    memory                  (bindBufferMemory(vki, vkd, physicalDevice, device, *srcBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
3709                 const vk::Unique<vk::VkCommandBuffer>   commandBuffer   (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3710                 const vk::VkImageMemoryBarrier                  preImageBarrier =
3711                 {
3712                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3713                         DE_NULL,
3714
3715                         0,
3716                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3717
3718                         vk::VK_IMAGE_LAYOUT_UNDEFINED,
3719                         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3720
3721                         vk::VK_QUEUE_FAMILY_IGNORED,
3722                         vk::VK_QUEUE_FAMILY_IGNORED,
3723
3724                         *m_srcImage,
3725                         {
3726                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3727                                 0,      // Mip level
3728                                 1,      // Mip level count
3729                                 0,      // Layer
3730                                 1       // Layer count
3731                         }
3732                 };
3733                 const vk::VkImageMemoryBarrier                  postImageBarrier =
3734                 {
3735                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3736                         DE_NULL,
3737
3738                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3739                         0,
3740
3741                         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3742                         vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3743
3744                         vk::VK_QUEUE_FAMILY_IGNORED,
3745                         vk::VK_QUEUE_FAMILY_IGNORED,
3746
3747                         *m_srcImage,
3748                         {
3749                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3750                                 0,      // Mip level
3751                                 1,      // Mip level count
3752                                 0,      // Layer
3753                                 1       // Layer count
3754                         }
3755                 };
3756                 const vk::VkBufferImageCopy                             region                          =
3757                 {
3758                         0,
3759                         0, 0,
3760                         {
3761                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3762                                 0,      // mipLevel
3763                                 0,      // arrayLayer
3764                                 1       // layerCount
3765                         },
3766                         { 0, 0, 0 },
3767                         {
3768                                 (deUint32)m_srcImageWidth,
3769                                 (deUint32)m_srcImageHeight,
3770                                 1u
3771                         }
3772                 };
3773
3774                 {
3775                         void* const     ptr     = mapMemory(vkd, device, *memory, 4 * m_srcImageWidth * m_srcImageHeight);
3776                         de::Random      rng     (m_seed);
3777
3778                         {
3779                                 deUint8* const  data = (deUint8*)ptr;
3780
3781                                 for (size_t ndx = 0; ndx < (size_t)(4 * m_srcImageWidth * m_srcImageHeight); ndx++)
3782                                         data[ndx] = rng.getUint8();
3783                         }
3784
3785                         vk::flushMappedMemoryRange(vkd, device, *memory, 0, 4 * m_srcImageWidth * m_srcImageHeight);
3786                         vkd.unmapMemory(device, *memory);
3787                 }
3788
3789                 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);
3790                 vkd.cmdCopyBufferToImage(*commandBuffer, *srcBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
3791                 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);
3792
3793                 VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
3794                 queueRun(vkd, queue, *commandBuffer);
3795         }
3796 }
3797
3798 void ImageBlitFromImage::logSubmit (TestLog& log, size_t commandIndex) const
3799 {
3800         log << TestLog::Message << commandIndex << ":" << getName() << " Blit from another image" << (m_scale == BLIT_SCALE_20 ? " scale 2x" : "")  << TestLog::EndMessage;
3801 }
3802
3803 void ImageBlitFromImage::submit (SubmitContext& context)
3804 {
3805         const vk::DeviceInterface&      vkd                             = context.getContext().getDeviceInterface();
3806         const vk::VkCommandBuffer       commandBuffer   = context.getCommandBuffer();
3807         const vk::VkImageBlit           region                  =
3808         {
3809                 // Src
3810                 {
3811                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
3812                         0,      // mipLevel
3813                         0,      // arrayLayer
3814                         1       // layerCount
3815                 },
3816                 {
3817                         { 0, 0, 0 },
3818                         {
3819                                 m_srcImageWidth,
3820                                 m_srcImageHeight,
3821                                 1
3822                         },
3823                 },
3824
3825                 // Dst
3826                 {
3827                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
3828                         0,      // mipLevel
3829                         0,      // arrayLayer
3830                         1       // layerCount
3831                 },
3832                 {
3833                         { 0, 0, 0 },
3834                         {
3835                                 m_imageWidth,
3836                                 m_imageHeight,
3837                                 1u
3838                         }
3839                 }
3840         };
3841         vkd.cmdBlitImage(commandBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, context.getImage(), context.getImageLayout(), 1, &region, vk::VK_FILTER_NEAREST);
3842 }
3843
3844 void ImageBlitFromImage::verify (VerifyContext& context, size_t)
3845 {
3846         ReferenceMemory&        reference       (context.getReference());
3847         de::Random                      rng                     (m_seed);
3848
3849         reference.setUndefined(0, (size_t)m_imageMemorySize);
3850
3851         {
3852                 const PixelBufferAccess&        refAccess       (context.getReferenceImage().getAccess());
3853
3854                 if (m_scale == BLIT_SCALE_10)
3855                 {
3856                         for (deInt32 y = 0; y < m_imageHeight; y++)
3857                         for (deInt32 x = 0; x < m_imageWidth; x++)
3858                         {
3859                                 const deUint8 r8 = rng.getUint8();
3860                                 const deUint8 g8 = rng.getUint8();
3861                                 const deUint8 b8 = rng.getUint8();
3862                                 const deUint8 a8 = rng.getUint8();
3863
3864                                 refAccess.setPixel(UVec4(r8, g8, b8, a8), x, y);
3865                         }
3866                 }
3867                 else if (m_scale == BLIT_SCALE_20)
3868                 {
3869                         tcu::TextureLevel       source  (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_srcImageWidth, m_srcImageHeight);
3870                         const float                     xscale  = ((float)m_srcImageWidth)  / (float)m_imageWidth;
3871                         const float                     yscale  = ((float)m_srcImageHeight) / (float)m_imageHeight;
3872
3873                         for (deInt32 y = 0; y < m_srcImageHeight; y++)
3874                         for (deInt32 x = 0; x < m_srcImageWidth; x++)
3875                         {
3876                                 const deUint8 r8 = rng.getUint8();
3877                                 const deUint8 g8 = rng.getUint8();
3878                                 const deUint8 b8 = rng.getUint8();
3879                                 const deUint8 a8 = rng.getUint8();
3880
3881                                 source.getAccess().setPixel(UVec4(r8, g8, b8, a8), x, y);
3882                         }
3883
3884                         for (deInt32 y = 0; y < m_imageHeight; y++)
3885                         for (deInt32 x = 0; x < m_imageWidth; x++)
3886                                 refAccess.setPixel(source.getAccess().getPixelUint(int(float(x) * xscale), int(float(y) * yscale)), x, y);
3887                 }
3888                 else
3889                         DE_FATAL("Unsupported scale");
3890         }
3891 }
3892
3893 class ImageBlitToImage : public CmdCommand
3894 {
3895 public:
3896                                                                         ImageBlitToImage        (BlitScale scale) : m_scale(scale) {}
3897                                                                         ~ImageBlitToImage       (void) {}
3898         const char*                                             getName                         (void) const { return "ImageBlitToImage"; }
3899
3900         void                                                    logPrepare                      (TestLog& log, size_t commandIndex) const;
3901         void                                                    prepare                         (PrepareContext& context);
3902         void                                                    logSubmit                       (TestLog& log, size_t commandIndex) const;
3903         void                                                    submit                          (SubmitContext& context);
3904         void                                                    verify                          (VerifyContext& context, size_t commandIndex);
3905
3906 private:
3907         const BlitScale                                 m_scale;
3908         deInt32                                                 m_imageWidth;
3909         deInt32                                                 m_imageHeight;
3910         vk::VkDeviceSize                                m_imageMemorySize;
3911         deInt32                                                 m_dstImageWidth;
3912         deInt32                                                 m_dstImageHeight;
3913         vk::Move<vk::VkImage>                   m_dstImage;
3914         vk::Move<vk::VkDeviceMemory>    m_memory;
3915 };
3916
3917 void ImageBlitToImage::logPrepare (TestLog& log, size_t commandIndex) const
3918 {
3919         log << TestLog::Message << commandIndex << ":" << getName() << " Allocate destination image for image to image blit." << TestLog::EndMessage;
3920 }
3921
3922 void ImageBlitToImage::prepare (PrepareContext& context)
3923 {
3924         const vk::InstanceInterface&    vki                             = context.getContext().getInstanceInterface();
3925         const vk::DeviceInterface&              vkd                             = context.getContext().getDeviceInterface();
3926         const vk::VkPhysicalDevice              physicalDevice  = context.getContext().getPhysicalDevice();
3927         const vk::VkDevice                              device                  = context.getContext().getDevice();
3928         const vk::VkQueue                               queue                   = context.getContext().getQueue();
3929         const vk::VkCommandPool                 commandPool             = context.getContext().getCommandPool();
3930         const vector<deUint32>&                 queueFamilies   = context.getContext().getQueueFamilies();
3931
3932         m_imageWidth            = context.getImageWidth();
3933         m_imageHeight           = context.getImageHeight();
3934         m_imageMemorySize       = context.getImageMemorySize();
3935
3936         if (m_scale == BLIT_SCALE_10)
3937         {
3938                 m_dstImageWidth         = context.getImageWidth();
3939                 m_dstImageHeight        = context.getImageHeight();
3940         }
3941         else if (m_scale == BLIT_SCALE_20)
3942         {
3943                 m_dstImageWidth         = context.getImageWidth() * 2;
3944                 m_dstImageHeight        = context.getImageHeight() * 2;
3945         }
3946         else
3947                 DE_FATAL("Unsupportd blit scale");
3948
3949         {
3950                 const vk::VkImageCreateInfo     createInfo =
3951                 {
3952                         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3953                         DE_NULL,
3954
3955                         0,
3956                         vk::VK_IMAGE_TYPE_2D,
3957                         vk::VK_FORMAT_R8G8B8A8_UNORM,
3958                         {
3959                                 (deUint32)m_dstImageWidth,
3960                                 (deUint32)m_dstImageHeight,
3961                                 1u,
3962                         },
3963                         1, 1, // mipLevels, arrayLayers
3964                         vk::VK_SAMPLE_COUNT_1_BIT,
3965
3966                         vk::VK_IMAGE_TILING_OPTIMAL,
3967                         vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3968                         vk::VK_SHARING_MODE_EXCLUSIVE,
3969
3970                         (deUint32)queueFamilies.size(),
3971                         &queueFamilies[0],
3972                         vk::VK_IMAGE_LAYOUT_UNDEFINED
3973                 };
3974
3975                 m_dstImage = vk::createImage(vkd, device, &createInfo);
3976         }
3977
3978         m_memory = bindImageMemory(vki, vkd, physicalDevice, device, *m_dstImage, 0);
3979
3980         {
3981                 const vk::Unique<vk::VkCommandBuffer>   commandBuffer   (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3982                 const vk::VkImageMemoryBarrier                  barrier                 =
3983                 {
3984                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3985                         DE_NULL,
3986
3987                         0,
3988                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,
3989
3990                         vk::VK_IMAGE_LAYOUT_UNDEFINED,
3991                         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3992
3993                         vk::VK_QUEUE_FAMILY_IGNORED,
3994                         vk::VK_QUEUE_FAMILY_IGNORED,
3995
3996                         *m_dstImage,
3997                         {
3998                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
3999                                 0,      // Mip level
4000                                 1,      // Mip level count
4001                                 0,      // Layer
4002                                 1       // Layer count
4003                         }
4004                 };
4005
4006                 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);
4007
4008                 VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
4009                 queueRun(vkd, queue, *commandBuffer);
4010         }
4011 }
4012
4013 void ImageBlitToImage::logSubmit (TestLog& log, size_t commandIndex) const
4014 {
4015         log << TestLog::Message << commandIndex << ":" << getName() << " Blit image to another image" << (m_scale == BLIT_SCALE_20 ? " scale 2x" : "")  << TestLog::EndMessage;
4016 }
4017
4018 void ImageBlitToImage::submit (SubmitContext& context)
4019 {
4020         const vk::DeviceInterface&      vkd                             = context.getContext().getDeviceInterface();
4021         const vk::VkCommandBuffer       commandBuffer   = context.getCommandBuffer();
4022         const vk::VkImageBlit           region                  =
4023         {
4024                 // Src
4025                 {
4026                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
4027                         0,      // mipLevel
4028                         0,      // arrayLayer
4029                         1       // layerCount
4030                 },
4031                 {
4032                         { 0, 0, 0 },
4033                         {
4034                                 m_imageWidth,
4035                                 m_imageHeight,
4036                                 1
4037                         },
4038                 },
4039
4040                 // Dst
4041                 {
4042                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
4043                         0,      // mipLevel
4044                         0,      // arrayLayer
4045                         1       // layerCount
4046                 },
4047                 {
4048                         { 0, 0, 0 },
4049                         {
4050                                 m_dstImageWidth,
4051                                 m_dstImageHeight,
4052                                 1u
4053                         }
4054                 }
4055         };
4056         vkd.cmdBlitImage(commandBuffer, context.getImage(), context.getImageLayout(), *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region, vk::VK_FILTER_NEAREST);
4057 }
4058
4059 void ImageBlitToImage::verify (VerifyContext& context, size_t commandIndex)
4060 {
4061         tcu::ResultCollector&                                   resultCollector (context.getResultCollector());
4062         const vk::InstanceInterface&                    vki                             = context.getContext().getInstanceInterface();
4063         const vk::DeviceInterface&                              vkd                             = context.getContext().getDeviceInterface();
4064         const vk::VkPhysicalDevice                              physicalDevice  = context.getContext().getPhysicalDevice();
4065         const vk::VkDevice                                              device                  = context.getContext().getDevice();
4066         const vk::VkQueue                                               queue                   = context.getContext().getQueue();
4067         const vk::VkCommandPool                                 commandPool             = context.getContext().getCommandPool();
4068         const vk::Unique<vk::VkCommandBuffer>   commandBuffer   (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
4069         const vector<deUint32>&                                 queueFamilies   = context.getContext().getQueueFamilies();
4070         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));
4071         const vk::Unique<vk::VkDeviceMemory>    memory                  (bindBufferMemory(vki, vkd, physicalDevice, device, *dstBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
4072         {
4073                 const vk::VkImageMemoryBarrier          imageBarrier    =
4074                 {
4075                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
4076                         DE_NULL,
4077
4078                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,
4079                         vk::VK_ACCESS_TRANSFER_READ_BIT,
4080
4081                         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4082                         vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4083
4084                         vk::VK_QUEUE_FAMILY_IGNORED,
4085                         vk::VK_QUEUE_FAMILY_IGNORED,
4086
4087                         *m_dstImage,
4088                         {
4089                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
4090                                 0,      // Mip level
4091                                 1,      // Mip level count
4092                                 0,      // Layer
4093                                 1       // Layer count
4094                         }
4095                 };
4096                 const vk::VkBufferMemoryBarrier bufferBarrier =
4097                 {
4098                         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
4099                         DE_NULL,
4100
4101                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,
4102                         vk::VK_ACCESS_HOST_READ_BIT,
4103
4104                         vk::VK_QUEUE_FAMILY_IGNORED,
4105                         vk::VK_QUEUE_FAMILY_IGNORED,
4106                         *dstBuffer,
4107                         0,
4108                         vk::VK_WHOLE_SIZE
4109                 };
4110                 const vk::VkBufferImageCopy     region =
4111                 {
4112                         0,
4113                         0, 0,
4114                         {
4115                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
4116                                 0,      // mipLevel
4117                                 0,      // arrayLayer
4118                                 1       // layerCount
4119                         },
4120                         { 0, 0, 0 },
4121                         {
4122                                 (deUint32)m_dstImageWidth,
4123                                 (deUint32)m_dstImageHeight,
4124                                 1
4125                         }
4126                 };
4127
4128                 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);
4129                 vkd.cmdCopyImageToBuffer(*commandBuffer, *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dstBuffer, 1, &region);
4130                 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);
4131         }
4132
4133         VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
4134         queueRun(vkd, queue, *commandBuffer);
4135
4136         {
4137                 void* const     ptr             = mapMemory(vkd, device, *memory, 4 * m_dstImageWidth * m_dstImageHeight);
4138
4139                 vk::invalidateMappedMemoryRange(vkd, device, *memory, 0,  4 * m_dstImageWidth * m_dstImageHeight);
4140
4141                 if (m_scale == BLIT_SCALE_10)
4142                 {
4143                         const deUint8* const                    data            = (const deUint8*)ptr;
4144                         const ConstPixelBufferAccess    resAccess       (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_dstImageWidth, m_dstImageHeight, 1, data);
4145                         const ConstPixelBufferAccess&   refAccess       (context.getReferenceImage().getAccess());
4146
4147                         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))
4148                                 resultCollector.fail(de::toString(commandIndex) + ":" + getName() + " Image comparison failed");
4149                 }
4150                 else if (m_scale == BLIT_SCALE_20)
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                         tcu::TextureLevel                               reference       (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_dstImageWidth, m_dstImageHeight, 1);
4155
4156                         {
4157                                 const ConstPixelBufferAccess&   refAccess       (context.getReferenceImage().getAccess());
4158
4159                                 for (deInt32 y = 0; y < m_dstImageHeight; y++)
4160                                 for (deInt32 x = 0; x < m_dstImageWidth; x++)
4161                                 {
4162                                         reference.getAccess().setPixel(refAccess.getPixel(x/2, y/2), x, y);
4163                                 }
4164                         }
4165
4166                         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))
4167                                 resultCollector.fail(de::toString(commandIndex) + ":" + getName() + " Image comparison failed");
4168                 }
4169                 else
4170                         DE_FATAL("Unknown scale");
4171
4172                 vkd.unmapMemory(device, *memory);
4173         }
4174 }
4175
4176 class PrepareRenderPassContext
4177 {
4178 public:
4179                                                                 PrepareRenderPassContext        (PrepareContext&        context,
4180                                                                                                                          vk::VkRenderPass       renderPass,
4181                                                                                                                          vk::VkFramebuffer      framebuffer,
4182                                                                                                                          deInt32                        targetWidth,
4183                                                                                                                          deInt32                        targetHeight)
4184                 : m_context                     (context)
4185                 , m_renderPass          (renderPass)
4186                 , m_framebuffer         (framebuffer)
4187                 , m_targetWidth         (targetWidth)
4188                 , m_targetHeight        (targetHeight)
4189         {
4190         }
4191
4192         const Memory&                                                                   getMemory                                       (void) const { return m_context.getMemory(); }
4193         const Context&                                                                  getContext                                      (void) const { return m_context.getContext(); }
4194         const vk::ProgramCollection<vk::ProgramBinary>& getBinaryCollection                     (void) const { return m_context.getBinaryCollection(); }
4195
4196         vk::VkBuffer                            getBuffer                                       (void) const { return m_context.getBuffer(); }
4197         vk::VkDeviceSize                        getBufferSize                           (void) const { return m_context.getBufferSize(); }
4198
4199         vk::VkImage                                     getImage                                        (void) const { return m_context.getImage(); }
4200         deInt32                                         getImageWidth                           (void) const { return m_context.getImageWidth(); }
4201         deInt32                                         getImageHeight                          (void) const { return m_context.getImageHeight(); }
4202         vk::VkImageLayout                       getImageLayout                          (void) const { return m_context.getImageLayout(); }
4203
4204         deInt32                                         getTargetWidth                          (void) const { return m_targetWidth; }
4205         deInt32                                         getTargetHeight                         (void) const { return m_targetHeight; }
4206
4207         vk::VkRenderPass                        getRenderPass                           (void) const { return m_renderPass; }
4208
4209 private:
4210         PrepareContext&                         m_context;
4211         const vk::VkRenderPass          m_renderPass;
4212         const vk::VkFramebuffer         m_framebuffer;
4213         const deInt32                           m_targetWidth;
4214         const deInt32                           m_targetHeight;
4215 };
4216
4217 class VerifyRenderPassContext
4218 {
4219 public:
4220                                                         VerifyRenderPassContext         (VerifyContext&                 context,
4221                                                                                                                  deInt32                                targetWidth,
4222                                                                                                                  deInt32                                targetHeight)
4223                 : m_context                     (context)
4224                 , m_referenceTarget     (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), targetWidth, targetHeight)
4225         {
4226         }
4227
4228         const Context&                  getContext                      (void) const { return m_context.getContext(); }
4229         TestLog&                                getLog                          (void) const { return m_context.getLog(); }
4230         tcu::ResultCollector&   getResultCollector      (void) const { return m_context.getResultCollector(); }
4231
4232         TextureLevel&                   getReferenceTarget      (void) { return m_referenceTarget; }
4233
4234         ReferenceMemory&                getReference            (void) { return m_context.getReference(); }
4235         TextureLevel&                   getReferenceImage       (void) { return m_context.getReferenceImage();}
4236
4237 private:
4238         VerifyContext&  m_context;
4239         TextureLevel    m_referenceTarget;
4240 };
4241
4242
4243 class RenderPassCommand
4244 {
4245 public:
4246         virtual                         ~RenderPassCommand      (void) {}
4247         virtual const char*     getName                         (void) const = 0;
4248
4249         // Log things that are done during prepare
4250         virtual void            logPrepare                      (TestLog&, size_t) const {}
4251         // Log submitted calls etc.
4252         virtual void            logSubmit                       (TestLog&, size_t) const {}
4253
4254         // Allocate vulkan resources and prepare for submit.
4255         virtual void            prepare                         (PrepareRenderPassContext&) {}
4256
4257         // Submit commands to command buffer.
4258         virtual void            submit                          (SubmitContext&) {}
4259
4260         // Verify results
4261         virtual void            verify                          (VerifyRenderPassContext&, size_t) {}
4262 };
4263
4264 class SubmitRenderPass : public CmdCommand
4265 {
4266 public:
4267                                 SubmitRenderPass        (const vector<RenderPassCommand*>& commands);
4268                                 ~SubmitRenderPass       (void) {}
4269         const char*     getName                         (void) const { return "SubmitRenderPass"; }
4270
4271         void            logPrepare                      (TestLog&, size_t) const;
4272         void            logSubmit                       (TestLog&, size_t) const;
4273
4274         void            prepare                         (PrepareContext&);
4275         void            submit                          (SubmitContext&);
4276
4277         void            verify                          (VerifyContext&, size_t);
4278
4279 private:
4280         const deInt32                                   m_targetWidth;
4281         const deInt32                                   m_targetHeight;
4282         vk::Move<vk::VkRenderPass>              m_renderPass;
4283         vk::Move<vk::VkDeviceMemory>    m_colorTargetMemory;
4284         de::MovePtr<vk::Allocation>             m_colorTargetMemory2;
4285         vk::Move<vk::VkImage>                   m_colorTarget;
4286         vk::Move<vk::VkImageView>               m_colorTargetView;
4287         vk::Move<vk::VkFramebuffer>             m_framebuffer;
4288         vector<RenderPassCommand*>              m_commands;
4289 };
4290
4291 SubmitRenderPass::SubmitRenderPass (const vector<RenderPassCommand*>& commands)
4292         : m_targetWidth         (256)
4293         , m_targetHeight        (256)
4294         , m_commands            (commands)
4295 {
4296 }
4297
4298 void SubmitRenderPass::logPrepare (TestLog& log, size_t commandIndex) const
4299 {
4300         const string                            sectionName     (de::toString(commandIndex) + ":" + getName());
4301         const tcu::ScopedLogSection     section         (log, sectionName, sectionName);
4302
4303         for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4304         {
4305                 RenderPassCommand& command = *m_commands[cmdNdx];
4306                 command.logPrepare(log, cmdNdx);
4307         }
4308 }
4309
4310 void SubmitRenderPass::logSubmit (TestLog& log, size_t commandIndex) const
4311 {
4312         const string                            sectionName     (de::toString(commandIndex) + ":" + getName());
4313         const tcu::ScopedLogSection     section         (log, sectionName, sectionName);
4314
4315         for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4316         {
4317                 RenderPassCommand& command = *m_commands[cmdNdx];
4318                 command.logSubmit(log, cmdNdx);
4319         }
4320 }
4321
4322 void SubmitRenderPass::prepare (PrepareContext& context)
4323 {
4324         const vk::InstanceInterface&                    vki                             = context.getContext().getInstanceInterface();
4325         const vk::DeviceInterface&                              vkd                             = context.getContext().getDeviceInterface();
4326         const vk::VkPhysicalDevice                              physicalDevice  = context.getContext().getPhysicalDevice();
4327         const vk::VkDevice                                              device                  = context.getContext().getDevice();
4328         const vector<deUint32>&                                 queueFamilies   = context.getContext().getQueueFamilies();
4329
4330         const vk::VkAttachmentReference colorAttachments[]      =
4331         {
4332                 { 0, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }
4333         };
4334         const vk::VkSubpassDescription  subpass                         =
4335         {
4336                 0u,
4337                 vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
4338
4339                 0u,
4340                 DE_NULL,
4341
4342                 DE_LENGTH_OF_ARRAY(colorAttachments),
4343                 colorAttachments,
4344                 DE_NULL,
4345                 DE_NULL,
4346                 0u,
4347                 DE_NULL
4348         };
4349         const vk::VkAttachmentDescription attachment =
4350         {
4351                 0u,
4352                 vk::VK_FORMAT_R8G8B8A8_UNORM,
4353                 vk::VK_SAMPLE_COUNT_1_BIT,
4354
4355                 vk::VK_ATTACHMENT_LOAD_OP_CLEAR,
4356                 vk::VK_ATTACHMENT_STORE_OP_STORE,
4357
4358                 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4359                 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
4360
4361                 vk::VK_IMAGE_LAYOUT_UNDEFINED,
4362                 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
4363         };
4364         {
4365                 const vk::VkImageCreateInfo createInfo =
4366                 {
4367                         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
4368                         DE_NULL,
4369                         0u,
4370
4371                         vk::VK_IMAGE_TYPE_2D,
4372                         vk::VK_FORMAT_R8G8B8A8_UNORM,
4373                         { (deUint32)m_targetWidth, (deUint32)m_targetHeight, 1u },
4374                         1u,
4375                         1u,
4376                         vk::VK_SAMPLE_COUNT_1_BIT,
4377                         vk::VK_IMAGE_TILING_OPTIMAL,
4378                         vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
4379                         vk::VK_SHARING_MODE_EXCLUSIVE,
4380                         (deUint32)queueFamilies.size(),
4381                         &queueFamilies[0],
4382                         vk::VK_IMAGE_LAYOUT_UNDEFINED
4383                 };
4384
4385                 m_colorTarget = vk::createImage(vkd, device, &createInfo);
4386         }
4387
4388         m_colorTargetMemory = bindImageMemory(vki, vkd, physicalDevice, device, *m_colorTarget, 0);
4389
4390         {
4391                 const vk::VkImageViewCreateInfo createInfo =
4392                 {
4393                         vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
4394                         DE_NULL,
4395
4396                         0u,
4397                         *m_colorTarget,
4398                         vk::VK_IMAGE_VIEW_TYPE_2D,
4399                         vk::VK_FORMAT_R8G8B8A8_UNORM,
4400                         {
4401                                 vk::VK_COMPONENT_SWIZZLE_R,
4402                                 vk::VK_COMPONENT_SWIZZLE_G,
4403                                 vk::VK_COMPONENT_SWIZZLE_B,
4404                                 vk::VK_COMPONENT_SWIZZLE_A
4405                         },
4406                         {
4407                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,
4408                                 0u,
4409                                 1u,
4410                                 0u,
4411                                 1u
4412                         }
4413                 };
4414
4415                 m_colorTargetView = vk::createImageView(vkd, device, &createInfo);
4416         }
4417         {
4418                 const vk::VkRenderPassCreateInfo createInfo =
4419                 {
4420                         vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
4421                         DE_NULL,
4422                         0u,
4423
4424                         1u,
4425                         &attachment,
4426
4427                         1u,
4428                         &subpass,
4429
4430                         0,
4431                         DE_NULL
4432                 };
4433
4434                 m_renderPass = vk::createRenderPass(vkd, device, &createInfo);
4435         }
4436
4437         {
4438                 const vk::VkImageView                           imageViews[]    =
4439                 {
4440                         *m_colorTargetView
4441                 };
4442                 const vk::VkFramebufferCreateInfo       createInfo              =
4443                 {
4444                         vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
4445                         DE_NULL,
4446                         0u,
4447
4448                         *m_renderPass,
4449                         DE_LENGTH_OF_ARRAY(imageViews),
4450                         imageViews,
4451                         (deUint32)m_targetWidth,
4452                         (deUint32)m_targetHeight,
4453                         1u
4454                 };
4455
4456                 m_framebuffer = vk::createFramebuffer(vkd, device, &createInfo);
4457         }
4458
4459         {
4460                 PrepareRenderPassContext renderpassContext (context, *m_renderPass, *m_framebuffer, m_targetWidth, m_targetHeight);
4461
4462                 for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4463                 {
4464                         RenderPassCommand& command = *m_commands[cmdNdx];
4465                         command.prepare(renderpassContext);
4466                 }
4467         }
4468 }
4469
4470 void SubmitRenderPass::submit (SubmitContext& context)
4471 {
4472         const vk::DeviceInterface&              vkd                             = context.getContext().getDeviceInterface();
4473         const vk::VkCommandBuffer               commandBuffer   = context.getCommandBuffer();
4474         const vk::VkClearValue                  clearValue              = vk::makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f);
4475
4476         const vk::VkRenderPassBeginInfo beginInfo               =
4477         {
4478                 vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
4479                 DE_NULL,
4480
4481                 *m_renderPass,
4482                 *m_framebuffer,
4483
4484                 { { 0, 0 },  { (deUint32)m_targetWidth, (deUint32)m_targetHeight } },
4485                 1u,
4486                 &clearValue
4487         };
4488
4489         vkd.cmdBeginRenderPass(commandBuffer, &beginInfo, vk::VK_SUBPASS_CONTENTS_INLINE);
4490
4491         for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4492         {
4493                 RenderPassCommand& command = *m_commands[cmdNdx];
4494
4495                 command.submit(context);
4496         }
4497
4498         vkd.cmdEndRenderPass(commandBuffer);
4499 }
4500
4501 void SubmitRenderPass::verify (VerifyContext& context, size_t commandIndex)
4502 {
4503         TestLog&                                        log                             (context.getLog());
4504         tcu::ResultCollector&           resultCollector (context.getResultCollector());
4505         const string                            sectionName             (de::toString(commandIndex) + ":" + getName());
4506         const tcu::ScopedLogSection     section                 (log, sectionName, sectionName);
4507         VerifyRenderPassContext         verifyContext   (context, m_targetWidth, m_targetHeight);
4508
4509         tcu::clear(verifyContext.getReferenceTarget().getAccess(), Vec4(0.0f, 0.0f, 0.0f, 1.0f));
4510
4511         for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
4512         {
4513                 RenderPassCommand& command = *m_commands[cmdNdx];
4514                 command.verify(verifyContext, cmdNdx);
4515         }
4516
4517         {
4518                 const vk::InstanceInterface&                    vki                             = context.getContext().getInstanceInterface();
4519                 const vk::DeviceInterface&                              vkd                             = context.getContext().getDeviceInterface();
4520                 const vk::VkPhysicalDevice                              physicalDevice  = context.getContext().getPhysicalDevice();
4521                 const vk::VkDevice                                              device                  = context.getContext().getDevice();
4522                 const vk::VkQueue                                               queue                   = context.getContext().getQueue();
4523                 const vk::VkCommandPool                                 commandPool             = context.getContext().getCommandPool();
4524                 const vk::Unique<vk::VkCommandBuffer>   commandBuffer   (createBeginCommandBuffer(vkd, device, commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
4525                 const vector<deUint32>&                                 queueFamilies   = context.getContext().getQueueFamilies();
4526                 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));
4527                 const vk::Unique<vk::VkDeviceMemory>    memory                  (bindBufferMemory(vki, vkd, physicalDevice, device, *dstBuffer, vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
4528                 {
4529                         const vk::VkImageMemoryBarrier          imageBarrier    =
4530                         {
4531                                 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
4532                                 DE_NULL,
4533
4534                                 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
4535                                 vk::VK_ACCESS_TRANSFER_READ_BIT,
4536
4537                                 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4538                                 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4539
4540                                 vk::VK_QUEUE_FAMILY_IGNORED,
4541                                 vk::VK_QUEUE_FAMILY_IGNORED,
4542
4543                                 *m_colorTarget,
4544                                 {
4545                                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
4546                                         0,      // Mip level
4547                                         1,      // Mip level count
4548                                         0,      // Layer
4549                                         1       // Layer count
4550                                 }
4551                         };
4552                         const vk::VkBufferMemoryBarrier bufferBarrier =
4553                         {
4554                                 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
4555                                 DE_NULL,
4556
4557                                 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
4558                                 vk::VK_ACCESS_HOST_READ_BIT,
4559
4560                                 vk::VK_QUEUE_FAMILY_IGNORED,
4561                                 vk::VK_QUEUE_FAMILY_IGNORED,
4562                                 *dstBuffer,
4563                                 0,
4564                                 vk::VK_WHOLE_SIZE
4565                         };
4566                         const vk::VkBufferImageCopy     region =
4567                         {
4568                                 0,
4569                                 0, 0,
4570                                 {
4571                                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
4572                                         0,      // mipLevel
4573                                         0,      // arrayLayer
4574                                         1       // layerCount
4575                                 },
4576                                 { 0, 0, 0 },
4577                                 {
4578                                         (deUint32)m_targetWidth,
4579                                         (deUint32)m_targetHeight,
4580                                         1u
4581                                 }
4582                         };
4583
4584                         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);
4585                         vkd.cmdCopyImageToBuffer(*commandBuffer, *m_colorTarget, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dstBuffer, 1, &region);
4586                         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);
4587                 }
4588
4589                 VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
4590                 queueRun(vkd, queue, *commandBuffer);
4591
4592                 {
4593                         void* const     ptr             = mapMemory(vkd, device, *memory, 4 * m_targetWidth * m_targetHeight);
4594
4595                         vk::invalidateMappedMemoryRange(vkd, device, *memory, 0,  4 * m_targetWidth * m_targetHeight);
4596
4597                         {
4598                                 const deUint8* const                    data            = (const deUint8*)ptr;
4599                                 const ConstPixelBufferAccess    resAccess       (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_targetWidth, m_targetHeight, 1, data);
4600                                 const ConstPixelBufferAccess&   refAccess       (verifyContext.getReferenceTarget().getAccess());
4601
4602                                 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))
4603                                         resultCollector.fail(de::toString(commandIndex) + ":" + getName() + " Image comparison failed");
4604                         }
4605
4606                         vkd.unmapMemory(device, *memory);
4607                 }
4608         }
4609 }
4610
4611 class RenderBuffer : public RenderPassCommand
4612 {
4613 public:
4614         enum RenderAs
4615         {
4616                 RENDERAS_VERTEX_BUFFER,
4617                 RENDERAS_INDEX_BUFFER,
4618         };
4619                                 RenderBuffer            (RenderAs renderAs) : m_renderAs(renderAs) {}
4620                                 ~RenderBuffer           (void) {}
4621
4622         const char*     getName                         (void) const { return "RenderBuffer"; }
4623         void            logPrepare                      (TestLog&, size_t) const;
4624         void            logSubmit                       (TestLog&, size_t) const;
4625         void            prepare                         (PrepareRenderPassContext&);
4626         void            submit                          (SubmitContext& context);
4627         void            verify                          (VerifyRenderPassContext&, size_t);
4628
4629 private:
4630         const RenderAs                                          m_renderAs;
4631         vk::Move<vk::VkPipeline>                        m_pipeline;
4632         vk::Move<vk::VkPipelineLayout>          m_pipelineLayout;
4633         vk::VkDeviceSize                                        m_bufferSize;
4634
4635         static const vk::ProgramBinary&         getVertexShader         (const vk::ProgramCollection<vk::ProgramBinary>& collections, RenderAs renderAs)
4636         {
4637                 switch (renderAs)
4638                 {
4639                         case RENDERAS_VERTEX_BUFFER:
4640                                 return collections.get("vertex-buffer.vert");
4641
4642                         case RENDERAS_INDEX_BUFFER:
4643                                 return collections.get("index-buffer.vert");
4644
4645                         default:
4646                                 DE_FATAL("Unknown renderAs");
4647                                 return collections.get("");
4648                 }
4649         }
4650 };
4651
4652 void RenderBuffer::logPrepare (TestLog& log, size_t commandIndex) const
4653 {
4654         log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render buffer as " << (m_renderAs == RENDERAS_VERTEX_BUFFER ? "vertex" : "index") << " buffer." << TestLog::EndMessage;
4655 }
4656
4657 void RenderBuffer::logSubmit (TestLog& log, size_t commandIndex) const
4658 {
4659         log << TestLog::Message << commandIndex << ":" << getName() << " Render using buffer as " << (m_renderAs == RENDERAS_VERTEX_BUFFER ? "vertex" : "index") << " buffer." << TestLog::EndMessage;
4660 }
4661
4662 void RenderBuffer::prepare (PrepareRenderPassContext& context)
4663 {
4664         const vk::DeviceInterface&                              vkd                                             = context.getContext().getDeviceInterface();
4665         const vk::VkDevice                                              device                                  = context.getContext().getDevice();
4666         const vk::VkRenderPass                                  renderPass                              = context.getRenderPass();
4667         const deUint32                                                  subpass                                 = 0;
4668         const vk::Unique<vk::VkShaderModule>    vertexShaderModule              (vk::createShaderModule(vkd, device, getVertexShader(context.getBinaryCollection(), m_renderAs), 0));
4669         const vk::Unique<vk::VkShaderModule>    fragmentShaderModule    (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-white.frag"), 0));
4670
4671         m_bufferSize = context.getBufferSize();
4672
4673         {
4674                 const vk::VkPipelineLayoutCreateInfo    createInfo      =
4675                 {
4676                         vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
4677                         DE_NULL,
4678                         0,
4679                         0,
4680                         DE_NULL,
4681                         0,
4682                         DE_NULL
4683                 };
4684
4685                 m_pipelineLayout = vk::createPipelineLayout(vkd, device, &createInfo);
4686         }
4687
4688         {
4689                 const vk::VkPipelineShaderStageCreateInfo                       shaderStages[]                                  =
4690                 {
4691                         {
4692                                 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
4693                                 DE_NULL,
4694                                 0,
4695                                 vk::VK_SHADER_STAGE_VERTEX_BIT,
4696                                 *vertexShaderModule,
4697                                 "main",
4698                                 DE_NULL
4699                         },
4700                         {
4701                                 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
4702                                 DE_NULL,
4703                                 0,
4704                                 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
4705                                 *fragmentShaderModule,
4706                                 "main",
4707                                 DE_NULL
4708                         }
4709                 };
4710                 const vk::VkPipelineDepthStencilStateCreateInfo         depthStencilState                               =
4711                 {
4712                         vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
4713                         DE_NULL,
4714                         0u,
4715                         DE_FALSE,
4716                         DE_FALSE,
4717                         vk::VK_COMPARE_OP_ALWAYS,
4718                         DE_FALSE,
4719                         DE_FALSE,
4720                         {
4721                                 vk::VK_STENCIL_OP_KEEP,
4722                                 vk::VK_STENCIL_OP_KEEP,
4723                                 vk::VK_STENCIL_OP_KEEP,
4724                                 vk::VK_COMPARE_OP_ALWAYS,
4725                                 0u,
4726                                 0u,
4727                                 0u,
4728                         },
4729                         {
4730                                 vk::VK_STENCIL_OP_KEEP,
4731                                 vk::VK_STENCIL_OP_KEEP,
4732                                 vk::VK_STENCIL_OP_KEEP,
4733                                 vk::VK_COMPARE_OP_ALWAYS,
4734                                 0u,
4735                                 0u,
4736                                 0u,
4737                         },
4738                         -1.0f,
4739                         +1.0f
4740                 };
4741                 const vk::VkVertexInputBindingDescription                       vertexBindingDescriptions[]             =
4742                 {
4743                         {
4744                                 0,
4745                                 2,
4746                                 vk::VK_VERTEX_INPUT_RATE_VERTEX
4747                         }
4748                 };
4749                 const vk::VkVertexInputAttributeDescription                     vertexAttributeDescriptions[]   =
4750                 {
4751                         {
4752                                 0,
4753                                 0,
4754                                 vk::VK_FORMAT_R8G8_UNORM,
4755                                 0
4756                         }
4757                 };
4758                 const vk::VkPipelineVertexInputStateCreateInfo          vertexInputState                                =
4759                 {
4760                         vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
4761                         DE_NULL,
4762                         0u,
4763
4764                         m_renderAs == RENDERAS_VERTEX_BUFFER ? DE_LENGTH_OF_ARRAY(vertexBindingDescriptions) : 0u,
4765                         m_renderAs == RENDERAS_VERTEX_BUFFER ? vertexBindingDescriptions : DE_NULL,
4766
4767                         m_renderAs == RENDERAS_VERTEX_BUFFER ? DE_LENGTH_OF_ARRAY(vertexAttributeDescriptions) : 0u,
4768                         m_renderAs == RENDERAS_VERTEX_BUFFER ? vertexAttributeDescriptions : DE_NULL,
4769                 };
4770                 const vk::VkPipelineInputAssemblyStateCreateInfo        inputAssemblyState                              =
4771                 {
4772                         vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
4773                         DE_NULL,
4774                         0,
4775                         vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
4776                         vk::VK_FALSE
4777                 };
4778                 const vk::VkViewport                                                            viewports[]                                             =
4779                 {
4780                         { 0.0f, 0.0f, (float)context.getTargetWidth(), (float)context.getTargetHeight(), 0.0f, 1.0f }
4781                 };
4782                 const vk::VkRect2D                                                                      scissors[]                                              =
4783                 {
4784                         { { 0, 0 }, { (deUint32)context.getTargetWidth(), (deUint32)context.getTargetHeight() } }
4785                 };
4786                 const vk::VkPipelineViewportStateCreateInfo                     viewportState                                   =
4787                 {
4788                         vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
4789                         DE_NULL,
4790                         0,
4791                         DE_LENGTH_OF_ARRAY(viewports),
4792                         viewports,
4793                         DE_LENGTH_OF_ARRAY(scissors),
4794                         scissors
4795                 };
4796                 const vk::VkPipelineRasterizationStateCreateInfo        rasterState                                             =
4797                 {
4798                         vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
4799                         DE_NULL,
4800                         0,
4801
4802                         vk::VK_TRUE,
4803                         vk::VK_FALSE,
4804                         vk::VK_POLYGON_MODE_FILL,
4805                         vk::VK_CULL_MODE_NONE,
4806                         vk::VK_FRONT_FACE_COUNTER_CLOCKWISE,
4807                         vk::VK_FALSE,
4808                         0.0f,
4809                         0.0f,
4810                         0.0f,
4811                         1.0f
4812                 };
4813                 const vk::VkSampleMask                                                          sampleMask                                              = ~0u;
4814                 const vk::VkPipelineMultisampleStateCreateInfo          multisampleState                                =
4815                 {
4816                         vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
4817                         DE_NULL,
4818                         0,
4819
4820                         vk::VK_SAMPLE_COUNT_1_BIT,
4821                         vk::VK_FALSE,
4822                         0.0f,
4823                         &sampleMask,
4824                         vk::VK_FALSE,
4825                         vk::VK_FALSE
4826                 };
4827                 const vk::VkPipelineColorBlendAttachmentState           attachments[]                                   =
4828                 {
4829                         {
4830                                 vk::VK_FALSE,
4831                                 vk::VK_BLEND_FACTOR_ONE,
4832                                 vk::VK_BLEND_FACTOR_ZERO,
4833                                 vk::VK_BLEND_OP_ADD,
4834                                 vk::VK_BLEND_FACTOR_ONE,
4835                                 vk::VK_BLEND_FACTOR_ZERO,
4836                                 vk::VK_BLEND_OP_ADD,
4837                                 (vk::VK_COLOR_COMPONENT_R_BIT|
4838                                  vk::VK_COLOR_COMPONENT_G_BIT|
4839                                  vk::VK_COLOR_COMPONENT_B_BIT|
4840                                  vk::VK_COLOR_COMPONENT_A_BIT)
4841                         }
4842                 };
4843                 const vk::VkPipelineColorBlendStateCreateInfo           colorBlendState                                 =
4844                 {
4845                         vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
4846                         DE_NULL,
4847                         0,
4848
4849                         vk::VK_FALSE,
4850                         vk::VK_LOGIC_OP_COPY,
4851                         DE_LENGTH_OF_ARRAY(attachments),
4852                         attachments,
4853                         { 0.0f, 0.0f, 0.0f, 0.0f }
4854                 };
4855                 const vk::VkGraphicsPipelineCreateInfo                          createInfo                                              =
4856                 {
4857                         vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
4858                         DE_NULL,
4859                         0u,
4860
4861                         DE_LENGTH_OF_ARRAY(shaderStages),
4862                         shaderStages,
4863
4864                         &vertexInputState,
4865                         &inputAssemblyState,
4866                         DE_NULL,
4867                         &viewportState,
4868                         &rasterState,
4869                         &multisampleState,
4870                         &depthStencilState,
4871                         &colorBlendState,
4872                         DE_NULL,
4873                         *m_pipelineLayout,
4874                         renderPass,
4875                         subpass,
4876                         0,
4877                         0
4878                 };
4879
4880                 m_pipeline = vk::createGraphicsPipeline(vkd, device, 0, &createInfo);
4881         }
4882 }
4883
4884 void RenderBuffer::submit (SubmitContext& context)
4885 {
4886         const vk::DeviceInterface&      vkd                             = context.getContext().getDeviceInterface();
4887         const vk::VkCommandBuffer       commandBuffer   = context.getCommandBuffer();
4888         const vk::VkDeviceSize          offset                  = 0;
4889         const vk::VkBuffer                      buffer                  = context.getBuffer();
4890
4891         vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
4892
4893         if (m_renderAs == RENDERAS_VERTEX_BUFFER)
4894         {
4895                 vkd.cmdBindVertexBuffers(commandBuffer, 0, 1, &buffer, &offset);
4896                 vkd.cmdDraw(commandBuffer, (deUint32)(context.getBufferSize() / 2), 1, 0, 0);
4897         }
4898         else if (m_renderAs == RENDERAS_INDEX_BUFFER)
4899         {
4900                 vkd.cmdBindIndexBuffer(commandBuffer, context.getBuffer(), 0, vk::VK_INDEX_TYPE_UINT16);
4901                 vkd.cmdDrawIndexed(commandBuffer, (deUint32)(context.getBufferSize() / 2), 1, 0, 0, 0);
4902         }
4903         else
4904                 DE_FATAL("Unknown renderAs");
4905 }
4906
4907 void RenderBuffer::verify (VerifyRenderPassContext& context, size_t)
4908 {
4909         for (size_t pos = 0; pos < (size_t)m_bufferSize / 2; pos++)
4910         {
4911                 const deUint8 x  = context.getReference().get(pos * 2);
4912                 const deUint8 y  = context.getReference().get((pos * 2) + 1);
4913
4914                 context.getReferenceTarget().getAccess().setPixel(Vec4(1.0f, 1.0f, 1.0f, 1.0f), x, y);
4915         }
4916 }
4917
4918 enum Op
4919 {
4920         OP_MAP,
4921         OP_UNMAP,
4922
4923         OP_MAP_FLUSH,
4924         OP_MAP_INVALIDATE,
4925
4926         OP_MAP_READ,
4927         OP_MAP_WRITE,
4928         OP_MAP_MODIFY,
4929
4930         OP_BUFFER_CREATE,
4931         OP_BUFFER_DESTROY,
4932         OP_BUFFER_BINDMEMORY,
4933
4934         OP_QUEUE_WAIT_FOR_IDLE,
4935         OP_DEVICE_WAIT_FOR_IDLE,
4936
4937         OP_COMMAND_BUFFER_BEGIN,
4938         OP_COMMAND_BUFFER_END,
4939
4940         // Buffer transfer operations
4941         OP_BUFFER_FILL,
4942         OP_BUFFER_UPDATE,
4943
4944         OP_BUFFER_COPY_TO_BUFFER,
4945         OP_BUFFER_COPY_FROM_BUFFER,
4946
4947         OP_BUFFER_COPY_TO_IMAGE,
4948         OP_BUFFER_COPY_FROM_IMAGE,
4949
4950         OP_IMAGE_CREATE,
4951         OP_IMAGE_DESTROY,
4952         OP_IMAGE_BINDMEMORY,
4953
4954         OP_IMAGE_TRANSITION_LAYOUT,
4955
4956         OP_IMAGE_COPY_TO_BUFFER,
4957         OP_IMAGE_COPY_FROM_BUFFER,
4958
4959         OP_IMAGE_COPY_TO_IMAGE,
4960         OP_IMAGE_COPY_FROM_IMAGE,
4961
4962         OP_IMAGE_BLIT_TO_IMAGE,
4963         OP_IMAGE_BLIT_FROM_IMAGE,
4964
4965         OP_IMAGE_RESOLVE,
4966
4967         OP_PIPELINE_BARRIER_GLOBAL,
4968         OP_PIPELINE_BARRIER_BUFFER,
4969         OP_PIPELINE_BARRIER_IMAGE,
4970
4971         // Renderpass operations
4972         OP_RENDERPASS_BEGIN,
4973         OP_RENDERPASS_END,
4974
4975         // Commands inside render pass
4976         OP_RENDER_VERTEX_BUFFER,
4977         OP_RENDER_INDEX_BUFFER
4978 };
4979
4980 enum Stage
4981 {
4982         STAGE_HOST,
4983         STAGE_COMMAND_BUFFER,
4984
4985         STAGE_RENDER_PASS
4986 };
4987
4988 vk::VkAccessFlags getWriteAccessFlags (void)
4989 {
4990         return vk::VK_ACCESS_SHADER_WRITE_BIT
4991                 | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
4992                 | vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
4993                 | vk::VK_ACCESS_TRANSFER_WRITE_BIT
4994                 | vk::VK_ACCESS_HOST_WRITE_BIT
4995                 | vk::VK_ACCESS_MEMORY_WRITE_BIT;
4996 }
4997
4998 bool isWriteAccess (vk::VkAccessFlagBits access)
4999 {
5000         return (getWriteAccessFlags() & access) != 0;
5001 }
5002
5003 class CacheState
5004 {
5005 public:
5006                                                                         CacheState                              (vk::VkPipelineStageFlags allowedStages, vk::VkAccessFlags allowedAccesses);
5007
5008         bool                                                    isValid                                 (vk::VkPipelineStageFlagBits    stage,
5009                                                                                                                          vk::VkAccessFlagBits                   access) const;
5010
5011         void                                                    perform                                 (vk::VkPipelineStageFlagBits    stage,
5012                                                                                                                          vk::VkAccessFlagBits                   access);
5013
5014         void                                                    submitCommandBuffer             (void);
5015         void                                                    waitForIdle                             (void);
5016
5017         void                                                    getFullBarrier                  (vk::VkPipelineStageFlags&      srcStages,
5018                                                                                                                          vk::VkAccessFlags&                     srcAccesses,
5019                                                                                                                          vk::VkPipelineStageFlags&      dstStages,
5020                                                                                                                          vk::VkAccessFlags&                     dstAccesses) const;
5021
5022         void                                                    barrier                                 (vk::VkPipelineStageFlags       srcStages,
5023                                                                                                                          vk::VkAccessFlags                      srcAccesses,
5024                                                                                                                          vk::VkPipelineStageFlags       dstStages,
5025                                                                                                                          vk::VkAccessFlags                      dstAccesses);
5026
5027         void                                                    imageLayoutBarrier              (vk::VkPipelineStageFlags       srcStages,
5028                                                                                                                          vk::VkAccessFlags                      srcAccesses,
5029                                                                                                                          vk::VkPipelineStageFlags       dstStages,
5030                                                                                                                          vk::VkAccessFlags                      dstAccesses);
5031
5032         void                                                    checkImageLayoutBarrier (vk::VkPipelineStageFlags       srcStages,
5033                                                                                                                          vk::VkAccessFlags                      srcAccesses,
5034                                                                                                                          vk::VkPipelineStageFlags       dstStages,
5035                                                                                                                          vk::VkAccessFlags                      dstAccesses);
5036
5037         // Everything is clean and there is no need for barriers
5038         bool                                                    isClean                                 (void) const;
5039
5040         vk::VkPipelineStageFlags                getAllowedStages                (void) const { return m_allowedStages; }
5041         vk::VkAccessFlags                               getAllowedAcceses               (void) const { return m_allowedAccesses; }
5042 private:
5043         // Limit which stages and accesses are used by the CacheState tracker
5044         const vk::VkPipelineStageFlags  m_allowedStages;
5045         const vk::VkAccessFlags                 m_allowedAccesses;
5046
5047         // [dstStage][srcStage] = srcAccesses
5048         // In stage dstStage write srcAccesses from srcStage are not yet available
5049         vk::VkAccessFlags                               m_unavailableWriteOperations[PIPELINESTAGE_LAST][PIPELINESTAGE_LAST];
5050         // Latest pipeline transition is not available in stage
5051         bool                                                    m_unavailableLayoutTransition[PIPELINESTAGE_LAST];
5052         // [dstStage] = dstAccesses
5053         // In stage dstStage ops with dstAccesses are not yet visible
5054         vk::VkAccessFlags                               m_invisibleOperations[PIPELINESTAGE_LAST];
5055
5056         // [dstStage] = srcStage
5057         // Memory operation in srcStage have not completed before dstStage
5058         vk::VkPipelineStageFlags                m_incompleteOperations[PIPELINESTAGE_LAST];
5059 };
5060
5061 CacheState::CacheState (vk::VkPipelineStageFlags allowedStages, vk::VkAccessFlags allowedAccesses)
5062         : m_allowedStages       (allowedStages)
5063         , m_allowedAccesses     (allowedAccesses)
5064 {
5065         for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
5066         {
5067                 const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
5068
5069                 if ((dstStage_ & m_allowedStages) == 0)
5070                         continue;
5071
5072                 // All operations are initially visible
5073                 m_invisibleOperations[dstStage] = 0;
5074
5075                 // There are no incomplete read operations initially
5076                 m_incompleteOperations[dstStage] = 0;
5077
5078                 // There are no incomplete layout transitions
5079                 m_unavailableLayoutTransition[dstStage] = false;
5080
5081                 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
5082                 {
5083                         const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
5084
5085                         if ((srcStage_ & m_allowedStages) == 0)
5086                                 continue;
5087
5088                         // There are no write operations that are not yet available
5089                         // initially.
5090                         m_unavailableWriteOperations[dstStage][srcStage] = 0;
5091                 }
5092         }
5093 }
5094
5095 bool CacheState::isValid (vk::VkPipelineStageFlagBits   stage,
5096                                                   vk::VkAccessFlagBits                  access) const
5097 {
5098         DE_ASSERT((access & (~m_allowedAccesses)) == 0);
5099         DE_ASSERT((stage & (~m_allowedStages)) == 0);
5100
5101         const PipelineStage     dstStage        = pipelineStageFlagToPipelineStage(stage);
5102
5103         // Previous operations are not visible to access on stage
5104         if (m_unavailableLayoutTransition[dstStage] || (m_invisibleOperations[dstStage] & access) != 0)
5105                 return false;
5106
5107         if (isWriteAccess(access))
5108         {
5109                 // Memory operations from other stages have not completed before
5110                 // dstStage
5111                 if (m_incompleteOperations[dstStage] != 0)
5112                         return false;
5113         }
5114
5115         return true;
5116 }
5117
5118 void CacheState::perform (vk::VkPipelineStageFlagBits   stage,
5119                                                   vk::VkAccessFlagBits                  access)
5120 {
5121         DE_ASSERT((access & (~m_allowedAccesses)) == 0);
5122         DE_ASSERT((stage & (~m_allowedStages)) == 0);
5123
5124         const PipelineStage srcStage = pipelineStageFlagToPipelineStage(stage);
5125
5126         for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
5127         {
5128                 const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
5129
5130                 if ((dstStage_ & m_allowedStages) == 0)
5131                         continue;
5132
5133                 // Mark stage as incomplete for all stages
5134                 m_incompleteOperations[dstStage] |= stage;
5135
5136                 if (isWriteAccess(access))
5137                 {
5138                         // Mark all accesses from all stages invisible
5139                         m_invisibleOperations[dstStage] |= m_allowedAccesses;
5140
5141                         // Mark write access from srcStage unavailable to all stages
5142                         m_unavailableWriteOperations[dstStage][srcStage] |= access;
5143                 }
5144         }
5145 }
5146
5147 void CacheState::submitCommandBuffer (void)
5148 {
5149         // Flush all host writes and reads
5150         barrier(m_allowedStages & vk::VK_PIPELINE_STAGE_HOST_BIT,
5151                         m_allowedAccesses & (vk::VK_ACCESS_HOST_READ_BIT | vk::VK_ACCESS_HOST_WRITE_BIT),
5152                         m_allowedStages,
5153                         m_allowedAccesses);
5154 }
5155
5156 void CacheState::waitForIdle (void)
5157 {
5158         // Make all writes available
5159         barrier(m_allowedStages,
5160                         m_allowedAccesses & getWriteAccessFlags(),
5161                         m_allowedStages,
5162                         0);
5163
5164         // Make all writes visible on device side
5165         barrier(m_allowedStages,
5166                         0,
5167                         m_allowedStages & (~vk::VK_PIPELINE_STAGE_HOST_BIT),
5168                         m_allowedAccesses);
5169 }
5170
5171 void CacheState::getFullBarrier (vk::VkPipelineStageFlags&      srcStages,
5172                                                                  vk::VkAccessFlags&                     srcAccesses,
5173                                                                  vk::VkPipelineStageFlags&      dstStages,
5174                                                                  vk::VkAccessFlags&                     dstAccesses) const
5175 {
5176         srcStages       = 0;
5177         srcAccesses     = 0;
5178         dstStages       = 0;
5179         dstAccesses     = 0;
5180
5181         for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
5182         {
5183                 const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
5184
5185                 if ((dstStage_ & m_allowedStages) == 0)
5186                         continue;
5187
5188                 // Make sure all previous operation are complete in all stages
5189                 if (m_incompleteOperations[dstStage])
5190                 {
5191                         dstStages |= dstStage_;
5192                         srcStages |= m_incompleteOperations[dstStage];
5193                 }
5194
5195                 // Make sure all read operations are visible in dstStage
5196                 if (m_invisibleOperations[dstStage])
5197                 {
5198                         dstStages |= dstStage_;
5199                         dstAccesses |= m_invisibleOperations[dstStage];
5200                 }
5201
5202                 // Make sure all write operations fro mall stages are available
5203                 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
5204                 {
5205                         const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
5206
5207                         if ((srcStage_ & m_allowedStages) == 0)
5208                                 continue;
5209
5210                         if (m_unavailableWriteOperations[dstStage][srcStage])
5211                         {
5212                                 dstStages |= dstStage_;
5213                                 srcStages |= dstStage_;
5214                                 srcAccesses |= m_unavailableWriteOperations[dstStage][srcStage];
5215                         }
5216
5217                         if (m_unavailableLayoutTransition[dstStage] && !m_unavailableLayoutTransition[srcStage])
5218                         {
5219                                 // Add dependency between srcStage and dstStage if layout transition has not completed in dstStage,
5220                                 // but has completed in srcStage.
5221                                 dstStages |= dstStage_;
5222                                 srcStages |= dstStage_;
5223                         }
5224                 }
5225         }
5226
5227         DE_ASSERT((srcStages & (~m_allowedStages)) == 0);
5228         DE_ASSERT((srcAccesses & (~m_allowedAccesses)) == 0);
5229         DE_ASSERT((dstStages & (~m_allowedStages)) == 0);
5230         DE_ASSERT((dstAccesses & (~m_allowedAccesses)) == 0);
5231 }
5232
5233 void CacheState::checkImageLayoutBarrier (vk::VkPipelineStageFlags      srcStages,
5234                                                                                  vk::VkAccessFlags                      srcAccesses,
5235                                                                                  vk::VkPipelineStageFlags       dstStages,
5236                                                                                  vk::VkAccessFlags                      dstAccesses)
5237 {
5238         DE_ASSERT((srcStages & (~m_allowedStages)) == 0);
5239         DE_ASSERT((srcAccesses & (~m_allowedAccesses)) == 0);
5240         DE_ASSERT((dstStages & (~m_allowedStages)) == 0);
5241         DE_ASSERT((dstAccesses & (~m_allowedAccesses)) == 0);
5242
5243         DE_UNREF(srcStages);
5244         DE_UNREF(srcAccesses);
5245
5246         DE_UNREF(dstStages);
5247         DE_UNREF(dstAccesses);
5248
5249 #if defined(DE_DEBUG)
5250         // Check that all stages have completed before srcStages or are in srcStages.
5251         {
5252                 vk::VkPipelineStageFlags completedStages = srcStages;
5253
5254                 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= srcStages; srcStage_ <<= 1)
5255                 {
5256                         const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
5257
5258                         if ((srcStage_ & srcStages) == 0)
5259                                 continue;
5260
5261                         completedStages |= (~m_incompleteOperations[srcStage]);
5262                 }
5263
5264                 DE_ASSERT((completedStages & m_allowedStages) == m_allowedStages);
5265         }
5266
5267         // Check that any write is available at least in one stage. Since all stages are complete even single flush is enough.
5268         if ((getWriteAccessFlags() & m_allowedAccesses) != 0 && (srcAccesses & getWriteAccessFlags()) == 0)
5269         {
5270                 bool anyWriteAvailable = false;
5271
5272                 for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
5273                 {
5274                         const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
5275
5276                         if ((dstStage_ & m_allowedStages) == 0)
5277                                 continue;
5278
5279                         for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
5280                         {
5281                                 const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
5282
5283                                 if ((srcStage_ & m_allowedStages) == 0)
5284                                         continue;
5285
5286                                 if (m_unavailableWriteOperations[dstStage][srcStage] != (getWriteAccessFlags() & m_allowedAccesses))
5287                                 {
5288                                         anyWriteAvailable = true;
5289                                         break;
5290                                 }
5291                         }
5292                 }
5293
5294                 DE_ASSERT(anyWriteAvailable);
5295         }
5296 #endif
5297 }
5298
5299 void CacheState::imageLayoutBarrier (vk::VkPipelineStageFlags   srcStages,
5300                                                                          vk::VkAccessFlags                      srcAccesses,
5301                                                                          vk::VkPipelineStageFlags       dstStages,
5302                                                                          vk::VkAccessFlags                      dstAccesses)
5303 {
5304         checkImageLayoutBarrier(srcStages, srcAccesses, dstStages, dstAccesses);
5305
5306         for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
5307         {
5308                 const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
5309
5310                 if ((dstStage_ & m_allowedStages) == 0)
5311                         continue;
5312
5313                 // All stages are incomplete after the barrier except each dstStage in it self.
5314                 m_incompleteOperations[dstStage] = m_allowedStages & (~dstStage_);
5315
5316                 // All memory operations are invisible unless they are listed in dstAccess
5317                 m_invisibleOperations[dstStage] = m_allowedAccesses & (~dstAccesses);
5318
5319                 // Layout transition is unavailable in stage unless it was listed in dstStages
5320                 m_unavailableLayoutTransition[dstStage]= (dstStage_ & dstStages) == 0;
5321
5322                 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
5323                 {
5324                         const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
5325
5326                         if ((srcStage_ & m_allowedStages) == 0)
5327                                 continue;
5328
5329                         // All write operations are available after layout transition
5330                         m_unavailableWriteOperations[dstStage][srcStage] = 0;
5331                 }
5332         }
5333 }
5334
5335 void CacheState::barrier (vk::VkPipelineStageFlags      srcStages,
5336                                                   vk::VkAccessFlags                     srcAccesses,
5337                                                   vk::VkPipelineStageFlags      dstStages,
5338                                                   vk::VkAccessFlags                     dstAccesses)
5339 {
5340         DE_ASSERT((srcStages & (~m_allowedStages)) == 0);
5341         DE_ASSERT((srcAccesses & (~m_allowedAccesses)) == 0);
5342         DE_ASSERT((dstStages & (~m_allowedStages)) == 0);
5343         DE_ASSERT((dstAccesses & (~m_allowedAccesses)) == 0);
5344
5345         // Transitivity
5346         {
5347                 vk::VkPipelineStageFlags                oldIncompleteOperations[PIPELINESTAGE_LAST];
5348                 vk::VkAccessFlags                               oldUnavailableWriteOperations[PIPELINESTAGE_LAST][PIPELINESTAGE_LAST];
5349                 bool                                                    oldUnavailableLayoutTransition[PIPELINESTAGE_LAST];
5350
5351                 deMemcpy(oldIncompleteOperations, m_incompleteOperations, sizeof(oldIncompleteOperations));
5352                 deMemcpy(oldUnavailableWriteOperations, m_unavailableWriteOperations, sizeof(oldUnavailableWriteOperations));
5353                 deMemcpy(oldUnavailableLayoutTransition, m_unavailableLayoutTransition, sizeof(oldUnavailableLayoutTransition));
5354
5355                 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= srcStages; srcStage_ <<= 1)
5356                 {
5357                         const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
5358
5359                         if ((srcStage_ & srcStages) == 0)
5360                                 continue;
5361
5362                         for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= dstStages; dstStage_ <<= 1)
5363                         {
5364                                 const PipelineStage     dstStage                        = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
5365
5366                                 if ((dstStage_ & dstStages) == 0)
5367                                         continue;
5368
5369                                 // Stages that have completed before srcStage have also completed before dstStage
5370                                 m_incompleteOperations[dstStage] &= oldIncompleteOperations[srcStage];
5371
5372                                 // Image layout transition in srcStage are now available in dstStage
5373                                 m_unavailableLayoutTransition[dstStage] &= oldUnavailableLayoutTransition[srcStage];
5374
5375                                 for (vk::VkPipelineStageFlags sharedStage_ = 1; sharedStage_ <= m_allowedStages; sharedStage_ <<= 1)
5376                                 {
5377                                         const PipelineStage     sharedStage                     = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)sharedStage_);
5378
5379                                         if ((sharedStage_ & m_allowedStages) == 0)
5380                                                 continue;
5381
5382                                         // Writes that are available in srcStage are also available in dstStage
5383                                         m_unavailableWriteOperations[dstStage][sharedStage] &= oldUnavailableWriteOperations[srcStage][sharedStage];
5384                                 }
5385                         }
5386                 }
5387         }
5388
5389         // Barrier
5390         for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= dstStages; dstStage_ <<= 1)
5391         {
5392                 const PipelineStage     dstStage                        = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
5393                 bool                            allWritesAvailable      = true;
5394
5395                 if ((dstStage_ & dstStages) == 0)
5396                         continue;
5397
5398                 // Operations in srcStages have completed before any stage in dstStages
5399                 m_incompleteOperations[dstStage] &= ~srcStages;
5400
5401                 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
5402                 {
5403                         const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
5404
5405                         if ((srcStage_ & m_allowedStages) == 0)
5406                                 continue;
5407
5408                         // Make srcAccesses from srcStage available in dstStage
5409                         if ((srcStage_ & srcStages) != 0)
5410                                 m_unavailableWriteOperations[dstStage][srcStage] &= ~srcAccesses;
5411
5412                         if (m_unavailableWriteOperations[dstStage][srcStage] != 0)
5413                                 allWritesAvailable = false;
5414                 }
5415
5416                 // If all writes are available in dstStage make dstAccesses also visible
5417                 if (allWritesAvailable)
5418                         m_invisibleOperations[dstStage] &= ~dstAccesses;
5419         }
5420 }
5421
5422 bool CacheState::isClean (void) const
5423 {
5424         for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
5425         {
5426                 const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
5427
5428                 if ((dstStage_ & m_allowedStages) == 0)
5429                         continue;
5430
5431                 // Some operations are not visible to some stages
5432                 if (m_invisibleOperations[dstStage] != 0)
5433                         return false;
5434
5435                 // There are operation that have not completed yet
5436                 if (m_incompleteOperations[dstStage] != 0)
5437                         return false;
5438
5439                 // Layout transition has not completed yet
5440                 if (m_unavailableLayoutTransition[dstStage])
5441                         return false;
5442
5443                 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
5444                 {
5445                         const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
5446
5447                         if ((srcStage_ & m_allowedStages) == 0)
5448                                 continue;
5449
5450                         // Some write operations are not available yet
5451                         if (m_unavailableWriteOperations[dstStage][srcStage] != 0)
5452                                 return false;
5453                 }
5454         }
5455
5456         return true;
5457 }
5458
5459 struct State
5460 {
5461         State (Usage usage, deUint32 seed)
5462                 : stage                                 (STAGE_HOST)
5463                 , cache                                 (usageToStageFlags(usage), usageToAccessFlags(usage))
5464                 , rng                                   (seed)
5465                 , mapped                                (false)
5466                 , hostInvalidated               (true)
5467                 , hostFlushed                   (true)
5468                 , memoryDefined                 (false)
5469                 , hasBuffer                             (false)
5470                 , hasBoundBufferMemory  (false)
5471                 , hasImage                              (false)
5472                 , hasBoundImageMemory   (false)
5473                 , imageLayout                   (vk::VK_IMAGE_LAYOUT_UNDEFINED)
5474                 , imageDefined                  (false)
5475                 , queueIdle                             (true)
5476                 , deviceIdle                    (true)
5477                 , commandBufferIsEmpty  (true)
5478         {
5479         }
5480
5481         Stage                           stage;
5482         CacheState                      cache;
5483         de::Random                      rng;
5484
5485         bool                            mapped;
5486         bool                            hostInvalidated;
5487         bool                            hostFlushed;
5488         bool                            memoryDefined;
5489
5490         bool                            hasBuffer;
5491         bool                            hasBoundBufferMemory;
5492
5493         bool                            hasImage;
5494         bool                            hasBoundImageMemory;
5495         vk::VkImageLayout       imageLayout;
5496         bool                            imageDefined;
5497
5498         bool                            queueIdle;
5499         bool                            deviceIdle;
5500
5501         bool                            commandBufferIsEmpty;
5502 };
5503
5504 void getAvailableOps (const State& state, bool supportsBuffers, bool supportsImages, Usage usage, vector<Op>& ops)
5505 {
5506         if (state.stage == STAGE_HOST)
5507         {
5508                 if (usage & (USAGE_HOST_READ | USAGE_HOST_WRITE))
5509                 {
5510                         // Host memory operations
5511                         if (state.mapped)
5512                         {
5513                                 ops.push_back(OP_UNMAP);
5514
5515                                 // Avoid flush and finish if they are not needed
5516                                 if (!state.hostFlushed)
5517                                         ops.push_back(OP_MAP_FLUSH);
5518
5519                                 if (!state.hostInvalidated
5520                                         && state.queueIdle
5521                                         && ((usage & USAGE_HOST_READ) == 0
5522                                                 || state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_READ_BIT))
5523                                         && ((usage & USAGE_HOST_WRITE) == 0
5524                                                 || state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_WRITE_BIT)))
5525                                 {
5526                                         ops.push_back(OP_MAP_INVALIDATE);
5527                                 }
5528
5529                                 if (usage & USAGE_HOST_READ
5530                                         && usage & USAGE_HOST_WRITE
5531                                         && state.memoryDefined
5532                                         && state.hostInvalidated
5533                                         && state.queueIdle
5534                                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_WRITE_BIT)
5535                                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_READ_BIT))
5536                                 {
5537                                         ops.push_back(OP_MAP_MODIFY);
5538                                 }
5539
5540                                 if (usage & USAGE_HOST_READ
5541                                         && state.memoryDefined
5542                                         && state.hostInvalidated
5543                                         && state.queueIdle
5544                                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_READ_BIT))
5545                                 {
5546                                         ops.push_back(OP_MAP_READ);
5547                                 }
5548
5549                                 if (usage & USAGE_HOST_WRITE
5550                                         && state.hostInvalidated
5551                                         && state.queueIdle
5552                                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_WRITE_BIT))
5553                                 {
5554                                         ops.push_back(OP_MAP_WRITE);
5555                                 }
5556                         }
5557                         else
5558                                 ops.push_back(OP_MAP);
5559                 }
5560
5561                 if (state.hasBoundBufferMemory && state.queueIdle)
5562                 {
5563                         // \note Destroy only buffers after they have been bound
5564                         ops.push_back(OP_BUFFER_DESTROY);
5565                 }
5566                 else
5567                 {
5568                         if (state.hasBuffer)
5569                         {
5570                                 if (!state.hasBoundBufferMemory)
5571                                         ops.push_back(OP_BUFFER_BINDMEMORY);
5572                         }
5573                         else if (!state.hasImage && supportsBuffers)    // Avoid creating buffer if there is already image
5574                                 ops.push_back(OP_BUFFER_CREATE);
5575                 }
5576
5577                 if (state.hasBoundImageMemory && state.queueIdle)
5578                 {
5579                         // \note Destroy only image after they have been bound
5580                         ops.push_back(OP_IMAGE_DESTROY);
5581                 }
5582                 else
5583                 {
5584                         if (state.hasImage)
5585                         {
5586                                 if (!state.hasBoundImageMemory)
5587                                         ops.push_back(OP_IMAGE_BINDMEMORY);
5588                         }
5589                         else if (!state.hasBuffer && supportsImages)    // Avoid creating image if there is already buffer
5590                                 ops.push_back(OP_IMAGE_CREATE);
5591                 }
5592
5593                 // Host writes must be flushed before GPU commands and there must be
5594                 // buffer or image for GPU commands
5595                 if (state.hostFlushed
5596                         && (state.memoryDefined || supportsDeviceBufferWrites(usage) || state.imageDefined || supportsDeviceImageWrites(usage))
5597                         && (state.hasBoundBufferMemory || state.hasBoundImageMemory) // Avoid command buffers if there is no object to use
5598                         && (usageToStageFlags(usage) & (~vk::VK_PIPELINE_STAGE_HOST_BIT)) != 0) // Don't start command buffer if there are no ways to use memory from gpu
5599                 {
5600                         ops.push_back(OP_COMMAND_BUFFER_BEGIN);
5601                 }
5602
5603                 if (!state.deviceIdle)
5604                         ops.push_back(OP_DEVICE_WAIT_FOR_IDLE);
5605
5606                 if (!state.queueIdle)
5607                         ops.push_back(OP_QUEUE_WAIT_FOR_IDLE);
5608         }
5609         else if (state.stage == STAGE_COMMAND_BUFFER)
5610         {
5611                 if (!state.cache.isClean())
5612                 {
5613                         ops.push_back(OP_PIPELINE_BARRIER_GLOBAL);
5614
5615                         if (state.hasImage)
5616                                 ops.push_back(OP_PIPELINE_BARRIER_IMAGE);
5617
5618                         if (state.hasBuffer)
5619                                 ops.push_back(OP_PIPELINE_BARRIER_BUFFER);
5620                 }
5621
5622                 if (state.hasBoundBufferMemory)
5623                 {
5624                         if (usage & USAGE_TRANSFER_DST
5625                                 && state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT))
5626                         {
5627                                 ops.push_back(OP_BUFFER_FILL);
5628                                 ops.push_back(OP_BUFFER_UPDATE);
5629                                 ops.push_back(OP_BUFFER_COPY_FROM_BUFFER);
5630                                 ops.push_back(OP_BUFFER_COPY_FROM_IMAGE);
5631                         }
5632
5633                         if (usage & USAGE_TRANSFER_SRC
5634                                 && state.memoryDefined
5635                                 && state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT))
5636                         {
5637                                 ops.push_back(OP_BUFFER_COPY_TO_BUFFER);
5638                                 ops.push_back(OP_BUFFER_COPY_TO_IMAGE);
5639                         }
5640                 }
5641
5642                 if (state.hasBoundImageMemory)
5643                 {
5644                         ops.push_back(OP_IMAGE_TRANSITION_LAYOUT);
5645
5646                         {
5647                                 if (usage & USAGE_TRANSFER_DST
5648                                         && (state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL
5649                                                 || state.imageLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
5650                                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT))
5651                                 {
5652                                         ops.push_back(OP_IMAGE_COPY_FROM_BUFFER);
5653                                         ops.push_back(OP_IMAGE_COPY_FROM_IMAGE);
5654                                         ops.push_back(OP_IMAGE_BLIT_FROM_IMAGE);
5655                                 }
5656
5657                                 if (usage & USAGE_TRANSFER_SRC
5658                                         && (state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL
5659                                                 || state.imageLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
5660                                         && state.imageDefined
5661                                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT))
5662                                 {
5663                                         ops.push_back(OP_IMAGE_COPY_TO_BUFFER);
5664                                         ops.push_back(OP_IMAGE_COPY_TO_IMAGE);
5665                                         ops.push_back(OP_IMAGE_BLIT_TO_IMAGE);
5666                                 }
5667                         }
5668                 }
5669
5670                 // \todo [2016-03-09 mika] Add other usages?
5671                 if (((usage & USAGE_VERTEX_BUFFER) && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT))
5672                         || ((usage & USAGE_INDEX_BUFFER) && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_INDEX_READ_BIT)))
5673                         ops.push_back(OP_RENDERPASS_BEGIN);
5674
5675                 // \note This depends on previous operations and has to be always the
5676                 // last command buffer operation check
5677                 if (ops.empty() || !state.commandBufferIsEmpty)
5678                         ops.push_back(OP_COMMAND_BUFFER_END);
5679         }
5680         else if (state.stage == STAGE_RENDER_PASS)
5681         {
5682                 if (usage & USAGE_VERTEX_BUFFER
5683                         && state.memoryDefined
5684                         && state.hasBoundBufferMemory
5685                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT))
5686                 {
5687                         ops.push_back(OP_RENDER_VERTEX_BUFFER);
5688                 }
5689
5690                 if (usage & USAGE_INDEX_BUFFER
5691                         && state.memoryDefined
5692                         && state.hasBoundBufferMemory
5693                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_INDEX_READ_BIT))
5694                 {
5695                         ops.push_back(OP_RENDER_INDEX_BUFFER);
5696                 }
5697
5698                 ops.push_back(OP_RENDERPASS_END);
5699         }
5700         else
5701                 DE_FATAL("Unknown stage");
5702 }
5703
5704 bool layoutSupportedByUsage (Usage usage, vk::VkImageLayout layout)
5705 {
5706         switch (layout)
5707         {
5708                 case vk::VK_IMAGE_LAYOUT_GENERAL:
5709                         return true;
5710
5711                 case vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
5712                         return (usage & USAGE_COLOR_ATTACHMENT) != 0;
5713
5714                 case vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
5715                         return (usage & USAGE_DEPTH_STENCIL_ATTACHMENT) != 0;
5716
5717                 case vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
5718                         return (usage & USAGE_DEPTH_STENCIL_ATTACHMENT) != 0;
5719
5720                 case vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
5721                         // \todo [2016-03-09 mika] Should include input attachment
5722                         return (usage & USAGE_TEXTURE_SAMPLED) != 0;
5723
5724                 case vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
5725                         return (usage & USAGE_TRANSFER_SRC) != 0;
5726
5727                 case vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
5728                         return (usage & USAGE_TRANSFER_DST) != 0;
5729
5730                 case vk::VK_IMAGE_LAYOUT_PREINITIALIZED:
5731                         return true;
5732
5733                 default:
5734                         DE_FATAL("Unknown layout");
5735                         return false;
5736         }
5737 }
5738
5739 vk::VkImageLayout getRandomNextLayout (de::Random&                      rng,
5740                                                                            Usage                                usage,
5741                                                                            vk::VkImageLayout    previousLayout)
5742 {
5743         const vk::VkImageLayout layouts[] =
5744         {
5745                 vk::VK_IMAGE_LAYOUT_GENERAL,
5746                 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
5747                 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
5748                 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
5749                 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
5750                 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
5751                 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
5752         };
5753         size_t possibleLayoutCount = 0;
5754
5755         for (size_t layoutNdx = 0; layoutNdx < DE_LENGTH_OF_ARRAY(layouts); layoutNdx++)
5756         {
5757                 const vk::VkImageLayout layout = layouts[layoutNdx];
5758
5759                 if (layoutSupportedByUsage(usage, layout) && layout != previousLayout)
5760                         possibleLayoutCount++;
5761         }
5762
5763         size_t nextLayoutNdx = ((size_t)rng.getUint64()) % possibleLayoutCount;
5764
5765         for (size_t layoutNdx = 0; layoutNdx < DE_LENGTH_OF_ARRAY(layouts); layoutNdx++)
5766         {
5767                 const vk::VkImageLayout layout = layouts[layoutNdx];
5768
5769                 if (layoutSupportedByUsage(usage, layout) && layout != previousLayout)
5770                 {
5771                         if (nextLayoutNdx == 0)
5772                                 return layout;
5773                         else
5774                                 nextLayoutNdx--;
5775                 }
5776         }
5777
5778         DE_FATAL("Unreachable");
5779         return vk::VK_IMAGE_LAYOUT_UNDEFINED;
5780 }
5781
5782 void applyOp (State& state, const Memory& memory, Op op, Usage usage)
5783 {
5784         switch (op)
5785         {
5786                 case OP_MAP:
5787                         DE_ASSERT(state.stage == STAGE_HOST);
5788                         DE_ASSERT(!state.mapped);
5789                         state.mapped = true;
5790                         break;
5791
5792                 case OP_UNMAP:
5793                         DE_ASSERT(state.stage == STAGE_HOST);
5794                         DE_ASSERT(state.mapped);
5795                         state.mapped = false;
5796                         break;
5797
5798                 case OP_MAP_FLUSH:
5799                         DE_ASSERT(state.stage == STAGE_HOST);
5800                         DE_ASSERT(!state.hostFlushed);
5801                         state.hostFlushed = true;
5802                         break;
5803
5804                 case OP_MAP_INVALIDATE:
5805                         DE_ASSERT(state.stage == STAGE_HOST);
5806                         DE_ASSERT(!state.hostInvalidated);
5807                         state.hostInvalidated = true;
5808                         break;
5809
5810                 case OP_MAP_READ:
5811                         DE_ASSERT(state.stage == STAGE_HOST);
5812                         DE_ASSERT(state.hostInvalidated);
5813                         state.rng.getUint32();
5814                         break;
5815
5816                 case OP_MAP_WRITE:
5817                         DE_ASSERT(state.stage == STAGE_HOST);
5818                         if ((memory.getMemoryType().propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
5819                                 state.hostFlushed = false;
5820
5821                         state.memoryDefined = true;
5822                         state.imageDefined = false;
5823                         state.imageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
5824                         state.rng.getUint32();
5825                         break;
5826
5827                 case OP_MAP_MODIFY:
5828                         DE_ASSERT(state.stage == STAGE_HOST);
5829                         DE_ASSERT(state.hostInvalidated);
5830
5831                         if ((memory.getMemoryType().propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
5832                                 state.hostFlushed = false;
5833
5834                         state.rng.getUint32();
5835                         break;
5836
5837                 case OP_BUFFER_CREATE:
5838                         DE_ASSERT(state.stage == STAGE_HOST);
5839                         DE_ASSERT(!state.hasBuffer);
5840
5841                         state.hasBuffer = true;
5842                         break;
5843
5844                 case OP_BUFFER_DESTROY:
5845                         DE_ASSERT(state.stage == STAGE_HOST);
5846                         DE_ASSERT(state.hasBuffer);
5847                         DE_ASSERT(state.hasBoundBufferMemory);
5848
5849                         state.hasBuffer = false;
5850                         state.hasBoundBufferMemory = false;
5851                         break;
5852
5853                 case OP_BUFFER_BINDMEMORY:
5854                         DE_ASSERT(state.stage == STAGE_HOST);
5855                         DE_ASSERT(state.hasBuffer);
5856                         DE_ASSERT(!state.hasBoundBufferMemory);
5857
5858                         state.hasBoundBufferMemory = true;
5859                         break;
5860
5861                 case OP_IMAGE_CREATE:
5862                         DE_ASSERT(state.stage == STAGE_HOST);
5863                         DE_ASSERT(!state.hasImage);
5864                         DE_ASSERT(!state.hasBuffer);
5865
5866                         state.hasImage = true;
5867                         break;
5868
5869                 case OP_IMAGE_DESTROY:
5870                         DE_ASSERT(state.stage == STAGE_HOST);
5871                         DE_ASSERT(state.hasImage);
5872                         DE_ASSERT(state.hasBoundImageMemory);
5873
5874                         state.hasImage = false;
5875                         state.hasBoundImageMemory = false;
5876                         state.imageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
5877                         state.imageDefined = false;
5878                         break;
5879
5880                 case OP_IMAGE_BINDMEMORY:
5881                         DE_ASSERT(state.stage == STAGE_HOST);
5882                         DE_ASSERT(state.hasImage);
5883                         DE_ASSERT(!state.hasBoundImageMemory);
5884
5885                         state.hasBoundImageMemory = true;
5886                         break;
5887
5888                 case OP_IMAGE_TRANSITION_LAYOUT:
5889                 {
5890                         DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
5891                         DE_ASSERT(state.hasImage);
5892                         DE_ASSERT(state.hasBoundImageMemory);
5893
5894                         // \todo [2016-03-09 mika] Support linear tiling and predefined data
5895                         const vk::VkImageLayout         srcLayout       = state.rng.getFloat() < 0.9f ? state.imageLayout : vk::VK_IMAGE_LAYOUT_UNDEFINED;
5896                         const vk::VkImageLayout         dstLayout       = getRandomNextLayout(state.rng, usage, srcLayout);
5897
5898                         vk::VkPipelineStageFlags        dirtySrcStages;
5899                         vk::VkAccessFlags                       dirtySrcAccesses;
5900                         vk::VkPipelineStageFlags        dirtyDstStages;
5901                         vk::VkAccessFlags                       dirtyDstAccesses;
5902
5903                         vk::VkPipelineStageFlags        srcStages;
5904                         vk::VkAccessFlags                       srcAccesses;
5905                         vk::VkPipelineStageFlags        dstStages;
5906                         vk::VkAccessFlags                       dstAccesses;
5907
5908                         state.cache.getFullBarrier(dirtySrcStages, dirtySrcAccesses, dirtyDstStages, dirtyDstAccesses);
5909
5910                         // Try masking some random bits
5911                         srcStages       = dirtySrcStages;
5912                         srcAccesses     = dirtySrcAccesses;
5913
5914                         dstStages       = state.cache.getAllowedStages() & state.rng.getUint32();
5915                         dstAccesses     = state.cache.getAllowedAcceses() & state.rng.getUint32();
5916
5917                         // If there are no bits in dst stage mask use all stages
5918                         dstStages       = dstStages ? dstStages : state.cache.getAllowedStages();
5919
5920                         if (!srcStages)
5921                                 srcStages = dstStages;
5922
5923                         if (srcLayout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
5924                                 state.imageDefined = false;
5925
5926                         state.commandBufferIsEmpty = false;
5927                         state.imageLayout = dstLayout;
5928                         state.memoryDefined = false;
5929                         state.cache.imageLayoutBarrier(srcStages, srcAccesses, dstStages, dstAccesses);
5930                         break;
5931                 }
5932
5933                 case OP_QUEUE_WAIT_FOR_IDLE:
5934                         DE_ASSERT(state.stage == STAGE_HOST);
5935                         DE_ASSERT(!state.queueIdle);
5936
5937                         state.queueIdle = true;
5938
5939                         state.cache.waitForIdle();
5940                         break;
5941
5942                 case OP_DEVICE_WAIT_FOR_IDLE:
5943                         DE_ASSERT(state.stage == STAGE_HOST);
5944                         DE_ASSERT(!state.deviceIdle);
5945
5946                         state.queueIdle = true;
5947                         state.deviceIdle = true;
5948
5949                         state.cache.waitForIdle();
5950                         break;
5951
5952                 case OP_COMMAND_BUFFER_BEGIN:
5953                         DE_ASSERT(state.stage == STAGE_HOST);
5954                         state.stage = STAGE_COMMAND_BUFFER;
5955                         state.commandBufferIsEmpty = true;
5956                         // Makes host writes visible to command buffer
5957                         state.cache.submitCommandBuffer();
5958                         break;
5959
5960                 case OP_COMMAND_BUFFER_END:
5961                         DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
5962                         state.stage = STAGE_HOST;
5963                         state.queueIdle = false;
5964                         state.deviceIdle = false;
5965                         break;
5966
5967                 case OP_BUFFER_COPY_FROM_BUFFER:
5968                 case OP_BUFFER_COPY_FROM_IMAGE:
5969                 case OP_BUFFER_UPDATE:
5970                 case OP_BUFFER_FILL:
5971                         state.rng.getUint32();
5972                         DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
5973
5974                         if ((memory.getMemoryType().propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
5975                                 state.hostInvalidated = false;
5976
5977                         state.commandBufferIsEmpty = false;
5978                         state.memoryDefined = true;
5979                         state.imageDefined = false;
5980                         state.imageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
5981                         state.cache.perform(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT);
5982                         break;
5983
5984                 case OP_BUFFER_COPY_TO_BUFFER:
5985                 case OP_BUFFER_COPY_TO_IMAGE:
5986                         DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
5987
5988                         state.commandBufferIsEmpty = false;
5989                         state.cache.perform(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT);
5990                         break;
5991
5992                 case OP_IMAGE_BLIT_FROM_IMAGE:
5993                         state.rng.getBool();
5994                         // Fall through
5995                 case OP_IMAGE_COPY_FROM_BUFFER:
5996                 case OP_IMAGE_COPY_FROM_IMAGE:
5997                         state.rng.getUint32();
5998                         DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
5999
6000                         if ((memory.getMemoryType().propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
6001                                 state.hostInvalidated = false;
6002
6003                         state.commandBufferIsEmpty = false;
6004                         state.memoryDefined = false;
6005                         state.imageDefined = true;
6006                         state.cache.perform(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT);
6007                         break;
6008
6009                 case OP_IMAGE_BLIT_TO_IMAGE:
6010                         state.rng.getBool();
6011                         // Fall through
6012                 case OP_IMAGE_COPY_TO_BUFFER:
6013                 case OP_IMAGE_COPY_TO_IMAGE:
6014                         DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
6015
6016                         state.commandBufferIsEmpty = false;
6017                         state.cache.perform(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT);
6018                         break;
6019
6020                 case OP_PIPELINE_BARRIER_GLOBAL:
6021                 case OP_PIPELINE_BARRIER_BUFFER:
6022                 case OP_PIPELINE_BARRIER_IMAGE:
6023                 {
6024                         DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
6025
6026                         vk::VkPipelineStageFlags        dirtySrcStages;
6027                         vk::VkAccessFlags                       dirtySrcAccesses;
6028                         vk::VkPipelineStageFlags        dirtyDstStages;
6029                         vk::VkAccessFlags                       dirtyDstAccesses;
6030
6031                         vk::VkPipelineStageFlags        srcStages;
6032                         vk::VkAccessFlags                       srcAccesses;
6033                         vk::VkPipelineStageFlags        dstStages;
6034                         vk::VkAccessFlags                       dstAccesses;
6035
6036                         state.cache.getFullBarrier(dirtySrcStages, dirtySrcAccesses, dirtyDstStages, dirtyDstAccesses);
6037
6038                         // Try masking some random bits
6039                         srcStages       = dirtySrcStages & state.rng.getUint32();
6040                         srcAccesses     = dirtySrcAccesses & state.rng.getUint32();
6041
6042                         dstStages       = dirtyDstStages & state.rng.getUint32();
6043                         dstAccesses     = dirtyDstAccesses & state.rng.getUint32();
6044
6045                         // If there are no bits in stage mask use the original dirty stages
6046                         srcStages       = srcStages ? srcStages : dirtySrcStages;
6047                         dstStages       = dstStages ? dstStages : dirtyDstStages;
6048
6049                         if (!srcStages)
6050                                 srcStages = dstStages;
6051
6052                         state.commandBufferIsEmpty = false;
6053                         state.cache.barrier(srcStages, srcAccesses, dstStages, dstAccesses);
6054                         break;
6055                 }
6056
6057                 case OP_RENDERPASS_BEGIN:
6058                 {
6059                         DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
6060
6061                         state.stage = STAGE_RENDER_PASS;
6062                         break;
6063                 }
6064
6065                 case OP_RENDERPASS_END:
6066                 {
6067                         DE_ASSERT(state.stage == STAGE_RENDER_PASS);
6068
6069                         state.stage = STAGE_COMMAND_BUFFER;
6070                         break;
6071                 }
6072
6073                 case OP_RENDER_VERTEX_BUFFER:
6074                 {
6075                         DE_ASSERT(state.stage == STAGE_RENDER_PASS);
6076
6077                         state.cache.perform(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT);
6078                         break;
6079                 }
6080
6081                 case OP_RENDER_INDEX_BUFFER:
6082                 {
6083                         DE_ASSERT(state.stage == STAGE_RENDER_PASS);
6084
6085                         state.cache.perform(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_INDEX_READ_BIT);
6086                         break;
6087                 }
6088
6089                 default:
6090                         DE_FATAL("Unknown op");
6091         }
6092 }
6093
6094 de::MovePtr<Command> createHostCommand (Op                                      op,
6095                                                                                 de::Random&                     rng,
6096                                                                                 Usage                           usage,
6097                                                                                 vk::VkSharingMode       sharing)
6098 {
6099         switch (op)
6100         {
6101                 case OP_MAP:                                    return de::MovePtr<Command>(new Map());
6102                 case OP_UNMAP:                                  return de::MovePtr<Command>(new UnMap());
6103
6104                 case OP_MAP_FLUSH:                              return de::MovePtr<Command>(new Flush());
6105                 case OP_MAP_INVALIDATE:                 return de::MovePtr<Command>(new Invalidate());
6106
6107                 case OP_MAP_READ:                               return de::MovePtr<Command>(new HostMemoryAccess(true, false, rng.getUint32()));
6108                 case OP_MAP_WRITE:                              return de::MovePtr<Command>(new HostMemoryAccess(false, true, rng.getUint32()));
6109                 case OP_MAP_MODIFY:                             return de::MovePtr<Command>(new HostMemoryAccess(true, true, rng.getUint32()));
6110
6111                 case OP_BUFFER_CREATE:                  return de::MovePtr<Command>(new CreateBuffer(usageToBufferUsageFlags(usage), sharing));
6112                 case OP_BUFFER_DESTROY:                 return de::MovePtr<Command>(new DestroyBuffer());
6113                 case OP_BUFFER_BINDMEMORY:              return de::MovePtr<Command>(new BindBufferMemory());
6114
6115                 case OP_IMAGE_CREATE:                   return de::MovePtr<Command>(new CreateImage(usageToImageUsageFlags(usage), sharing));
6116                 case OP_IMAGE_DESTROY:                  return de::MovePtr<Command>(new DestroyImage());
6117                 case OP_IMAGE_BINDMEMORY:               return de::MovePtr<Command>(new BindImageMemory());
6118
6119                 case OP_QUEUE_WAIT_FOR_IDLE:    return de::MovePtr<Command>(new QueueWaitIdle());
6120                 case OP_DEVICE_WAIT_FOR_IDLE:   return de::MovePtr<Command>(new DeviceWaitIdle());
6121
6122                 default:
6123                         DE_FATAL("Unknown op");
6124                         return de::MovePtr<Command>(DE_NULL);
6125         }
6126 }
6127
6128 de::MovePtr<CmdCommand> createCmdCommand (de::Random&   rng,
6129                                                                                   const State&  state,
6130                                                                                   Op                    op,
6131                                                                                   Usage                 usage)
6132 {
6133         switch (op)
6134         {
6135                 case OP_BUFFER_FILL:                                    return de::MovePtr<CmdCommand>(new FillBuffer(rng.getUint32()));
6136                 case OP_BUFFER_UPDATE:                                  return de::MovePtr<CmdCommand>(new UpdateBuffer(rng.getUint32()));
6137                 case OP_BUFFER_COPY_TO_BUFFER:                  return de::MovePtr<CmdCommand>(new BufferCopyToBuffer());
6138                 case OP_BUFFER_COPY_FROM_BUFFER:                return de::MovePtr<CmdCommand>(new BufferCopyFromBuffer(rng.getUint32()));
6139
6140                 case OP_BUFFER_COPY_TO_IMAGE:                   return de::MovePtr<CmdCommand>(new BufferCopyToImage());
6141                 case OP_BUFFER_COPY_FROM_IMAGE:                 return de::MovePtr<CmdCommand>(new BufferCopyFromImage(rng.getUint32()));
6142
6143                 case OP_IMAGE_TRANSITION_LAYOUT:
6144                 {
6145                         DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
6146                         DE_ASSERT(state.hasImage);
6147                         DE_ASSERT(state.hasBoundImageMemory);
6148
6149                         const vk::VkImageLayout         srcLayout       = rng.getFloat() < 0.9f ? state.imageLayout : vk::VK_IMAGE_LAYOUT_UNDEFINED;
6150                         const vk::VkImageLayout         dstLayout       = getRandomNextLayout(rng, usage, srcLayout);
6151
6152                         vk::VkPipelineStageFlags        dirtySrcStages;
6153                         vk::VkAccessFlags                       dirtySrcAccesses;
6154                         vk::VkPipelineStageFlags        dirtyDstStages;
6155                         vk::VkAccessFlags                       dirtyDstAccesses;
6156
6157                         vk::VkPipelineStageFlags        srcStages;
6158                         vk::VkAccessFlags                       srcAccesses;
6159                         vk::VkPipelineStageFlags        dstStages;
6160                         vk::VkAccessFlags                       dstAccesses;
6161
6162                         state.cache.getFullBarrier(dirtySrcStages, dirtySrcAccesses, dirtyDstStages, dirtyDstAccesses);
6163
6164                         // Try masking some random bits
6165                         srcStages       = dirtySrcStages;
6166                         srcAccesses     = dirtySrcAccesses;
6167
6168                         dstStages       = state.cache.getAllowedStages() & rng.getUint32();
6169                         dstAccesses     = state.cache.getAllowedAcceses() & rng.getUint32();
6170
6171                         // If there are no bits in dst stage mask use all stages
6172                         dstStages       = dstStages ? dstStages : state.cache.getAllowedStages();
6173
6174                         if (!srcStages)
6175                                 srcStages = dstStages;
6176
6177                         return de::MovePtr<CmdCommand>(new ImageTransition(srcStages, srcAccesses, dstStages, dstAccesses, srcLayout, dstLayout));
6178                 }
6179
6180                 case OP_IMAGE_COPY_TO_BUFFER:                   return de::MovePtr<CmdCommand>(new ImageCopyToBuffer());
6181                 case OP_IMAGE_COPY_FROM_BUFFER:                 return de::MovePtr<CmdCommand>(new ImageCopyFromBuffer(rng.getUint32()));
6182                 case OP_IMAGE_COPY_TO_IMAGE:                    return de::MovePtr<CmdCommand>(new ImageCopyToImage());
6183                 case OP_IMAGE_COPY_FROM_IMAGE:                  return de::MovePtr<CmdCommand>(new ImageCopyFromImage(rng.getUint32()));
6184                 case OP_IMAGE_BLIT_TO_IMAGE:
6185                 {
6186                         const BlitScale scale = rng.getBool() ? BLIT_SCALE_20 : BLIT_SCALE_10;
6187                         return de::MovePtr<CmdCommand>(new ImageBlitToImage(scale));
6188                 }
6189
6190                 case OP_IMAGE_BLIT_FROM_IMAGE:
6191                 {
6192                         const BlitScale scale = rng.getBool() ? BLIT_SCALE_20 : BLIT_SCALE_10;
6193                         return de::MovePtr<CmdCommand>(new ImageBlitFromImage(rng.getUint32(), scale));
6194                 }
6195
6196                 case OP_PIPELINE_BARRIER_GLOBAL:
6197                 case OP_PIPELINE_BARRIER_BUFFER:
6198                 case OP_PIPELINE_BARRIER_IMAGE:
6199                 {
6200                         vk::VkPipelineStageFlags        dirtySrcStages;
6201                         vk::VkAccessFlags                       dirtySrcAccesses;
6202                         vk::VkPipelineStageFlags        dirtyDstStages;
6203                         vk::VkAccessFlags                       dirtyDstAccesses;
6204
6205                         vk::VkPipelineStageFlags        srcStages;
6206                         vk::VkAccessFlags                       srcAccesses;
6207                         vk::VkPipelineStageFlags        dstStages;
6208                         vk::VkAccessFlags                       dstAccesses;
6209
6210                         state.cache.getFullBarrier(dirtySrcStages, dirtySrcAccesses, dirtyDstStages, dirtyDstAccesses);
6211
6212                         // Try masking some random bits
6213                         srcStages       = dirtySrcStages & rng.getUint32();
6214                         srcAccesses     = dirtySrcAccesses & rng.getUint32();
6215
6216                         dstStages       = dirtyDstStages & rng.getUint32();
6217                         dstAccesses     = dirtyDstAccesses & rng.getUint32();
6218
6219                         // If there are no bits in stage mask use the original dirty stages
6220                         srcStages       = srcStages ? srcStages : dirtySrcStages;
6221                         dstStages       = dstStages ? dstStages : dirtyDstStages;
6222
6223                         if (!srcStages)
6224                                 srcStages = dstStages;
6225
6226                         PipelineBarrier::Type type;
6227
6228                         if (op == OP_PIPELINE_BARRIER_IMAGE)
6229                                 type = PipelineBarrier::TYPE_IMAGE;
6230                         else if (op == OP_PIPELINE_BARRIER_BUFFER)
6231                                 type = PipelineBarrier::TYPE_BUFFER;
6232                         else if (op == OP_PIPELINE_BARRIER_GLOBAL)
6233                                 type = PipelineBarrier::TYPE_GLOBAL;
6234                         else
6235                         {
6236                                 type = PipelineBarrier::TYPE_LAST;
6237                                 DE_FATAL("Unknown op");
6238                         }
6239
6240                         return de::MovePtr<CmdCommand>(new PipelineBarrier(srcStages, srcAccesses, dstStages, dstAccesses, type));
6241                 }
6242
6243                 default:
6244                         DE_FATAL("Unknown op");
6245                         return de::MovePtr<CmdCommand>(DE_NULL);
6246         }
6247 }
6248
6249 de::MovePtr<RenderPassCommand> createRenderPassCommand (de::Random&,
6250                                                                                                                 const State&,
6251                                                                                                                 Op                              op)
6252 {
6253         switch (op)
6254         {
6255                 case OP_RENDER_VERTEX_BUFFER:   return de::MovePtr<RenderPassCommand>(new RenderBuffer(RenderBuffer::RENDERAS_VERTEX_BUFFER));
6256                 case OP_RENDER_INDEX_BUFFER:    return de::MovePtr<RenderPassCommand>(new RenderBuffer(RenderBuffer::RENDERAS_INDEX_BUFFER));
6257
6258                 default:
6259                         DE_FATAL("Unknown op");
6260                         return de::MovePtr<RenderPassCommand>(DE_NULL);
6261         }
6262 }
6263
6264 de::MovePtr<CmdCommand> createRenderPassCommands (const Memory& memory,
6265                                                                                                   de::Random&   nextOpRng,
6266                                                                                                   State&                state,
6267                                                                                                   Usage                 usage,
6268                                                                                                   size_t&               opNdx,
6269                                                                                                   size_t                opCount)
6270 {
6271         vector<RenderPassCommand*>      commands;
6272
6273         try
6274         {
6275                 for (; opNdx < opCount; opNdx++)
6276                 {
6277                         vector<Op>      ops;
6278
6279                         getAvailableOps(state, memory.getSupportBuffers(), memory.getSupportImages(), usage, ops);
6280
6281                         DE_ASSERT(!ops.empty());
6282
6283                         {
6284                                 const Op op = nextOpRng.choose<Op>(ops.begin(), ops.end());
6285
6286                                 if (op == OP_RENDERPASS_END)
6287                                 {
6288                                         break;
6289                                 }
6290                                 else
6291                                 {
6292                                         de::Random      rng     (state.rng);
6293
6294                                         commands.push_back(createRenderPassCommand(rng, state, op).release());
6295                                         applyOp(state, memory, op, usage);
6296
6297                                         DE_ASSERT(state.rng == rng);
6298                                 }
6299                         }
6300                 }
6301
6302                 applyOp(state, memory, OP_RENDERPASS_END, usage);
6303                 return de::MovePtr<CmdCommand>(new SubmitRenderPass(commands));
6304         }
6305         catch (...)
6306         {
6307                 for (size_t commandNdx = 0; commandNdx < commands.size(); commandNdx++)
6308                         delete commands[commandNdx];
6309
6310                 throw;
6311         }
6312 }
6313
6314 de::MovePtr<Command> createCmdCommands (const Memory&   memory,
6315                                                                                 de::Random&             nextOpRng,
6316                                                                                 State&                  state,
6317                                                                                 Usage                   usage,
6318                                                                                 size_t&                 opNdx,
6319                                                                                 size_t                  opCount)
6320 {
6321         vector<CmdCommand*>     commands;
6322
6323         try
6324         {
6325                 for (; opNdx < opCount; opNdx++)
6326                 {
6327                         vector<Op>      ops;
6328
6329                         getAvailableOps(state, memory.getSupportBuffers(), memory.getSupportImages(), usage, ops);
6330
6331                         DE_ASSERT(!ops.empty());
6332
6333                         {
6334                                 const Op op = nextOpRng.choose<Op>(ops.begin(), ops.end());
6335
6336                                 if (op == OP_COMMAND_BUFFER_END)
6337                                 {
6338                                         break;
6339                                 }
6340                                 else
6341                                 {
6342                                         // \note Command needs to known the state before the operation
6343                                         if (op == OP_RENDERPASS_BEGIN)
6344                                         {
6345                                                 applyOp(state, memory, op, usage);
6346                                                 commands.push_back(createRenderPassCommands(memory, nextOpRng, state, usage, opNdx, opCount).release());
6347                                         }
6348                                         else
6349                                         {
6350                                                 de::Random      rng     (state.rng);
6351
6352                                                 commands.push_back(createCmdCommand(rng, state, op, usage).release());
6353                                                 applyOp(state, memory, op, usage);
6354
6355                                                 DE_ASSERT(state.rng == rng);
6356                                         }
6357
6358                                 }
6359                         }
6360                 }
6361
6362                 applyOp(state, memory, OP_COMMAND_BUFFER_END, usage);
6363                 return de::MovePtr<Command>(new SubmitCommandBuffer(commands));
6364         }
6365         catch (...)
6366         {
6367                 for (size_t commandNdx = 0; commandNdx < commands.size(); commandNdx++)
6368                         delete commands[commandNdx];
6369
6370                 throw;
6371         }
6372 }
6373
6374 void createCommands (vector<Command*>&                  commands,
6375                                          deUint32                                       seed,
6376                                          const Memory&                          memory,
6377                                          Usage                                          usage,
6378                                          vk::VkSharingMode                      sharingMode)
6379 {
6380         const size_t            opCount         = 100;
6381         State                           state           (usage, seed);
6382         // Used to select next operation only
6383         de::Random                      nextOpRng       (seed ^ 12930809);
6384
6385         commands.reserve(opCount);
6386
6387         for (size_t opNdx = 0; opNdx < opCount; opNdx++)
6388         {
6389                 vector<Op>      ops;
6390
6391                 getAvailableOps(state, memory.getSupportBuffers(), memory.getSupportImages(), usage, ops);
6392
6393                 DE_ASSERT(!ops.empty());
6394
6395                 {
6396                         const Op        op      = nextOpRng.choose<Op>(ops.begin(), ops.end());
6397
6398                         if (op == OP_COMMAND_BUFFER_BEGIN)
6399                         {
6400                                 applyOp(state, memory, op, usage);
6401                                 commands.push_back(createCmdCommands(memory, nextOpRng, state, usage, opNdx, opCount).release());
6402                         }
6403                         else
6404                         {
6405                                 de::Random      rng     (state.rng);
6406
6407                                 commands.push_back(createHostCommand(op, rng, usage, sharingMode).release());
6408                                 applyOp(state, memory, op, usage);
6409
6410                                 // Make sure that random generator is in sync
6411                                 DE_ASSERT(state.rng == rng);
6412                         }
6413                 }
6414         }
6415
6416         // Clean up resources
6417         if (state.hasBuffer && state.hasImage)
6418         {
6419                 if (!state.queueIdle)
6420                         commands.push_back(new QueueWaitIdle());
6421
6422                 if (state.hasBuffer)
6423                         commands.push_back(new DestroyBuffer());
6424
6425                 if (state.hasImage)
6426                         commands.push_back(new DestroyImage());
6427         }
6428 }
6429
6430 void testCommand (TestLog&                                                                                      log,
6431                                   tcu::ResultCollector&                                                         resultCollector,
6432                                   const vk::ProgramCollection<vk::ProgramBinary>&       binaryCollection,
6433                                   const vk::InstanceInterface&                                          vki,
6434                                   const vk::DeviceInterface&                                            vkd,
6435                                   vk::VkPhysicalDevice                                                          physicalDevice,
6436                                   vk::VkDevice                                                                          device,
6437                                   vk::VkDeviceSize                                                                      size,
6438                                   deUint32                                                                                      memoryTypeIndex,
6439                                   Usage                                                                                         usage,
6440                                   vk::VkSharingMode                                                                     sharingMode,
6441                                   vk::VkQueue                                                                           executionQueue,
6442                                   deUint32                                                                                      executionQueueFamily,
6443                                   const vector<deUint32>&                                                       queueFamilies,
6444                                   const vk::VkDeviceSize                                                        maxBufferSize,
6445                                   const IVec2                                                                           maxImageSize)
6446 {
6447         const deUint32                                                  seed                    = 2830980989u;
6448         Memory                                                                  memory                  (vki, vkd, physicalDevice, device, size, memoryTypeIndex, maxBufferSize, maxImageSize[0], maxImageSize[1]);
6449         vector<Command*>                                                commands;
6450         vector<pair<deUint32, vk::VkQueue> >    queues;
6451
6452         try
6453         {
6454                 log << TestLog::Message << "Create commands" << TestLog::EndMessage;
6455                 createCommands(commands, seed, memory, usage, sharingMode);
6456
6457                 for (size_t queueNdx = 0; queueNdx < queueFamilies.size(); queueNdx++)
6458                 {
6459                         vk::VkQueue queue;
6460
6461                         vkd.getDeviceQueue(device, queueFamilies[queueNdx], 0, &queue);
6462                         queues.push_back(std::make_pair(queueFamilies[queueNdx], queue));
6463                 }
6464
6465                 {
6466                         const tcu::ScopedLogSection section (log, "LogPrepare", "LogPrepare");
6467
6468                         for (size_t cmdNdx = 0; cmdNdx < commands.size(); cmdNdx++)
6469                                 commands[cmdNdx]->logPrepare(log, cmdNdx);
6470                 }
6471
6472                 {
6473                         const tcu::ScopedLogSection section (log, "LogExecute", "LogExecute");
6474
6475                         for (size_t cmdNdx = 0; cmdNdx < commands.size(); cmdNdx++)
6476                                 commands[cmdNdx]->logExecute(log, cmdNdx);
6477                 }
6478
6479                 {
6480                         const Context context (vki, vkd, physicalDevice, device, executionQueue, executionQueueFamily, queues, binaryCollection);
6481
6482                         try
6483                         {
6484                                 {
6485                                         PrepareContext  prepareContext  (context, memory);
6486
6487                                         log << TestLog::Message << "Begin prepare" << TestLog::EndMessage;
6488
6489                                         for (size_t cmdNdx = 0; cmdNdx < commands.size(); cmdNdx++)
6490                                         {
6491                                                 Command& command = *commands[cmdNdx];
6492
6493                                                 try
6494                                                 {
6495                                                         command.prepare(prepareContext);
6496                                                 }
6497                                                 catch (...)
6498                                                 {
6499                                                         resultCollector.fail(de::toString(cmdNdx) + ":" + command.getName() + " failed to prepare for execution");
6500                                                         throw;
6501                                                 }
6502                                         }
6503
6504                                         ExecuteContext  executeContext  (context);
6505
6506                                         log << TestLog::Message << "Begin execution" << TestLog::EndMessage;
6507
6508                                         for (size_t cmdNdx = 0; cmdNdx < commands.size(); cmdNdx++)
6509                                         {
6510                                                 Command& command = *commands[cmdNdx];
6511
6512                                                 try
6513                                                 {
6514                                                         command.execute(executeContext);
6515                                                 }
6516                                                 catch (...)
6517                                                 {
6518                                                         resultCollector.fail(de::toString(cmdNdx) + ":" + command.getName() + " failed to execute");
6519                                                         throw;
6520                                                 }
6521                                         }
6522
6523                                         VK_CHECK(vkd.deviceWaitIdle(device));
6524                                 }
6525
6526                                 {
6527                                         const tcu::ScopedLogSection     section                 (log, "Verify", "Verify");
6528                                         VerifyContext                           verifyContext   (log, resultCollector, context, size);
6529
6530                                         log << TestLog::Message << "Begin verify" << TestLog::EndMessage;
6531
6532                                         for (size_t cmdNdx = 0; cmdNdx < commands.size(); cmdNdx++)
6533                                         {
6534                                                 Command& command = *commands[cmdNdx];
6535
6536                                                 try
6537                                                 {
6538                                                         command.verify(verifyContext, cmdNdx);
6539                                                 }
6540                                                 catch (...)
6541                                                 {
6542                                                         resultCollector.fail(de::toString(cmdNdx) + ":" + command.getName() + " failed verification");
6543                                                         throw;
6544                                                 }
6545                                         }
6546                                 }
6547
6548                                 for (size_t commandNdx = 0; commandNdx < commands.size(); commandNdx++)
6549                                 {
6550                                         delete commands[commandNdx];
6551                                         commands[commandNdx] = DE_NULL;
6552                                 }
6553                         }
6554                         catch (...)
6555                         {
6556                                 for (size_t commandNdx = 0; commandNdx < commands.size(); commandNdx++)
6557                                 {
6558                                         delete commands[commandNdx];
6559                                         commands[commandNdx] = DE_NULL;
6560                                 }
6561
6562                                 throw;
6563                         }
6564                 }
6565         }
6566         catch (...)
6567         {
6568                 for (size_t commandNdx = 0; commandNdx < commands.size(); commandNdx++)
6569                 {
6570                         delete commands[commandNdx];
6571                         commands[commandNdx] = DE_NULL;
6572                 }
6573
6574                 throw;
6575         }
6576 }
6577 class MemoryTestInstance : public TestInstance
6578 {
6579 public:
6580
6581                                                 MemoryTestInstance      (::vkt::Context& context, const TestConfig& config);
6582
6583         tcu::TestStatus         iterate                         (void);
6584
6585 private:
6586         const TestConfig                                                        m_config;
6587         const vk::VkPhysicalDeviceMemoryProperties      m_memoryProperties;
6588         deUint32                                                                        m_memoryTypeNdx;
6589         tcu::ResultCollector                                            m_resultCollector;
6590 };
6591
6592 MemoryTestInstance::MemoryTestInstance (::vkt::Context& context, const TestConfig& config)
6593         : TestInstance                  (context)
6594         , m_config                              (config)
6595         , m_memoryProperties    (vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()))
6596         , m_memoryTypeNdx               (0)
6597         , m_resultCollector             (context.getTestContext().getLog())
6598 {
6599         TestLog&        log             = context.getTestContext().getLog();
6600         {
6601                 const tcu::ScopedLogSection section (log, "TestCaseInfo", "Test Case Info");
6602
6603                 log << TestLog::Message << "Buffer size: " << config.size << TestLog::EndMessage;
6604                 log << TestLog::Message << "Sharing: " << config.sharing << TestLog::EndMessage;
6605                 log << TestLog::Message << "Access: " << config.usage << TestLog::EndMessage;
6606         }
6607
6608         {
6609                 const tcu::ScopedLogSection section (log, "MemoryProperties", "Memory Properties");
6610
6611                 for (deUint32 heapNdx = 0; heapNdx < m_memoryProperties.memoryHeapCount; heapNdx++)
6612                 {
6613                         const tcu::ScopedLogSection heapSection (log, "Heap" + de::toString(heapNdx), "Heap " + de::toString(heapNdx));
6614
6615                         log << TestLog::Message << "Size: " << m_memoryProperties.memoryHeaps[heapNdx].size << TestLog::EndMessage;
6616                         log << TestLog::Message << "Flags: " << m_memoryProperties.memoryHeaps[heapNdx].flags << TestLog::EndMessage;
6617                 }
6618
6619                 for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < m_memoryProperties.memoryTypeCount; memoryTypeNdx++)
6620                 {
6621                         const tcu::ScopedLogSection memoryTypeSection (log, "MemoryType" + de::toString(memoryTypeNdx), "Memory type " + de::toString(memoryTypeNdx));
6622
6623                         log << TestLog::Message << "Properties: " << m_memoryProperties.memoryTypes[memoryTypeNdx].propertyFlags << TestLog::EndMessage;
6624                         log << TestLog::Message << "Heap: " << m_memoryProperties.memoryTypes[memoryTypeNdx].heapIndex << TestLog::EndMessage;
6625                 }
6626         }
6627 }
6628
6629 tcu::TestStatus MemoryTestInstance::iterate (void)
6630 {
6631         // \todo [2016-03-09 mika] Split different stages over multiple iterations
6632         if (m_memoryTypeNdx < m_memoryProperties.memoryTypeCount)
6633         {
6634                 TestLog&                                                                        log                                     = m_context.getTestContext().getLog();
6635                 const tcu::ScopedLogSection                                     section                         (log, "MemoryType" + de::toString(m_memoryTypeNdx), "Memory type " + de::toString(m_memoryTypeNdx));
6636                 const vk::InstanceInterface&                            vki                                     = m_context.getInstanceInterface();
6637                 const vk::VkPhysicalDevice                                      physicalDevice          = m_context.getPhysicalDevice();
6638                 const vk::DeviceInterface&                                      vkd                                     = m_context.getDeviceInterface();
6639                 const vk::VkDevice                                                      device                          = m_context.getDevice();
6640                 const vk::VkQueue                                                       queue                           = m_context.getUniversalQueue();
6641                 const deUint32                                                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
6642                 const vk::VkPhysicalDeviceMemoryProperties      memoryProperties        = vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice);
6643                 vector<deUint32>                                                        queues;
6644
6645                 queues.push_back(queueFamilyIndex);
6646
6647                 if (m_config.usage & (USAGE_HOST_READ|USAGE_HOST_WRITE)
6648                         && !(memoryProperties.memoryTypes[m_memoryTypeNdx].propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
6649                 {
6650                         log << TestLog::Message << "Memory type not supported" << TestLog::EndMessage;
6651
6652                         m_memoryTypeNdx++;
6653                         return tcu::TestStatus::incomplete();
6654                 }
6655                 else
6656                 {
6657                         try
6658                         {
6659                                 const vk::VkBufferUsageFlags    bufferUsage             = usageToBufferUsageFlags(m_config.usage);
6660                                 const vk::VkImageUsageFlags             imageUsage              = usageToImageUsageFlags(m_config.usage);
6661                                 const vk::VkDeviceSize                  maxBufferSize   = bufferUsage != 0
6662                                                                                                                                 ? roundBufferSizeToWxHx4(findMaxBufferSize(vkd, device, bufferUsage, m_config.sharing, queues, m_config.size, m_memoryTypeNdx))
6663                                                                                                                                 : 0;
6664                                 const IVec2                                             maxImageSize    = imageUsage != 0
6665                                                                                                                                 ? findMaxRGBA8ImageSize(vkd, device, imageUsage, m_config.sharing, queues, m_config.size, m_memoryTypeNdx)
6666                                                                                                                                 : IVec2(0, 0);
6667
6668                                 log << TestLog::Message << "Max buffer size: " << maxBufferSize << TestLog::EndMessage;
6669                                 log << TestLog::Message << "Max RGBA8 image size: " << maxImageSize << TestLog::EndMessage;
6670
6671                                 // Skip tests if there are no supported operations
6672                                 if (maxBufferSize == 0
6673                                         && maxImageSize[0] == 0
6674                                         && (m_config.usage & (USAGE_HOST_READ|USAGE_HOST_WRITE)) == 0)
6675                                 {
6676                                         log << TestLog::Message << "Skipping memory type. None of the usages are supported." << TestLog::EndMessage;
6677                                 }
6678                                 else
6679                                 {
6680                                         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);
6681                                 }
6682                         }
6683                         catch (const tcu::TestError& e)
6684                         {
6685                                 m_resultCollector.fail("Failed, got exception: " + string(e.getMessage()));
6686                         }
6687
6688                         m_memoryTypeNdx++;
6689                         return tcu::TestStatus::incomplete();
6690                 }
6691         }
6692         else
6693                 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
6694 }
6695
6696 struct AddPrograms
6697 {
6698         void init (vk::SourceCollections& sources, TestConfig config) const
6699         {
6700                 // Vertex buffer rendering
6701                 if (config.usage & USAGE_VERTEX_BUFFER)
6702                 {
6703                         const char* const vertexShader =
6704                                 "#version 310 es\n"
6705                                 "layout(location = 0) in highp vec2 a_position;\n"
6706                                 "void main (void) {\n"
6707                                 "\tgl_PointSize = 1.0;\n"
6708                                 "\tgl_Position = vec4(1.998 * a_position - vec2(0.999), 0.0, 1.0);\n"
6709                                 "}\n";
6710
6711                         sources.glslSources.add("vertex-buffer.vert")
6712                                 << glu::VertexSource(vertexShader);
6713                 }
6714
6715                 // Index buffer rendering
6716                 if (config.usage & USAGE_INDEX_BUFFER)
6717                 {
6718                         const char* const vertexShader =
6719                                 "#version 310 es\n"
6720                                 "highp float;\n"
6721                                 "void main (void) {\n"
6722                                 "\tgl_PointSize = 1.0;\n"
6723                                 "\thighp vec2 pos = vec2(gl_VertexIndex % 256, gl_VertexIndex / 256) / vec2(255.0);\n"
6724                                 "\tgl_Position = vec4(1.998 * pos - vec2(0.999), 0.0, 1.0);\n"
6725                                 "}\n";
6726
6727                         sources.glslSources.add("index-buffer.vert")
6728                                 << glu::VertexSource(vertexShader);
6729                 }
6730
6731                 {
6732                         const char* const fragmentShader =
6733                                 "#version 310 es\n"
6734                                 "layout(location = 0) out highp vec4 o_color;\n"
6735                                 "void main (void) {\n"
6736                                 "\to_color = vec4(1.0);\n"
6737                                 "}\n";
6738
6739                         sources.glslSources.add("render-white.frag")
6740                                 << glu::FragmentSource(fragmentShader);
6741                 }
6742         }
6743 };
6744
6745 } // anonymous
6746
6747 tcu::TestCaseGroup* createPipelineBarrierTests (tcu::TestContext& testCtx)
6748 {
6749         de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "pipeline_barrier", "Pipeline barrier tests."));
6750         const vk::VkDeviceSize                  sizes[]                 =
6751         {
6752                 1024,                   // 1K
6753                 8*1024,                 // 8K
6754                 64*1024,                // 64K
6755                 1024*1024,              // 1M
6756         };
6757         const Usage                                             usages[]                =
6758         {
6759                 USAGE_HOST_READ,
6760                 USAGE_HOST_WRITE,
6761                 USAGE_TRANSFER_SRC,
6762                 USAGE_TRANSFER_DST,
6763                 USAGE_VERTEX_BUFFER,
6764                 USAGE_INDEX_BUFFER
6765         };
6766         const Usage                                             readUsages[]            =
6767         {
6768                 USAGE_HOST_READ,
6769                 USAGE_TRANSFER_SRC,
6770                 USAGE_VERTEX_BUFFER,
6771                 USAGE_INDEX_BUFFER
6772         };
6773
6774         const Usage                                             writeUsages[]   =
6775         {
6776                 USAGE_HOST_WRITE,
6777                 USAGE_TRANSFER_DST
6778         };
6779
6780         for (size_t writeUsageNdx = 0; writeUsageNdx < DE_LENGTH_OF_ARRAY(writeUsages); writeUsageNdx++)
6781         {
6782                 const Usage     writeUsage      = writeUsages[writeUsageNdx];
6783
6784                 for (size_t readUsageNdx = 0; readUsageNdx < DE_LENGTH_OF_ARRAY(readUsages); readUsageNdx++)
6785                 {
6786                         const Usage                                             readUsage               = readUsages[readUsageNdx];
6787                         const Usage                                             usage                   = writeUsage | readUsage;
6788                         const string                                    usageGroupName  (usageToName(usage));
6789                         de::MovePtr<tcu::TestCaseGroup> usageGroup              (new tcu::TestCaseGroup(testCtx, usageGroupName.c_str(), usageGroupName.c_str()));
6790
6791                         for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); sizeNdx++)
6792                         {
6793                                 const vk::VkDeviceSize  size            = sizes[sizeNdx];
6794                                 const string                    testName        (de::toString((deUint64)(size)));
6795                                 const TestConfig                config          =
6796                                 {
6797                                         usage,
6798                                         size,
6799                                         vk::VK_SHARING_MODE_EXCLUSIVE
6800                                 };
6801
6802                                 usageGroup->addChild(new InstanceFactory1<MemoryTestInstance, TestConfig, AddPrograms>(testCtx,tcu::NODETYPE_SELF_VALIDATE,  testName, testName, AddPrograms(), config));
6803                         }
6804
6805                         group->addChild(usageGroup.get());
6806                         usageGroup.release();
6807                 }
6808         }
6809
6810         {
6811                 Usage all = (Usage)0;
6812
6813                 for (size_t usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usages); usageNdx++)
6814                         all = all | usages[usageNdx];
6815
6816                 {
6817                         const string                                    usageGroupName  ("all");
6818                         de::MovePtr<tcu::TestCaseGroup> usageGroup              (new tcu::TestCaseGroup(testCtx, usageGroupName.c_str(), usageGroupName.c_str()));
6819
6820                         for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); sizeNdx++)
6821                         {
6822                                 const vk::VkDeviceSize  size            = sizes[sizeNdx];
6823                                 const string                    testName        (de::toString((deUint64)(size)));
6824                                 const TestConfig                config          =
6825                                 {
6826                                         all,
6827                                         size,
6828                                         vk::VK_SHARING_MODE_EXCLUSIVE
6829                                 };
6830
6831                                 usageGroup->addChild(new InstanceFactory1<MemoryTestInstance, TestConfig, AddPrograms>(testCtx,tcu::NODETYPE_SELF_VALIDATE,  testName, testName, AddPrograms(), config));
6832                         }
6833
6834                         group->addChild(usageGroup.get());
6835                         usageGroup.release();
6836                 }
6837
6838                 {
6839                         const string                                    usageGroupName  ("all_device");
6840                         de::MovePtr<tcu::TestCaseGroup> usageGroup              (new tcu::TestCaseGroup(testCtx, usageGroupName.c_str(), usageGroupName.c_str()));
6841
6842                         for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); sizeNdx++)
6843                         {
6844                                 const vk::VkDeviceSize  size            = sizes[sizeNdx];
6845                                 const string                    testName        (de::toString((deUint64)(size)));
6846                                 const TestConfig                config          =
6847                                 {
6848                                         (Usage)(all & (~(USAGE_HOST_READ|USAGE_HOST_WRITE))),
6849                                         size,
6850                                         vk::VK_SHARING_MODE_EXCLUSIVE
6851                                 };
6852
6853                                 usageGroup->addChild(new InstanceFactory1<MemoryTestInstance, TestConfig, AddPrograms>(testCtx,tcu::NODETYPE_SELF_VALIDATE,  testName, testName, AddPrograms(), config));
6854                         }
6855
6856                         group->addChild(usageGroup.get());
6857                         usageGroup.release();
6858                 }
6859         }
6860
6861         return group.release();
6862 }
6863
6864 } // memory
6865 } // vkt