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