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