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