8ee2155eaf27b3680fd9976b6ecf12176baf28d1
[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::UVec2;
70 using tcu::UVec4;
71 using tcu::Vec4;
72 using tcu::ConstPixelBufferAccess;
73 using tcu::PixelBufferAccess;
74 using tcu::TextureFormat;
75 using tcu::TextureLevel;
76
77 namespace vkt
78 {
79 namespace memory
80 {
81 namespace
82 {
83 enum
84 {
85         MAX_UNIFORM_BUFFER_SIZE = 1024,
86         MAX_STORAGE_BUFFER_SIZE = (1<<28)
87 };
88
89 // \todo [mika] Add to utilities
90 template<typename T>
91 T divRoundUp (const T& a, const T& b)
92 {
93         return (a / b) + (a % b == 0 ? 0 : 1);
94 }
95
96 enum
97 {
98         ALL_PIPELINE_STAGES = vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
99                                                 | vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
100                                                 | vk::VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
101                                                 | vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
102                                                 | vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
103                                                 | vk::VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
104                                                 | vk::VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
105                                                 | vk::VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
106                                                 | vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
107                                                 | vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
108                                                 | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
109                                                 | vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
110                                                 | vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
111                                                 | vk::VK_PIPELINE_STAGE_TRANSFER_BIT
112                                                 | vk::VK_PIPELINE_STAGE_HOST_BIT
113 };
114
115 enum
116 {
117         ALL_ACCESSES = vk::VK_ACCESS_INDIRECT_COMMAND_READ_BIT
118                                  | vk::VK_ACCESS_INDEX_READ_BIT
119                                  | vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT
120                                  | vk::VK_ACCESS_UNIFORM_READ_BIT
121                                  | vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
122                                  | vk::VK_ACCESS_SHADER_READ_BIT
123                                  | vk::VK_ACCESS_SHADER_WRITE_BIT
124                                  | vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
125                                  | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
126                                  | vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
127                                  | vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
128                                  | vk::VK_ACCESS_TRANSFER_READ_BIT
129                                  | vk::VK_ACCESS_TRANSFER_WRITE_BIT
130                                  | vk::VK_ACCESS_HOST_READ_BIT
131                                  | vk::VK_ACCESS_HOST_WRITE_BIT
132                                  | vk::VK_ACCESS_MEMORY_READ_BIT
133                                  | vk::VK_ACCESS_MEMORY_WRITE_BIT
134 };
135
136 enum Usage
137 {
138         // Mapped host read and write
139         USAGE_HOST_READ = (0x1u<<0),
140         USAGE_HOST_WRITE = (0x1u<<1),
141
142         // Copy and other transfer operations
143         USAGE_TRANSFER_SRC = (0x1u<<2),
144         USAGE_TRANSFER_DST = (0x1u<<3),
145
146         // Buffer usage flags
147         USAGE_INDEX_BUFFER = (0x1u<<4),
148         USAGE_VERTEX_BUFFER = (0x1u<<5),
149
150         USAGE_UNIFORM_BUFFER = (0x1u<<6),
151         USAGE_STORAGE_BUFFER = (0x1u<<7),
152
153         USAGE_UNIFORM_TEXEL_BUFFER = (0x1u<<8),
154         USAGE_STORAGE_TEXEL_BUFFER = (0x1u<<9),
155
156         // \todo [2016-03-09 mika] This is probably almost impossible to do
157         USAGE_INDIRECT_BUFFER = (0x1u<<10),
158
159         // Texture usage flags
160         USAGE_SAMPLED_IMAGE = (0x1u<<11),
161         USAGE_STORAGE_IMAGE = (0x1u<<12),
162         USAGE_COLOR_ATTACHMENT = (0x1u<<13),
163         USAGE_INPUT_ATTACHMENT = (0x1u<<14),
164         USAGE_DEPTH_STENCIL_ATTACHMENT = (0x1u<<15),
165 };
166
167 bool supportsDeviceBufferWrites (Usage usage)
168 {
169         if (usage & USAGE_TRANSFER_DST)
170                 return true;
171
172         if (usage & USAGE_STORAGE_BUFFER)
173                 return true;
174
175         if (usage & USAGE_STORAGE_TEXEL_BUFFER)
176                 return true;
177
178         return false;
179 }
180
181 bool supportsDeviceImageWrites (Usage usage)
182 {
183         if (usage & USAGE_TRANSFER_DST)
184                 return true;
185
186         if (usage & USAGE_STORAGE_IMAGE)
187                 return true;
188
189         if (usage & USAGE_COLOR_ATTACHMENT)
190                 return true;
191
192         return false;
193 }
194
195 // Sequential access enums
196 enum Access
197 {
198         ACCESS_INDIRECT_COMMAND_READ_BIT = 0,
199         ACCESS_INDEX_READ_BIT,
200         ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
201         ACCESS_UNIFORM_READ_BIT,
202         ACCESS_INPUT_ATTACHMENT_READ_BIT,
203         ACCESS_SHADER_READ_BIT,
204         ACCESS_SHADER_WRITE_BIT,
205         ACCESS_COLOR_ATTACHMENT_READ_BIT,
206         ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
207         ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
208         ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
209         ACCESS_TRANSFER_READ_BIT,
210         ACCESS_TRANSFER_WRITE_BIT,
211         ACCESS_HOST_READ_BIT,
212         ACCESS_HOST_WRITE_BIT,
213         ACCESS_MEMORY_READ_BIT,
214         ACCESS_MEMORY_WRITE_BIT,
215
216         ACCESS_LAST
217 };
218
219 // Sequential stage enums
220 enum PipelineStage
221 {
222         PIPELINESTAGE_TOP_OF_PIPE_BIT = 0,
223         PIPELINESTAGE_BOTTOM_OF_PIPE_BIT,
224         PIPELINESTAGE_DRAW_INDIRECT_BIT,
225         PIPELINESTAGE_VERTEX_INPUT_BIT,
226         PIPELINESTAGE_VERTEX_SHADER_BIT,
227         PIPELINESTAGE_TESSELLATION_CONTROL_SHADER_BIT,
228         PIPELINESTAGE_TESSELLATION_EVALUATION_SHADER_BIT,
229         PIPELINESTAGE_GEOMETRY_SHADER_BIT,
230         PIPELINESTAGE_FRAGMENT_SHADER_BIT,
231         PIPELINESTAGE_EARLY_FRAGMENT_TESTS_BIT,
232         PIPELINESTAGE_LATE_FRAGMENT_TESTS_BIT,
233         PIPELINESTAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
234         PIPELINESTAGE_COMPUTE_SHADER_BIT,
235         PIPELINESTAGE_TRANSFER_BIT,
236         PIPELINESTAGE_HOST_BIT,
237
238         PIPELINESTAGE_LAST
239 };
240
241 PipelineStage pipelineStageFlagToPipelineStage (vk::VkPipelineStageFlagBits flags)
242 {
243         switch (flags)
244         {
245                 case vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT:                                             return PIPELINESTAGE_TOP_OF_PIPE_BIT;
246                 case vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT:                                  return PIPELINESTAGE_BOTTOM_OF_PIPE_BIT;
247                 case vk::VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT:                                   return PIPELINESTAGE_DRAW_INDIRECT_BIT;
248                 case vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT:                                    return PIPELINESTAGE_VERTEX_INPUT_BIT;
249                 case vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT:                                   return PIPELINESTAGE_VERTEX_SHADER_BIT;
250                 case vk::VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT:             return PIPELINESTAGE_TESSELLATION_CONTROL_SHADER_BIT;
251                 case vk::VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT:  return PIPELINESTAGE_TESSELLATION_EVALUATION_SHADER_BIT;
252                 case vk::VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT:                                 return PIPELINESTAGE_GEOMETRY_SHADER_BIT;
253                 case vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT:                                 return PIPELINESTAGE_FRAGMENT_SHADER_BIT;
254                 case vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT:                    return PIPELINESTAGE_EARLY_FRAGMENT_TESTS_BIT;
255                 case vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT:                             return PIPELINESTAGE_LATE_FRAGMENT_TESTS_BIT;
256                 case vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT:                 return PIPELINESTAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
257                 case vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT:                                  return PIPELINESTAGE_COMPUTE_SHADER_BIT;
258                 case vk::VK_PIPELINE_STAGE_TRANSFER_BIT:                                                return PIPELINESTAGE_TRANSFER_BIT;
259                 case vk::VK_PIPELINE_STAGE_HOST_BIT:                                                    return PIPELINESTAGE_HOST_BIT;
260
261                 default:
262                         DE_FATAL("Unknown pipeline stage flags");
263                         return PIPELINESTAGE_LAST;
264         }
265 }
266
267 Usage operator| (Usage a, Usage b)
268 {
269         return (Usage)((deUint32)a | (deUint32)b);
270 }
271
272 Usage operator& (Usage a, Usage b)
273 {
274         return (Usage)((deUint32)a & (deUint32)b);
275 }
276
277 string usageToName (Usage usage)
278 {
279         const struct
280         {
281                 Usage                           usage;
282                 const char* const       name;
283         } usageNames[] =
284         {
285                 { USAGE_HOST_READ,                                      "host_read" },
286                 { USAGE_HOST_WRITE,                                     "host_write" },
287
288                 { USAGE_TRANSFER_SRC,                           "transfer_src" },
289                 { USAGE_TRANSFER_DST,                           "transfer_dst" },
290
291                 { USAGE_INDEX_BUFFER,                           "index_buffer" },
292                 { USAGE_VERTEX_BUFFER,                          "vertex_buffer" },
293                 { USAGE_UNIFORM_BUFFER,                         "uniform_buffer" },
294                 { USAGE_STORAGE_BUFFER,                         "storage_buffer" },
295                 { USAGE_UNIFORM_TEXEL_BUFFER,           "uniform_texel_buffer" },
296                 { USAGE_STORAGE_TEXEL_BUFFER,           "storage_texel_buffer" },
297                 { USAGE_INDIRECT_BUFFER,                        "indirect_buffer" },
298                 { USAGE_SAMPLED_IMAGE,                          "image_sampled" },
299                 { USAGE_STORAGE_IMAGE,                          "storage_image" },
300                 { USAGE_COLOR_ATTACHMENT,                       "color_attachment" },
301                 { USAGE_INPUT_ATTACHMENT,                       "input_attachment" },
302                 { USAGE_DEPTH_STENCIL_ATTACHMENT,       "depth_stencil_attachment" },
303         };
304
305         std::ostringstream      stream;
306         bool                            first = true;
307
308         for (size_t usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usageNames); usageNdx++)
309         {
310                 if (usage & usageNames[usageNdx].usage)
311                 {
312                         if (!first)
313                                 stream << "_";
314                         else
315                                 first = false;
316
317                         stream << usageNames[usageNdx].name;
318                 }
319         }
320
321         return stream.str();
322 }
323
324 vk::VkBufferUsageFlags usageToBufferUsageFlags (Usage usage)
325 {
326         vk::VkBufferUsageFlags flags = 0;
327
328         if (usage & USAGE_TRANSFER_SRC)
329                 flags |= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
330
331         if (usage & USAGE_TRANSFER_DST)
332                 flags |= vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
333
334         if (usage & USAGE_INDEX_BUFFER)
335                 flags |= vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
336
337         if (usage & USAGE_VERTEX_BUFFER)
338                 flags |= vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
339
340         if (usage & USAGE_INDIRECT_BUFFER)
341                 flags |= vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
342
343         if (usage & USAGE_UNIFORM_BUFFER)
344                 flags |= vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
345
346         if (usage & USAGE_STORAGE_BUFFER)
347                 flags |= vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
348
349         if (usage & USAGE_UNIFORM_TEXEL_BUFFER)
350                 flags |= vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
351
352         if (usage & USAGE_STORAGE_TEXEL_BUFFER)
353                 flags |= vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
354
355         return flags;
356 }
357
358 vk::VkImageUsageFlags usageToImageUsageFlags (Usage usage)
359 {
360         vk::VkImageUsageFlags flags = 0;
361
362         if (usage & USAGE_TRANSFER_SRC)
363                 flags |= vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
364
365         if (usage & USAGE_TRANSFER_DST)
366                 flags |= vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT;
367
368         if (usage & USAGE_SAMPLED_IMAGE)
369                 flags |= vk::VK_IMAGE_USAGE_SAMPLED_BIT;
370
371         if (usage & USAGE_STORAGE_IMAGE)
372                 flags |= vk::VK_IMAGE_USAGE_STORAGE_BIT;
373
374         if (usage & USAGE_COLOR_ATTACHMENT)
375                 flags |= vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
376
377         if (usage & USAGE_INPUT_ATTACHMENT)
378                 flags |= vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
379
380         if (usage & USAGE_DEPTH_STENCIL_ATTACHMENT)
381                 flags |= vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
382
383         return flags;
384 }
385
386 vk::VkPipelineStageFlags usageToStageFlags (Usage usage)
387 {
388         vk::VkPipelineStageFlags flags = 0;
389
390         if (usage & (USAGE_HOST_READ|USAGE_HOST_WRITE))
391                 flags |= vk::VK_PIPELINE_STAGE_HOST_BIT;
392
393         if (usage & (USAGE_TRANSFER_SRC|USAGE_TRANSFER_DST))
394                 flags |= vk::VK_PIPELINE_STAGE_TRANSFER_BIT;
395
396         if (usage & (USAGE_VERTEX_BUFFER|USAGE_INDEX_BUFFER))
397                 flags |= vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
398
399         if (usage & USAGE_INDIRECT_BUFFER)
400                 flags |= vk::VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
401
402         if (usage &
403                         (USAGE_UNIFORM_BUFFER
404                         | USAGE_STORAGE_BUFFER
405                         | USAGE_UNIFORM_TEXEL_BUFFER
406                         | USAGE_STORAGE_TEXEL_BUFFER
407                         | USAGE_SAMPLED_IMAGE
408                         | USAGE_STORAGE_IMAGE))
409         {
410                 flags |= (vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
411                                 | vk::VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
412                                 | vk::VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
413                                 | vk::VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
414                                 | vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
415                                 | vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
416         }
417
418         if (usage & USAGE_INPUT_ATTACHMENT)
419                 flags |= vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
420
421         if (usage & USAGE_COLOR_ATTACHMENT)
422                 flags |= vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
423
424         if (usage & USAGE_DEPTH_STENCIL_ATTACHMENT)
425         {
426                 flags |= vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
427                                 | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
428         }
429
430         return flags;
431 }
432
433 vk::VkAccessFlags usageToAccessFlags (Usage usage)
434 {
435         vk::VkAccessFlags flags = 0;
436
437         if (usage & USAGE_HOST_READ)
438                 flags |= vk::VK_ACCESS_HOST_READ_BIT;
439
440         if (usage & USAGE_HOST_WRITE)
441                 flags |= vk::VK_ACCESS_HOST_WRITE_BIT;
442
443         if (usage & USAGE_TRANSFER_SRC)
444                 flags |= vk::VK_ACCESS_TRANSFER_READ_BIT;
445
446         if (usage & USAGE_TRANSFER_DST)
447                 flags |= vk::VK_ACCESS_TRANSFER_WRITE_BIT;
448
449         if (usage & USAGE_INDEX_BUFFER)
450                 flags |= vk::VK_ACCESS_INDEX_READ_BIT;
451
452         if (usage & USAGE_VERTEX_BUFFER)
453                 flags |= vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
454
455         if (usage & (USAGE_UNIFORM_BUFFER | USAGE_UNIFORM_TEXEL_BUFFER))
456                 flags |= vk::VK_ACCESS_UNIFORM_READ_BIT;
457
458         if (usage & USAGE_SAMPLED_IMAGE)
459                 flags |= vk::VK_ACCESS_SHADER_READ_BIT;
460
461         if (usage & (USAGE_STORAGE_BUFFER
462                                 | USAGE_STORAGE_TEXEL_BUFFER
463                                 | USAGE_STORAGE_IMAGE))
464                 flags |= vk::VK_ACCESS_SHADER_READ_BIT | vk::VK_ACCESS_SHADER_WRITE_BIT;
465
466         if (usage & USAGE_INDIRECT_BUFFER)
467                 flags |= vk::VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
468
469         if (usage & USAGE_COLOR_ATTACHMENT)
470                 flags |= vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
471
472         if (usage & USAGE_INPUT_ATTACHMENT)
473                 flags |= vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
474
475         if (usage & USAGE_DEPTH_STENCIL_ATTACHMENT)
476                 flags |= vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
477                         | vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
478
479         return flags;
480 }
481
482 struct TestConfig
483 {
484         Usage                           usage;
485         vk::VkDeviceSize        size;
486         vk::VkSharingMode       sharing;
487 };
488
489 vk::Move<vk::VkCommandBuffer> createCommandBuffer (const vk::DeviceInterface&   vkd,
490                                                                                                    vk::VkDevice                                 device,
491                                                                                                    vk::VkCommandPool                    pool,
492                                                                                                    vk::VkCommandBufferLevel             level)
493 {
494         const vk::VkCommandBufferAllocateInfo bufferInfo =
495         {
496                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
497                 DE_NULL,
498
499                 pool,
500                 level,
501                 1u
502         };
503
504         return vk::allocateCommandBuffer(vkd, device, &bufferInfo);
505 }
506
507 vk::Move<vk::VkCommandBuffer> createBeginCommandBuffer (const vk::DeviceInterface&      vkd,
508                                                                                                                 vk::VkDevice                            device,
509                                                                                                                 vk::VkCommandPool                       pool,
510                                                                                                                 vk::VkCommandBufferLevel        level)
511 {
512         const vk::VkCommandBufferInheritanceInfo        inheritInfo     =
513         {
514                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
515                 DE_NULL,
516                 0,
517                 0,
518                 0,
519                 VK_FALSE,
520                 0u,
521                 0u
522         };
523         const vk::VkCommandBufferBeginInfo                      beginInfo =
524         {
525                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
526                 DE_NULL,
527                 0u,
528                 (level == vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY ? &inheritInfo : (const vk::VkCommandBufferInheritanceInfo*)DE_NULL),
529         };
530
531         vk::Move<vk::VkCommandBuffer> commandBuffer (createCommandBuffer(vkd, device, pool, level));
532
533         vkd.beginCommandBuffer(*commandBuffer, &beginInfo);
534
535         return commandBuffer;
536 }
537
538 vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface&       vkd,
539                                                                                            vk::VkDevice                                 device,
540                                                                                            deUint32                                             queueFamilyIndex)
541 {
542         const vk::VkCommandPoolCreateInfo poolInfo =
543         {
544                 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
545                 DE_NULL,
546
547                 vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
548                 queueFamilyIndex,
549         };
550
551         return vk::createCommandPool(vkd, device, &poolInfo);
552 }
553
554 vk::Move<vk::VkBuffer> createBuffer (const vk::DeviceInterface& vkd,
555                                                                          vk::VkDevice                           device,
556                                                                          vk::VkDeviceSize                       size,
557                                                                          vk::VkBufferUsageFlags         usage,
558                                                                          vk::VkSharingMode                      sharingMode,
559                                                                          const vector<deUint32>&        queueFamilies)
560 {
561         const vk::VkBufferCreateInfo    createInfo =
562         {
563                 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
564                 DE_NULL,
565
566                 0,      // flags
567                 size,
568                 usage,
569                 sharingMode,
570                 (deUint32)queueFamilies.size(),
571                 &queueFamilies[0]
572         };
573
574         return vk::createBuffer(vkd, device, &createInfo);
575 }
576
577 vk::Move<vk::VkDeviceMemory> allocMemory (const vk::DeviceInterface&    vkd,
578                                                                                   vk::VkDevice                                  device,
579                                                                                   vk::VkDeviceSize                              size,
580                                                                                   deUint32                                              memoryTypeIndex)
581 {
582         const vk::VkMemoryAllocateInfo alloc =
583         {
584                 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,     // sType
585                 DE_NULL,                                                                        // pNext
586
587                 size,
588                 memoryTypeIndex
589         };
590
591         return vk::allocateMemory(vkd, device, &alloc);
592 }
593
594 vk::Move<vk::VkDeviceMemory> bindBufferMemory (const vk::InstanceInterface&     vki,
595                                                                                            const vk::DeviceInterface&   vkd,
596                                                                                            vk::VkPhysicalDevice                 physicalDevice,
597                                                                                            vk::VkDevice                                 device,
598                                                                                            vk::VkBuffer                                 buffer,
599                                                                                            vk::VkMemoryPropertyFlags    properties)
600 {
601         const vk::VkMemoryRequirements                          memoryRequirements      = vk::getBufferMemoryRequirements(vkd, device, buffer);
602         const vk::VkPhysicalDeviceMemoryProperties      memoryProperties        = vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice);
603         deUint32                                                                        memoryTypeIndex;
604
605         for (memoryTypeIndex = 0; memoryTypeIndex < memoryProperties.memoryTypeCount; memoryTypeIndex++)
606         {
607                 if ((memoryRequirements.memoryTypeBits & (0x1u << memoryTypeIndex))
608                         && (memoryProperties.memoryTypes[memoryTypeIndex].propertyFlags & properties) == properties)
609                 {
610                         try
611                         {
612                                 const vk::VkMemoryAllocateInfo  allocationInfo  =
613                                 {
614                                         vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
615                                         DE_NULL,
616                                         memoryRequirements.size,
617                                         memoryTypeIndex
618                                 };
619                                 vk::Move<vk::VkDeviceMemory>    memory                  (vk::allocateMemory(vkd, device, &allocationInfo));
620
621                                 VK_CHECK(vkd.bindBufferMemory(device, buffer, *memory, 0));
622
623                                 return memory;
624                         }
625                         catch (const vk::Error& error)
626                         {
627                                 if (error.getError() == vk::VK_ERROR_OUT_OF_DEVICE_MEMORY
628                                         || error.getError() == vk::VK_ERROR_OUT_OF_HOST_MEMORY)
629                                 {
630                                         // Try next memory type/heap if out of memory
631                                 }
632                                 else
633                                 {
634                                         // Throw all other errors forward
635                                         throw;
636                                 }
637                         }
638                 }
639         }
640
641         TCU_FAIL("Failed to allocate memory for buffer");
642 }
643
644 vk::Move<vk::VkDeviceMemory> bindImageMemory (const vk::InstanceInterface&      vki,
645                                                                                            const vk::DeviceInterface&   vkd,
646                                                                                            vk::VkPhysicalDevice                 physicalDevice,
647                                                                                            vk::VkDevice                                 device,
648                                                                                            vk::VkImage                                  image,
649                                                                                            vk::VkMemoryPropertyFlags    properties)
650 {
651         const vk::VkMemoryRequirements                          memoryRequirements      = vk::getImageMemoryRequirements(vkd, device, image);
652         const vk::VkPhysicalDeviceMemoryProperties      memoryProperties        = vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice);
653         deUint32                                                                        memoryTypeIndex;
654
655         for (memoryTypeIndex = 0; memoryTypeIndex < memoryProperties.memoryTypeCount; memoryTypeIndex++)
656         {
657                 if ((memoryRequirements.memoryTypeBits & (0x1u << memoryTypeIndex))
658                         && (memoryProperties.memoryTypes[memoryTypeIndex].propertyFlags & properties) == properties)
659                 {
660                         try
661                         {
662                                 const vk::VkMemoryAllocateInfo  allocationInfo  =
663                                 {
664                                         vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
665                                         DE_NULL,
666                                         memoryRequirements.size,
667                                         memoryTypeIndex
668                                 };
669                                 vk::Move<vk::VkDeviceMemory>    memory                  (vk::allocateMemory(vkd, device, &allocationInfo));
670
671                                 VK_CHECK(vkd.bindImageMemory(device, image, *memory, 0));
672
673                                 return memory;
674                         }
675                         catch (const vk::Error& error)
676                         {
677                                 if (error.getError() == vk::VK_ERROR_OUT_OF_DEVICE_MEMORY
678                                         || error.getError() == vk::VK_ERROR_OUT_OF_HOST_MEMORY)
679                                 {
680                                         // Try next memory type/heap if out of memory
681                                 }
682                                 else
683                                 {
684                                         // Throw all other errors forward
685                                         throw;
686                                 }
687                         }
688                 }
689         }
690
691         TCU_FAIL("Failed to allocate memory for image");
692 }
693
694 void queueRun (const vk::DeviceInterface&       vkd,
695                            vk::VkQueue                                  queue,
696                            vk::VkCommandBuffer                  commandBuffer)
697 {
698         const vk::VkSubmitInfo  submitInfo      =
699         {
700                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
701                 DE_NULL,
702
703                 0,
704                 DE_NULL,
705                 (const vk::VkPipelineStageFlags*)DE_NULL,
706
707                 1,
708                 &commandBuffer,
709
710                 0,
711                 DE_NULL
712         };
713
714         VK_CHECK(vkd.queueSubmit(queue, 1, &submitInfo, 0));
715         VK_CHECK(vkd.queueWaitIdle(queue));
716 }
717
718 void* mapMemory (const vk::DeviceInterface&     vkd,
719                                  vk::VkDevice                           device,
720                                  vk::VkDeviceMemory                     memory,
721                                  vk::VkDeviceSize                       size)
722 {
723         void* ptr;
724
725         VK_CHECK(vkd.mapMemory(device, memory, 0, size, 0, &ptr));
726
727         return ptr;
728 }
729
730 class ReferenceMemory
731 {
732 public:
733                         ReferenceMemory (size_t size);
734
735         void    set                             (size_t pos, deUint8 val);
736         deUint8 get                             (size_t pos) const;
737         bool    isDefined               (size_t pos) const;
738
739         void    setDefined              (size_t offset, size_t size, const void* data);
740         void    setUndefined    (size_t offset, size_t size);
741         void    setData                 (size_t offset, size_t size, const void* data);
742
743         size_t  getSize                 (void) const { return m_data.size(); }
744
745 private:
746         vector<deUint8>         m_data;
747         vector<deUint64>        m_defined;
748 };
749
750 ReferenceMemory::ReferenceMemory (size_t size)
751         : m_data        (size, 0)
752         , m_defined     (size / 64 + (size % 64 == 0 ? 0 : 1), 0ull)
753 {
754 }
755
756 void ReferenceMemory::set (size_t pos, deUint8 val)
757 {
758         DE_ASSERT(pos < m_data.size());
759
760         m_data[pos] = val;
761         m_defined[pos / 64] |= 0x1ull << (pos % 64);
762 }
763
764 void ReferenceMemory::setData (size_t offset, size_t size, const void* data_)
765 {
766         const deUint8* data = (const deUint8*)data_;
767
768         DE_ASSERT(offset < m_data.size());
769         DE_ASSERT(offset + size <= m_data.size());
770
771         // \todo [2016-03-09 mika] Optimize
772         for (size_t pos = 0; pos < size; pos++)
773         {
774                 m_data[offset + pos] = data[pos];
775                 m_defined[(offset + pos) / 64] |= 0x1ull << ((offset + pos) % 64);
776         }
777 }
778
779 void ReferenceMemory::setUndefined      (size_t offset, size_t size)
780 {
781         // \todo [2016-03-09 mika] Optimize
782         for (size_t pos = 0; pos < size; pos++)
783                 m_defined[(offset + pos) / 64] |= 0x1ull << ((offset + pos) % 64);
784 }
785
786 deUint8 ReferenceMemory::get (size_t pos) const
787 {
788         DE_ASSERT(pos < m_data.size());
789         DE_ASSERT(isDefined(pos));
790         return m_data[pos];
791 }
792
793 bool ReferenceMemory::isDefined (size_t pos) const
794 {
795         DE_ASSERT(pos < m_data.size());
796
797         return (m_defined[pos / 64] & (0x1ull << (pos % 64))) != 0;
798 }
799
800 class Memory
801 {
802 public:
803                                                         Memory                          (const vk::InstanceInterface&   vki,
804                                                                                                  const vk::DeviceInterface&             vkd,
805                                                                                                  vk::VkPhysicalDevice                   physicalDevice,
806                                                                                                  vk::VkDevice                                   device,
807                                                                                                  vk::VkDeviceSize                               size,
808                                                                                                  deUint32                                               memoryTypeIndex,
809                                                                                                  vk::VkDeviceSize                               maxBufferSize,
810                                                                                                  deInt32                                                maxImageWidth,
811                                                                                                  deInt32                                                maxImageHeight);
812
813         vk::VkDeviceSize                getSize                         (void) const { return m_size; }
814         vk::VkDeviceSize                getMaxBufferSize        (void) const { return m_maxBufferSize; }
815         bool                                    getSupportBuffers       (void) const { return m_maxBufferSize > 0; }
816
817         deInt32                                 getMaxImageWidth        (void) const { return m_maxImageWidth; }
818         deInt32                                 getMaxImageHeight       (void) const { return m_maxImageHeight; }
819         bool                                    getSupportImages        (void) const { return m_maxImageWidth > 0; }
820
821         const vk::VkMemoryType& getMemoryType           (void) const { return m_memoryType; }
822         deUint32                                getMemoryTypeIndex      (void) const { return m_memoryTypeIndex; }
823         vk::VkDeviceMemory              getMemory                       (void) const { return *m_memory; }
824
825 private:
826         const vk::VkDeviceSize                                  m_size;
827         const deUint32                                                  m_memoryTypeIndex;
828         const vk::VkMemoryType                                  m_memoryType;
829         const vk::Unique<vk::VkDeviceMemory>    m_memory;
830         const vk::VkDeviceSize                                  m_maxBufferSize;
831         const deInt32                                                   m_maxImageWidth;
832         const deInt32                                                   m_maxImageHeight;
833 };
834
835 vk::VkMemoryType getMemoryTypeInfo (const vk::InstanceInterface&        vki,
836                                                                         vk::VkPhysicalDevice                    device,
837                                                                         deUint32                                                memoryTypeIndex)
838 {
839         const vk::VkPhysicalDeviceMemoryProperties memoryProperties = vk::getPhysicalDeviceMemoryProperties(vki, device);
840
841         DE_ASSERT(memoryTypeIndex < memoryProperties.memoryTypeCount);
842
843         return memoryProperties.memoryTypes[memoryTypeIndex];
844 }
845
846 vk::VkDeviceSize findMaxBufferSize (const vk::DeviceInterface&          vkd,
847                                                                         vk::VkDevice                                    device,
848
849                                                                         vk::VkBufferUsageFlags                  usage,
850                                                                         vk::VkSharingMode                               sharingMode,
851                                                                         const vector<deUint32>&                 queueFamilies,
852
853                                                                         vk::VkDeviceSize                                memorySize,
854                                                                         deUint32                                                memoryTypeIndex)
855 {
856         vk::VkDeviceSize        lastSuccess     = 0;
857         vk::VkDeviceSize        currentSize     = memorySize / 2;
858
859         {
860                 const vk::Unique<vk::VkBuffer>  buffer                  (createBuffer(vkd, device, memorySize, usage, sharingMode, queueFamilies));
861                 const vk::VkMemoryRequirements  requirements    (vk::getBufferMemoryRequirements(vkd, device, *buffer));
862
863                 if (requirements.size == memorySize && requirements.memoryTypeBits & (0x1u << memoryTypeIndex))
864                         return memorySize;
865         }
866
867         for (vk::VkDeviceSize stepSize = memorySize / 4; currentSize > 0; stepSize /= 2)
868         {
869                 const vk::Unique<vk::VkBuffer>  buffer                  (createBuffer(vkd, device, currentSize, usage, sharingMode, queueFamilies));
870                 const vk::VkMemoryRequirements  requirements    (vk::getBufferMemoryRequirements(vkd, device, *buffer));
871
872                 if (requirements.size <= memorySize && requirements.memoryTypeBits & (0x1u << memoryTypeIndex))
873                 {
874                         lastSuccess = currentSize;
875                         currentSize += stepSize;
876                 }
877                 else
878                         currentSize -= stepSize;
879
880                 if (stepSize == 0)
881                         break;
882         }
883
884         return lastSuccess;
885 }
886
887 // Round size down maximum W * H * 4, where W and H < 4096
888 vk::VkDeviceSize roundBufferSizeToWxHx4 (vk::VkDeviceSize size)
889 {
890         const vk::VkDeviceSize  maxTextureSize  = 4096;
891         vk::VkDeviceSize                maxTexelCount   = size / 4;
892         vk::VkDeviceSize                bestW                   = de::max(maxTexelCount, maxTextureSize);
893         vk::VkDeviceSize                bestH                   = maxTexelCount / bestW;
894
895         // \todo [2016-03-09 mika] Could probably be faster?
896         for (vk::VkDeviceSize w = 1; w * w < maxTexelCount && w < maxTextureSize && bestW * bestH * 4 < size; w++)
897         {
898                 const vk::VkDeviceSize h = maxTexelCount / w;
899
900                 if (bestW * bestH < w * h)
901                 {
902                         bestW = w;
903                         bestH = h;
904                 }
905         }
906
907         return bestW * bestH * 4;
908 }
909
910 // Find RGBA8 image size that has exactly "size" of number of bytes.
911 // "size" must be W * H * 4 where W and H < 4096
912 IVec2 findImageSizeWxHx4 (vk::VkDeviceSize size)
913 {
914         const vk::VkDeviceSize  maxTextureSize  = 4096;
915         vk::VkDeviceSize                texelCount              = size / 4;
916
917         DE_ASSERT((size % 4) == 0);
918
919         // \todo [2016-03-09 mika] Could probably be faster?
920         for (vk::VkDeviceSize w = 1; w < maxTextureSize && w < texelCount; w++)
921         {
922                 const vk::VkDeviceSize  h       = texelCount / w;
923
924                 if ((texelCount  % w) == 0 && h < maxTextureSize)
925                         return IVec2((int)w, (int)h);
926         }
927
928         DE_FATAL("Invalid size");
929         return IVec2(-1, -1);
930 }
931
932 IVec2 findMaxRGBA8ImageSize (const vk::DeviceInterface& vkd,
933                                                          vk::VkDevice                           device,
934
935                                                          vk::VkImageUsageFlags          usage,
936                                                          vk::VkSharingMode                      sharingMode,
937                                                          const vector<deUint32>&        queueFamilies,
938
939                                                          vk::VkDeviceSize                       memorySize,
940                                                          deUint32                                       memoryTypeIndex)
941 {
942         IVec2           lastSuccess             (0);
943         IVec2           currentSize;
944
945         {
946                 const deUint32  texelCount      = (deUint32)(memorySize / 4);
947                 const deUint32  width           = (deUint32)deFloatSqrt((float)texelCount);
948                 const deUint32  height          = texelCount / width;
949
950                 currentSize[0] = deMaxu32(width, height);
951                 currentSize[1] = deMinu32(width, height);
952         }
953
954         for (deInt32 stepSize = currentSize[0] / 2; currentSize[0] > 0; stepSize /= 2)
955         {
956                 const vk::VkImageCreateInfo     createInfo              =
957                 {
958                         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
959                         DE_NULL,
960
961                         0u,
962                         vk::VK_IMAGE_TYPE_2D,
963                         vk::VK_FORMAT_R8G8B8A8_UNORM,
964                         {
965                                 (deUint32)currentSize[0],
966                                 (deUint32)currentSize[1],
967                                 1u,
968                         },
969                         1u, 1u,
970                         vk::VK_SAMPLE_COUNT_1_BIT,
971                         vk::VK_IMAGE_TILING_OPTIMAL,
972                         usage,
973                         sharingMode,
974                         (deUint32)queueFamilies.size(),
975                         &queueFamilies[0],
976                         vk::VK_IMAGE_LAYOUT_UNDEFINED
977                 };
978                 const vk::Unique<vk::VkImage>   image                   (vk::createImage(vkd, device, &createInfo));
979                 const vk::VkMemoryRequirements  requirements    (vk::getImageMemoryRequirements(vkd, device, *image));
980
981                 if (requirements.size <= memorySize && requirements.memoryTypeBits & (0x1u << memoryTypeIndex))
982                 {
983                         lastSuccess = currentSize;
984                         currentSize[0] += stepSize;
985                         currentSize[1] += stepSize;
986                 }
987                 else
988                 {
989                         currentSize[0] -= stepSize;
990                         currentSize[1] -= stepSize;
991                 }
992
993                 if (stepSize == 0)
994                         break;
995         }
996
997         return lastSuccess;
998 }
999
1000 Memory::Memory (const vk::InstanceInterface&    vki,
1001                                 const vk::DeviceInterface&              vkd,
1002                                 vk::VkPhysicalDevice                    physicalDevice,
1003                                 vk::VkDevice                                    device,
1004                                 vk::VkDeviceSize                                size,
1005                                 deUint32                                                memoryTypeIndex,
1006                                 vk::VkDeviceSize                                maxBufferSize,
1007                                 deInt32                                                 maxImageWidth,
1008                                 deInt32                                                 maxImageHeight)
1009         : m_size                        (size)
1010         , m_memoryTypeIndex     (memoryTypeIndex)
1011         , m_memoryType          (getMemoryTypeInfo(vki, physicalDevice, memoryTypeIndex))
1012         , m_memory                      (allocMemory(vkd, device, size, memoryTypeIndex))
1013         , m_maxBufferSize       (maxBufferSize)
1014         , m_maxImageWidth       (maxImageWidth)
1015         , m_maxImageHeight      (maxImageHeight)
1016 {
1017 }
1018
1019 class Context
1020 {
1021 public:
1022                                                                                                         Context                                 (const vk::InstanceInterface&                                           vki,
1023                                                                                                                                                          const vk::DeviceInterface&                                                     vkd,
1024                                                                                                                                                          vk::VkPhysicalDevice                                                           physicalDevice,
1025                                                                                                                                                          vk::VkDevice                                                                           device,
1026                                                                                                                                                          vk::VkQueue                                                                            queue,
1027                                                                                                                                                          deUint32                                                                                       queueFamilyIndex,
1028                                                                                                                                                          const vector<pair<deUint32, vk::VkQueue> >&            queues,
1029                                                                                                                                                          const vk::ProgramCollection<vk::ProgramBinary>&        binaryCollection)
1030                 : m_vki                                 (vki)
1031                 , m_vkd                                 (vkd)
1032                 , m_physicalDevice              (physicalDevice)
1033                 , m_device                              (device)
1034                 , m_queue                               (queue)
1035                 , m_queueFamilyIndex    (queueFamilyIndex)
1036                 , m_queues                              (queues)
1037                 , m_commandPool                 (createCommandPool(vkd, device, queueFamilyIndex))
1038                 , m_binaryCollection    (binaryCollection)
1039         {
1040                 for (size_t queueNdx = 0; queueNdx < m_queues.size(); queueNdx++)
1041                         m_queueFamilies.push_back(m_queues[queueNdx].first);
1042         }
1043
1044         const vk::InstanceInterface&                                    getInstanceInterface    (void) const { return m_vki; }
1045         vk::VkPhysicalDevice                                                    getPhysicalDevice               (void) const { return m_physicalDevice; }
1046         vk::VkDevice                                                                    getDevice                               (void) const { return m_device; }
1047         const vk::DeviceInterface&                                              getDeviceInterface              (void) const { return m_vkd; }
1048         vk::VkQueue                                                                             getQueue                                (void) const { return m_queue; }
1049         deUint32                                                                                getQueueFamily                  (void) const { return m_queueFamilyIndex; }
1050         const vector<pair<deUint32, vk::VkQueue> >&             getQueues                               (void) const { return m_queues; }
1051         const vector<deUint32>                                                  getQueueFamilies                (void) const { return m_queueFamilies; }
1052         vk::VkCommandPool                                                               getCommandPool                  (void) const { return *m_commandPool; }
1053         const vk::ProgramCollection<vk::ProgramBinary>& getBinaryCollection             (void) const { return m_binaryCollection; }
1054
1055 private:
1056         const vk::InstanceInterface&                                    m_vki;
1057         const vk::DeviceInterface&                                              m_vkd;
1058         const vk::VkPhysicalDevice                                              m_physicalDevice;
1059         const vk::VkDevice                                                              m_device;
1060         const vk::VkQueue                                                               m_queue;
1061         const deUint32                                                                  m_queueFamilyIndex;
1062         const vector<pair<deUint32, vk::VkQueue> >              m_queues;
1063         const vk::Unique<vk::VkCommandPool>                             m_commandPool;
1064         const vk::ProgramCollection<vk::ProgramBinary>& m_binaryCollection;
1065         vector<deUint32>                                                                m_queueFamilies;
1066 };
1067
1068 class PrepareContext
1069 {
1070 public:
1071                                                                                                         PrepareContext                  (const Context& context,
1072                                                                                                                                                          const Memory&  memory)
1073                 : m_context     (context)
1074                 , m_memory      (memory)
1075         {
1076         }
1077
1078         const Memory&                                                                   getMemory                               (void) const { return m_memory; }
1079         const Context&                                                                  getContext                              (void) const { return m_context; }
1080         const vk::ProgramCollection<vk::ProgramBinary>& getBinaryCollection             (void) const { return m_context.getBinaryCollection(); }
1081
1082         void                            setBuffer               (vk::Move<vk::VkBuffer> buffer,
1083                                                                                  vk::VkDeviceSize               size)
1084         {
1085                 DE_ASSERT(!m_currentImage);
1086                 DE_ASSERT(!m_currentBuffer);
1087
1088                 m_currentBuffer         = buffer;
1089                 m_currentBufferSize     = size;
1090         }
1091
1092         vk::VkBuffer            getBuffer               (void) const { return *m_currentBuffer; }
1093         vk::VkDeviceSize        getBufferSize   (void) const
1094         {
1095                 DE_ASSERT(m_currentBuffer);
1096                 return m_currentBufferSize;
1097         }
1098
1099         void                            releaseBuffer   (void) { m_currentBuffer.disown(); }
1100
1101         void                            setImage                (vk::Move<vk::VkImage>  image,
1102                                                                                  vk::VkImageLayout              layout,
1103                                                                                  vk::VkDeviceSize               memorySize,
1104                                                                                  deInt32                                width,
1105                                                                                  deInt32                                height)
1106         {
1107                 DE_ASSERT(!m_currentImage);
1108                 DE_ASSERT(!m_currentBuffer);
1109
1110                 m_currentImage                          = image;
1111                 m_currentImageMemorySize        = memorySize;
1112                 m_currentImageLayout            = layout;
1113                 m_currentImageWidth                     = width;
1114                 m_currentImageHeight            = height;
1115         }
1116
1117         void                            setImageLayout  (vk::VkImageLayout layout)
1118         {
1119                 DE_ASSERT(m_currentImage);
1120                 m_currentImageLayout = layout;
1121         }
1122
1123         vk::VkImage                     getImage                (void) const { return *m_currentImage; }
1124         deInt32                         getImageWidth   (void) const
1125         {
1126                 DE_ASSERT(m_currentImage);
1127                 return m_currentImageWidth;
1128         }
1129         deInt32                         getImageHeight  (void) const
1130         {
1131                 DE_ASSERT(m_currentImage);
1132                 return m_currentImageHeight;
1133         }
1134         vk::VkDeviceSize        getImageMemorySize      (void) const
1135         {
1136                 DE_ASSERT(m_currentImage);
1137                 return m_currentImageMemorySize;
1138         }
1139
1140         void                            releaseImage    (void) { m_currentImage.disown(); }
1141
1142         vk::VkImageLayout       getImageLayout  (void) const
1143         {
1144                 DE_ASSERT(m_currentImage);
1145                 return m_currentImageLayout;
1146         }
1147
1148 private:
1149         const Context&                  m_context;
1150         const Memory&                   m_memory;
1151
1152         vk::Move<vk::VkBuffer>  m_currentBuffer;
1153         vk::VkDeviceSize                m_currentBufferSize;
1154
1155         vk::Move<vk::VkImage>   m_currentImage;
1156         vk::VkDeviceSize                m_currentImageMemorySize;
1157         vk::VkImageLayout               m_currentImageLayout;
1158         deInt32                                 m_currentImageWidth;
1159         deInt32                                 m_currentImageHeight;
1160 };
1161
1162 class ExecuteContext
1163 {
1164 public:
1165                                         ExecuteContext  (const Context& context)
1166                 : m_context     (context)
1167         {
1168         }
1169
1170         const Context&  getContext              (void) const { return m_context; }
1171         void                    setMapping              (void* ptr) { m_mapping = ptr; }
1172         void*                   getMapping              (void) const { return m_mapping; }
1173
1174 private:
1175         const Context&  m_context;
1176         void*                   m_mapping;
1177 };
1178
1179 class VerifyContext
1180 {
1181 public:
1182                                                         VerifyContext           (TestLog&                               log,
1183                                                                                                  tcu::ResultCollector&  resultCollector,
1184                                                                                                  const Context&                 context,
1185                                                                                                  vk::VkDeviceSize               size)
1186                 : m_log                         (log)
1187                 , m_resultCollector     (resultCollector)
1188                 , m_context                     (context)
1189                 , m_reference           ((size_t)size)
1190         {
1191         }
1192
1193         const Context&                  getContext                      (void) const { return m_context; }
1194         TestLog&                                getLog                          (void) const { return m_log; }
1195         tcu::ResultCollector&   getResultCollector      (void) const { return m_resultCollector; }
1196
1197         ReferenceMemory&                getReference            (void) { return m_reference; }
1198         TextureLevel&                   getReferenceImage       (void) { return m_referenceImage;}
1199
1200 private:
1201         TestLog&                                m_log;
1202         tcu::ResultCollector&   m_resultCollector;
1203         const Context&                  m_context;
1204         ReferenceMemory                 m_reference;
1205         TextureLevel                    m_referenceImage;
1206 };
1207
1208 class Command
1209 {
1210 public:
1211         // Constructor should allocate all non-vulkan resources.
1212         virtual                         ~Command        (void) {}
1213
1214         // Get name of the command
1215         virtual const char*     getName         (void) const = 0;
1216
1217         // Log prepare operations
1218         virtual void            logPrepare      (TestLog&, size_t) const {}
1219         // Log executed operations
1220         virtual void            logExecute      (TestLog&, size_t) const {}
1221
1222         // Prepare should allocate all vulkan resources and resources that require
1223         // that buffer or memory has been already allocated. This should build all
1224         // command buffers etc.
1225         virtual void            prepare         (PrepareContext&) {}
1226
1227         // Execute command. Write or read mapped memory, submit commands to queue
1228         // etc.
1229         virtual void            execute         (ExecuteContext&) {}
1230
1231         // Verify that results are correct.
1232         virtual void            verify          (VerifyContext&, size_t) {}
1233
1234 protected:
1235         // Allow only inheritance
1236                                                 Command         (void) {}
1237
1238 private:
1239         // Disallow copying
1240                                                 Command         (const Command&);
1241         Command&                        operator&       (const Command&);
1242 };
1243
1244 class Map : public Command
1245 {
1246 public:
1247                                                 Map                     (void) {}
1248                                                 ~Map            (void) {}
1249         const char*                     getName         (void) const { return "Map"; }
1250
1251
1252         void                            logExecute      (TestLog& log, size_t commandIndex) const
1253         {
1254                 log << TestLog::Message << commandIndex << ":" << getName() << " Map memory" << TestLog::EndMessage;
1255         }
1256
1257         void                            prepare         (PrepareContext& context)
1258         {
1259                 m_memory        = context.getMemory().getMemory();
1260                 m_size          = context.getMemory().getSize();
1261         }
1262
1263         void                            execute         (ExecuteContext& context)
1264         {
1265                 const vk::DeviceInterface&      vkd             = context.getContext().getDeviceInterface();
1266                 const vk::VkDevice                      device  = context.getContext().getDevice();
1267
1268                 context.setMapping(mapMemory(vkd, device, m_memory, m_size));
1269         }
1270
1271 private:
1272         vk::VkDeviceMemory      m_memory;
1273         vk::VkDeviceSize        m_size;
1274 };
1275
1276 class UnMap : public Command
1277 {
1278 public:
1279                                                 UnMap           (void) {}
1280                                                 ~UnMap          (void) {}
1281         const char*                     getName         (void) const { return "UnMap"; }
1282
1283         void                            logExecute      (TestLog& log, size_t commandIndex) const
1284         {
1285                 log << TestLog::Message << commandIndex << ": Unmap memory" << TestLog::EndMessage;
1286         }
1287
1288         void                            prepare         (PrepareContext& context)
1289         {
1290                 m_memory        = context.getMemory().getMemory();
1291         }
1292
1293         void                            execute         (ExecuteContext& context)
1294         {
1295                 const vk::DeviceInterface&      vkd             = context.getContext().getDeviceInterface();
1296                 const vk::VkDevice                      device  = context.getContext().getDevice();
1297
1298                 vkd.unmapMemory(device, m_memory);
1299                 context.setMapping(DE_NULL);
1300         }
1301
1302 private:
1303         vk::VkDeviceMemory      m_memory;
1304 };
1305
1306 class Invalidate : public Command
1307 {
1308 public:
1309                                                 Invalidate      (void) {}
1310                                                 ~Invalidate     (void) {}
1311         const char*                     getName         (void) const { return "Invalidate"; }
1312
1313         void                            logExecute      (TestLog& log, size_t commandIndex) const
1314         {
1315                 log << TestLog::Message << commandIndex << ": Invalidate mapped memory" << TestLog::EndMessage;
1316         }
1317
1318         void                            prepare         (PrepareContext& context)
1319         {
1320                 m_memory        = context.getMemory().getMemory();
1321                 m_size          = context.getMemory().getSize();
1322         }
1323
1324         void                            execute         (ExecuteContext& context)
1325         {
1326                 const vk::DeviceInterface&      vkd             = context.getContext().getDeviceInterface();
1327                 const vk::VkDevice                      device  = context.getContext().getDevice();
1328
1329                 vk::invalidateMappedMemoryRange(vkd, device, m_memory, 0, m_size);
1330         }
1331
1332 private:
1333         vk::VkDeviceMemory      m_memory;
1334         vk::VkDeviceSize        m_size;
1335 };
1336
1337 class Flush : public Command
1338 {
1339 public:
1340                                                 Flush           (void) {}
1341                                                 ~Flush          (void) {}
1342         const char*                     getName         (void) const { return "Flush"; }
1343
1344         void                            logExecute      (TestLog& log, size_t commandIndex) const
1345         {
1346                 log << TestLog::Message << commandIndex << ": Flush mapped memory" << TestLog::EndMessage;
1347         }
1348
1349         void                            prepare         (PrepareContext& context)
1350         {
1351                 m_memory        = context.getMemory().getMemory();
1352                 m_size          = context.getMemory().getSize();
1353         }
1354
1355         void                            execute         (ExecuteContext& context)
1356         {
1357                 const vk::DeviceInterface&      vkd             = context.getContext().getDeviceInterface();
1358                 const vk::VkDevice                      device  = context.getContext().getDevice();
1359
1360                 vk::flushMappedMemoryRange(vkd, device, m_memory, 0, m_size);
1361         }
1362
1363 private:
1364         vk::VkDeviceMemory      m_memory;
1365         vk::VkDeviceSize        m_size;
1366 };
1367
1368 // Host memory reads and writes
1369 class HostMemoryAccess : public Command
1370 {
1371 public:
1372                                         HostMemoryAccess        (bool read, bool write, deUint32 seed);
1373                                         ~HostMemoryAccess       (void) {}
1374         const char*             getName                         (void) const { return "HostMemoryAccess"; }
1375
1376         void                    logExecute                      (TestLog& log, size_t commandIndex) const;
1377         void                    prepare                         (PrepareContext& context);
1378         void                    execute                         (ExecuteContext& context);
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                                 context.getImageLayout()
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                                 context.getImageLayout()
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                 {
6272                         (deUint32)descriptorSetNdx,
6273                         (deUint32)divRoundUp<size_t>(m_descriptorSets.size() * (MAX_UNIFORM_BUFFER_SIZE / 4), m_targetWidth * m_targetHeight)
6274                 };
6275
6276                 vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &m_descriptorSets[descriptorSetNdx], 0u, DE_NULL);
6277                 vkd.cmdPushConstants(commandBuffer, *m_resources.pipelineLayout, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, (deUint32)sizeof(callParams), &callParams);
6278                 vkd.cmdDraw(commandBuffer, 6, 1, 0, 0);
6279         }
6280 }
6281
6282 void RenderFragmentUniformBuffer::verify (VerifyRenderPassContext& context, size_t)
6283 {
6284         const deUint32  valuesPerPixel  = (deUint32)divRoundUp<size_t>(m_descriptorSets.size() * (MAX_UNIFORM_BUFFER_SIZE / 4), m_targetWidth * m_targetHeight);
6285         const size_t    arraySize               = MAX_UNIFORM_BUFFER_SIZE / (sizeof(deUint32) * 4);
6286         const size_t    arrayIntSize    = arraySize * 4;
6287
6288         for (int y = 0; y < context.getReferenceTarget().getSize().y(); y++)
6289         for (int x = 0; x < context.getReferenceTarget().getSize().x(); x++)
6290         {
6291                 const size_t firstDescriptorSetNdx = de::min<size_t>((y * 256u + x) / (arrayIntSize / valuesPerPixel), m_descriptorSets.size() - 1);
6292
6293                 for (size_t descriptorSetNdx = firstDescriptorSetNdx; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
6294                 {
6295                         const size_t    offset  = descriptorSetNdx * MAX_UNIFORM_BUFFER_SIZE;
6296                         const deUint32  callId  = (deUint32)descriptorSetNdx;
6297
6298                         const deUint32  id              = callId * ((deUint32)arrayIntSize / valuesPerPixel) + (deUint32)y * 256u + (deUint32)x;
6299
6300                         if (y * 256u + x < callId * (arrayIntSize / valuesPerPixel))
6301                                 continue;
6302                         else
6303                         {
6304                                 deUint32 value = id;
6305
6306                                 for (deUint32 i = 0; i < valuesPerPixel; i++)
6307                                 {
6308                                         value   = ((deUint32)context.getReference().get(offset + (value % (MAX_UNIFORM_BUFFER_SIZE / sizeof(deUint32))) * 4 + 0))
6309                                                         | (((deUint32)context.getReference().get(offset + (value % (MAX_UNIFORM_BUFFER_SIZE / sizeof(deUint32))) * 4 + 1)) << 8u)
6310                                                         | (((deUint32)context.getReference().get(offset + (value % (MAX_UNIFORM_BUFFER_SIZE / sizeof(deUint32))) * 4 + 2)) << 16u)
6311                                                         | (((deUint32)context.getReference().get(offset + (value % (MAX_UNIFORM_BUFFER_SIZE / sizeof(deUint32))) * 4 + 3)) << 24u);
6312
6313                                 }
6314                                 const UVec4     vec     ((value >>  0u) & 0xFFu,
6315                                                                  (value >>  8u) & 0xFFu,
6316                                                                  (value >> 16u) & 0xFFu,
6317                                                                  (value >> 24u) & 0xFFu);
6318
6319                                 context.getReferenceTarget().getAccess().setPixel(vec.asFloat() / Vec4(255.0f), x, y);
6320                         }
6321                 }
6322         }
6323 }
6324
6325 class RenderFragmentStorageBuffer : public RenderPassCommand
6326 {
6327 public:
6328                                                                         RenderFragmentStorageBuffer             (void) {}
6329                                                                         ~RenderFragmentStorageBuffer    (void);
6330
6331         const char*                                             getName                                                 (void) const { return "RenderFragmentStorageBuffer"; }
6332         void                                                    logPrepare                                              (TestLog&, size_t) const;
6333         void                                                    logSubmit                                               (TestLog&, size_t) const;
6334         void                                                    prepare                                                 (PrepareRenderPassContext&);
6335         void                                                    submit                                                  (SubmitContext& context);
6336         void                                                    verify                                                  (VerifyRenderPassContext&, size_t);
6337
6338 private:
6339         PipelineResources                               m_resources;
6340         vk::Move<vk::VkDescriptorPool>  m_descriptorPool;
6341         vk::Move<vk::VkDescriptorSet>   m_descriptorSet;
6342
6343         vk::VkDeviceSize                                m_bufferSize;
6344         size_t                                                  m_targetWidth;
6345         size_t                                                  m_targetHeight;
6346 };
6347
6348 RenderFragmentStorageBuffer::~RenderFragmentStorageBuffer (void)
6349 {
6350 }
6351
6352 void RenderFragmentStorageBuffer::logPrepare (TestLog& log, size_t commandIndex) const
6353 {
6354         log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline to render buffer as storage buffer." << TestLog::EndMessage;
6355 }
6356
6357 void RenderFragmentStorageBuffer::logSubmit (TestLog& log, size_t commandIndex) const
6358 {
6359         log << TestLog::Message << commandIndex << ":" << getName() << " Render using buffer as storage buffer." << TestLog::EndMessage;
6360 }
6361
6362 void RenderFragmentStorageBuffer::prepare (PrepareRenderPassContext& context)
6363 {
6364         const vk::DeviceInterface&                                      vkd                                             = context.getContext().getDeviceInterface();
6365         const vk::VkDevice                                                      device                                  = context.getContext().getDevice();
6366         const vk::VkRenderPass                                          renderPass                              = context.getRenderPass();
6367         const deUint32                                                          subpass                                 = 0;
6368         const vk::Unique<vk::VkShaderModule>            vertexShaderModule              (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-quad.vert"), 0));
6369         const vk::Unique<vk::VkShaderModule>            fragmentShaderModule    (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("storage-buffer.frag"), 0));
6370         vector<vk::VkDescriptorSetLayoutBinding>        bindings;
6371
6372         m_bufferSize    = context.getBufferSize();
6373         m_targetWidth   = context.getTargetWidth();
6374         m_targetHeight  = context.getTargetHeight();
6375
6376         {
6377                 const vk::VkDescriptorSetLayoutBinding binding =
6378                 {
6379                         0u,
6380                         vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
6381                         1,
6382                         vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6383                         DE_NULL
6384                 };
6385
6386                 bindings.push_back(binding);
6387         }
6388         const vk::VkPushConstantRange pushConstantRange =
6389         {
6390                 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6391                 0u,
6392                 12u
6393         };
6394
6395         createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
6396                                                                 vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), bindings, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 1u, &pushConstantRange, m_resources);
6397
6398         {
6399                 const deUint32                                                  descriptorCount = 1;
6400                 const vk::VkDescriptorPoolSize                  poolSizes               =
6401                 {
6402                         vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
6403                         descriptorCount
6404                 };
6405                 const vk::VkDescriptorPoolCreateInfo    createInfo              =
6406                 {
6407                         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
6408                         DE_NULL,
6409                         vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
6410
6411                         descriptorCount,
6412                         1u,
6413                         &poolSizes,
6414                 };
6415
6416                 m_descriptorPool = vk::createDescriptorPool(vkd, device, &createInfo);
6417         }
6418
6419         {
6420                 const vk::VkDescriptorSetLayout                 layout                  = *m_resources.descriptorSetLayout;
6421                 const vk::VkDescriptorSetAllocateInfo   allocateInfo    =
6422                 {
6423                         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
6424                         DE_NULL,
6425
6426                         *m_descriptorPool,
6427                         1,
6428                         &layout
6429                 };
6430
6431                 m_descriptorSet = vk::allocateDescriptorSet(vkd, device, &allocateInfo);
6432
6433                 {
6434                         const vk::VkDescriptorBufferInfo        bufferInfo      =
6435                         {
6436                                 context.getBuffer(),
6437                                 0u,
6438                                 m_bufferSize
6439                         };
6440                         const vk::VkWriteDescriptorSet          write           =
6441                         {
6442                                 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
6443                                 DE_NULL,
6444                                 m_descriptorSet.get(),
6445                                 0u,
6446                                 0u,
6447                                 1u,
6448                                 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
6449                                 DE_NULL,
6450                                 &bufferInfo,
6451                                 DE_NULL,
6452                         };
6453
6454                         vkd.updateDescriptorSets(device, 1u, &write, 0u, DE_NULL);
6455                 }
6456         }
6457 }
6458
6459 void RenderFragmentStorageBuffer::submit (SubmitContext& context)
6460 {
6461         const vk::DeviceInterface&      vkd                             = context.getContext().getDeviceInterface();
6462         const vk::VkCommandBuffer       commandBuffer   = context.getCommandBuffer();
6463
6464         vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
6465
6466         const struct
6467         {
6468                 const deUint32  valuesPerPixel;
6469                 const deUint32  bufferSize;
6470         } callParams =
6471         {
6472                 (deUint32)divRoundUp<vk::VkDeviceSize>(m_bufferSize / 4, m_targetWidth * m_targetHeight),
6473                 (deUint32)m_bufferSize
6474         };
6475
6476         vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
6477         vkd.cmdPushConstants(commandBuffer, *m_resources.pipelineLayout, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, (deUint32)sizeof(callParams), &callParams);
6478         vkd.cmdDraw(commandBuffer, 6, 1, 0, 0);
6479 }
6480
6481 void RenderFragmentStorageBuffer::verify (VerifyRenderPassContext& context, size_t)
6482 {
6483         const deUint32  valuesPerPixel  = (deUint32)divRoundUp<vk::VkDeviceSize>(m_bufferSize / 4, m_targetWidth * m_targetHeight);
6484
6485         for (int y = 0; y < context.getReferenceTarget().getSize().y(); y++)
6486         for (int x = 0; x < context.getReferenceTarget().getSize().x(); x++)
6487         {
6488                 const deUint32  id              = (deUint32)y * 256u + (deUint32)x;
6489
6490                 deUint32 value = id;
6491
6492                 for (deUint32 i = 0; i < valuesPerPixel; i++)
6493                 {
6494                         value   = (((deUint32)context.getReference().get((size_t)(value % (m_bufferSize / sizeof(deUint32))) * 4 + 0)) << 0u)
6495                                         | (((deUint32)context.getReference().get((size_t)(value % (m_bufferSize / sizeof(deUint32))) * 4 + 1)) << 8u)
6496                                         | (((deUint32)context.getReference().get((size_t)(value % (m_bufferSize / sizeof(deUint32))) * 4 + 2)) << 16u)
6497                                         | (((deUint32)context.getReference().get((size_t)(value % (m_bufferSize / sizeof(deUint32))) * 4 + 3)) << 24u);
6498
6499                 }
6500                 const UVec4     vec     ((value >>  0u) & 0xFFu,
6501                                                  (value >>  8u) & 0xFFu,
6502                                                  (value >> 16u) & 0xFFu,
6503                                                  (value >> 24u) & 0xFFu);
6504
6505                 context.getReferenceTarget().getAccess().setPixel(vec.asFloat() / Vec4(255.0f), x, y);
6506         }
6507 }
6508
6509 class RenderFragmentUniformTexelBuffer : public RenderPassCommand
6510 {
6511 public:
6512                                                                         RenderFragmentUniformTexelBuffer        (void) {}
6513                                                                         ~RenderFragmentUniformTexelBuffer       (void);
6514
6515         const char*                                             getName                                                         (void) const { return "RenderFragmentUniformTexelBuffer"; }
6516         void                                                    logPrepare                                                      (TestLog&, size_t) const;
6517         void                                                    logSubmit                                                       (TestLog&, size_t) const;
6518         void                                                    prepare                                                         (PrepareRenderPassContext&);
6519         void                                                    submit                                                          (SubmitContext& context);
6520         void                                                    verify                                                          (VerifyRenderPassContext&, size_t);
6521
6522 private:
6523         PipelineResources                               m_resources;
6524         vk::Move<vk::VkDescriptorPool>  m_descriptorPool;
6525         vector<vk::VkDescriptorSet>             m_descriptorSets;
6526         vector<vk::VkBufferView>                m_bufferViews;
6527
6528         const vk::DeviceInterface*              m_vkd;
6529         vk::VkDevice                                    m_device;
6530         vk::VkDeviceSize                                m_bufferSize;
6531         deUint32                                                m_maxUniformTexelCount;
6532         size_t                                                  m_targetWidth;
6533         size_t                                                  m_targetHeight;
6534 };
6535
6536 RenderFragmentUniformTexelBuffer::~RenderFragmentUniformTexelBuffer (void)
6537 {
6538         for (size_t bufferViewNdx = 0; bufferViewNdx < m_bufferViews.size(); bufferViewNdx++)
6539         {
6540                 if (!!m_bufferViews[bufferViewNdx])
6541                 {
6542                         m_vkd->destroyBufferView(m_device, m_bufferViews[bufferViewNdx], DE_NULL);
6543                         m_bufferViews[bufferViewNdx] = (vk::VkBufferView)0;
6544                 }
6545         }
6546 }
6547
6548 void RenderFragmentUniformTexelBuffer::logPrepare (TestLog& log, size_t commandIndex) const
6549 {
6550         log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render buffer as uniform buffer." << TestLog::EndMessage;
6551 }
6552
6553 void RenderFragmentUniformTexelBuffer::logSubmit (TestLog& log, size_t commandIndex) const
6554 {
6555         log << TestLog::Message << commandIndex << ":" << getName() << " Render using buffer as uniform buffer." << TestLog::EndMessage;
6556 }
6557
6558 void RenderFragmentUniformTexelBuffer::prepare (PrepareRenderPassContext& context)
6559 {
6560         const vk::InstanceInterface&                            vki                                             = context.getContext().getInstanceInterface();
6561         const vk::VkPhysicalDevice                                      physicalDevice                  = context.getContext().getPhysicalDevice();
6562         const vk::DeviceInterface&                                      vkd                                             = context.getContext().getDeviceInterface();
6563         const vk::VkDevice                                                      device                                  = context.getContext().getDevice();
6564         const vk::VkRenderPass                                          renderPass                              = context.getRenderPass();
6565         const deUint32                                                          subpass                                 = 0;
6566         const vk::Unique<vk::VkShaderModule>            vertexShaderModule              (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-quad.vert"), 0));
6567         const vk::Unique<vk::VkShaderModule>            fragmentShaderModule    (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("uniform-texel-buffer.frag"), 0));
6568         vector<vk::VkDescriptorSetLayoutBinding>        bindings;
6569
6570         m_device                                = device;
6571         m_vkd                                   = &vkd;
6572         m_bufferSize                    = context.getBufferSize();
6573         m_maxUniformTexelCount  = vk::getPhysicalDeviceProperties(vki, physicalDevice).limits.maxTexelBufferElements;
6574         m_targetWidth                   = context.getTargetWidth();
6575         m_targetHeight                  = context.getTargetHeight();
6576
6577         {
6578                 const vk::VkDescriptorSetLayoutBinding binding =
6579                 {
6580                         0u,
6581                         vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
6582                         1,
6583                         vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6584                         DE_NULL
6585                 };
6586
6587                 bindings.push_back(binding);
6588         }
6589         const vk::VkPushConstantRange pushConstantRange =
6590         {
6591                 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6592                 0u,
6593                 12u
6594         };
6595
6596         createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
6597                                                                 vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), bindings, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 1u, &pushConstantRange, m_resources);
6598
6599         {
6600                 const deUint32                                                  descriptorCount = (deUint32)(divRoundUp(m_bufferSize, (vk::VkDeviceSize)m_maxUniformTexelCount * 4));
6601                 const vk::VkDescriptorPoolSize                  poolSizes               =
6602                 {
6603                         vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
6604                         descriptorCount
6605                 };
6606                 const vk::VkDescriptorPoolCreateInfo    createInfo              =
6607                 {
6608                         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
6609                         DE_NULL,
6610                         vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
6611
6612                         descriptorCount,
6613                         1u,
6614                         &poolSizes,
6615                 };
6616
6617                 m_descriptorPool = vk::createDescriptorPool(vkd, device, &createInfo);
6618                 m_descriptorSets.resize(descriptorCount, (vk::VkDescriptorSet)0);
6619                 m_bufferViews.resize(descriptorCount, (vk::VkBufferView)0);
6620         }
6621
6622         for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
6623         {
6624                 const deUint32                                                  count                   = (deUint32)(m_bufferSize < (descriptorSetNdx + 1) * m_maxUniformTexelCount * 4
6625                                                                                                                                 ? m_bufferSize - descriptorSetNdx * m_maxUniformTexelCount * 4
6626                                                                                                                                 : m_maxUniformTexelCount * 4) / 4;
6627                 const vk::VkDescriptorSetLayout                 layout                  = *m_resources.descriptorSetLayout;
6628                 const vk::VkDescriptorSetAllocateInfo   allocateInfo    =
6629                 {
6630                         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
6631                         DE_NULL,
6632
6633                         *m_descriptorPool,
6634                         1,
6635                         &layout
6636                 };
6637
6638                 m_descriptorSets[descriptorSetNdx] = vk::allocateDescriptorSet(vkd, device, &allocateInfo).disown();
6639
6640                 {
6641                         const vk::VkBufferViewCreateInfo createInfo =
6642                         {
6643                                 vk::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
6644                                 DE_NULL,
6645                                 0u,
6646
6647                                 context.getBuffer(),
6648                                 vk::VK_FORMAT_R32_UINT,
6649                                 descriptorSetNdx * m_maxUniformTexelCount * 4,
6650                                 count * 4
6651                         };
6652
6653                         VK_CHECK(vkd.createBufferView(device, &createInfo, DE_NULL, &m_bufferViews[descriptorSetNdx]));
6654                 }
6655
6656                 {
6657                         const vk::VkWriteDescriptorSet                  write           =
6658                         {
6659                                 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
6660                                 DE_NULL,
6661                                 m_descriptorSets[descriptorSetNdx],
6662                                 0u,
6663                                 0u,
6664                                 1u,
6665                                 vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
6666                                 DE_NULL,
6667                                 DE_NULL,
6668                                 &m_bufferViews[descriptorSetNdx]
6669                         };
6670
6671                         vkd.updateDescriptorSets(device, 1u, &write, 0u, DE_NULL);
6672                 }
6673         }
6674 }
6675
6676 void RenderFragmentUniformTexelBuffer::submit (SubmitContext& context)
6677 {
6678         const vk::DeviceInterface&      vkd                             = context.getContext().getDeviceInterface();
6679         const vk::VkCommandBuffer       commandBuffer   = context.getCommandBuffer();
6680
6681         vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
6682
6683         for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
6684         {
6685                 const struct
6686                 {
6687                         const deUint32  callId;
6688                         const deUint32  valuesPerPixel;
6689                         const deUint32  maxUniformTexelCount;
6690                 } callParams =
6691                 {
6692                         (deUint32)descriptorSetNdx,
6693                         (deUint32)divRoundUp<size_t>(m_descriptorSets.size() * de::min<size_t>((size_t)m_bufferSize / 4, m_maxUniformTexelCount), m_targetWidth * m_targetHeight),
6694                         m_maxUniformTexelCount
6695                 };
6696
6697                 vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &m_descriptorSets[descriptorSetNdx], 0u, DE_NULL);
6698                 vkd.cmdPushConstants(commandBuffer, *m_resources.pipelineLayout, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, (deUint32)sizeof(callParams), &callParams);
6699                 vkd.cmdDraw(commandBuffer, 6, 1, 0, 0);
6700         }
6701 }
6702
6703 void RenderFragmentUniformTexelBuffer::verify (VerifyRenderPassContext& context, size_t)
6704 {
6705         const deUint32  valuesPerPixel  = (deUint32)divRoundUp<size_t>(m_descriptorSets.size() * de::min<size_t>((size_t)m_bufferSize / 4, m_maxUniformTexelCount), m_targetWidth * m_targetHeight);
6706
6707         for (int y = 0; y < context.getReferenceTarget().getSize().y(); y++)
6708         for (int x = 0; x < context.getReferenceTarget().getSize().x(); x++)
6709         {
6710                 const size_t firstDescriptorSetNdx = de::min<size_t>((y * 256u + x) / (m_maxUniformTexelCount / valuesPerPixel), m_descriptorSets.size() - 1);
6711
6712                 for (size_t descriptorSetNdx = firstDescriptorSetNdx; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
6713                 {
6714                         const size_t    offset  = descriptorSetNdx * m_maxUniformTexelCount * 4;
6715                         const deUint32  callId  = (deUint32)descriptorSetNdx;
6716
6717                         const deUint32  id              = (deUint32)y * 256u + (deUint32)x;
6718                         const deUint32  count   = (deUint32)(m_bufferSize < (descriptorSetNdx + 1) * m_maxUniformTexelCount * 4
6719                                                                         ? m_bufferSize - descriptorSetNdx * m_maxUniformTexelCount * 4
6720                                                                         : m_maxUniformTexelCount * 4) / 4;
6721
6722                         if (y * 256u + x < callId * (m_maxUniformTexelCount / valuesPerPixel))
6723                                 continue;
6724                         else
6725                         {
6726                                 deUint32 value = id;
6727
6728                                 for (deUint32 i = 0; i < valuesPerPixel; i++)
6729                                 {
6730                                         value   = ((deUint32)context.getReference().get( offset + (value % count) * 4 + 0))
6731                                                         | (((deUint32)context.getReference().get(offset + (value % count) * 4 + 1)) << 8u)
6732                                                         | (((deUint32)context.getReference().get(offset + (value % count) * 4 + 2)) << 16u)
6733                                                         | (((deUint32)context.getReference().get(offset + (value % count) * 4 + 3)) << 24u);
6734
6735                                 }
6736                                 const UVec4     vec     ((value >>  0u) & 0xFFu,
6737                                                                  (value >>  8u) & 0xFFu,
6738                                                                  (value >> 16u) & 0xFFu,
6739                                                                  (value >> 24u) & 0xFFu);
6740
6741                                 context.getReferenceTarget().getAccess().setPixel(vec.asFloat() / Vec4(255.0f), x, y);
6742                         }
6743                 }
6744         }
6745 }
6746
6747 class RenderFragmentStorageTexelBuffer : public RenderPassCommand
6748 {
6749 public:
6750                                                                         RenderFragmentStorageTexelBuffer        (void) {}
6751                                                                         ~RenderFragmentStorageTexelBuffer       (void);
6752
6753         const char*                                             getName                                                         (void) const { return "RenderFragmentStorageTexelBuffer"; }
6754         void                                                    logPrepare                                                      (TestLog&, size_t) const;
6755         void                                                    logSubmit                                                       (TestLog&, size_t) const;
6756         void                                                    prepare                                                         (PrepareRenderPassContext&);
6757         void                                                    submit                                                          (SubmitContext& context);
6758         void                                                    verify                                                          (VerifyRenderPassContext&, size_t);
6759
6760 private:
6761         PipelineResources                               m_resources;
6762         vk::Move<vk::VkDescriptorPool>  m_descriptorPool;
6763         vector<vk::VkDescriptorSet>             m_descriptorSets;
6764         vector<vk::VkBufferView>                m_bufferViews;
6765
6766         const vk::DeviceInterface*              m_vkd;
6767         vk::VkDevice                                    m_device;
6768         vk::VkDeviceSize                                m_bufferSize;
6769         deUint32                                                m_maxStorageTexelCount;
6770         size_t                                                  m_targetWidth;
6771         size_t                                                  m_targetHeight;
6772 };
6773
6774 RenderFragmentStorageTexelBuffer::~RenderFragmentStorageTexelBuffer (void)
6775 {
6776         for (size_t bufferViewNdx = 0; bufferViewNdx < m_bufferViews.size(); bufferViewNdx++)
6777         {
6778                 if (!!m_bufferViews[bufferViewNdx])
6779                 {
6780                         m_vkd->destroyBufferView(m_device, m_bufferViews[bufferViewNdx], DE_NULL);
6781                         m_bufferViews[bufferViewNdx] = (vk::VkBufferView)0;
6782                 }
6783         }
6784 }
6785
6786 void RenderFragmentStorageTexelBuffer::logPrepare (TestLog& log, size_t commandIndex) const
6787 {
6788         log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render buffer as storage buffer." << TestLog::EndMessage;
6789 }
6790
6791 void RenderFragmentStorageTexelBuffer::logSubmit (TestLog& log, size_t commandIndex) const
6792 {
6793         log << TestLog::Message << commandIndex << ":" << getName() << " Render using buffer as storage buffer." << TestLog::EndMessage;
6794 }
6795
6796 void RenderFragmentStorageTexelBuffer::prepare (PrepareRenderPassContext& context)
6797 {
6798         const vk::InstanceInterface&                            vki                                             = context.getContext().getInstanceInterface();
6799         const vk::VkPhysicalDevice                                      physicalDevice                  = context.getContext().getPhysicalDevice();
6800         const vk::DeviceInterface&                                      vkd                                             = context.getContext().getDeviceInterface();
6801         const vk::VkDevice                                                      device                                  = context.getContext().getDevice();
6802         const vk::VkRenderPass                                          renderPass                              = context.getRenderPass();
6803         const deUint32                                                          subpass                                 = 0;
6804         const vk::Unique<vk::VkShaderModule>            vertexShaderModule              (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-quad.vert"), 0));
6805         const vk::Unique<vk::VkShaderModule>            fragmentShaderModule    (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("storage-texel-buffer.frag"), 0));
6806         vector<vk::VkDescriptorSetLayoutBinding>        bindings;
6807
6808         m_device                                = device;
6809         m_vkd                                   = &vkd;
6810         m_bufferSize                    = context.getBufferSize();
6811         m_maxStorageTexelCount  = vk::getPhysicalDeviceProperties(vki, physicalDevice).limits.maxTexelBufferElements;
6812         m_targetWidth                   = context.getTargetWidth();
6813         m_targetHeight                  = context.getTargetHeight();
6814
6815         {
6816                 const vk::VkDescriptorSetLayoutBinding binding =
6817                 {
6818                         0u,
6819                         vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
6820                         1,
6821                         vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6822                         DE_NULL
6823                 };
6824
6825                 bindings.push_back(binding);
6826         }
6827         const vk::VkPushConstantRange pushConstantRange =
6828         {
6829                 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6830                 0u,
6831                 16u
6832         };
6833
6834         createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
6835                                                                 vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), bindings, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 1u, &pushConstantRange, m_resources);
6836
6837         {
6838                 const deUint32                                                  descriptorCount = (deUint32)(divRoundUp(m_bufferSize, (vk::VkDeviceSize)m_maxStorageTexelCount * 4));
6839                 const vk::VkDescriptorPoolSize                  poolSizes               =
6840                 {
6841                         vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
6842                         descriptorCount
6843                 };
6844                 const vk::VkDescriptorPoolCreateInfo    createInfo              =
6845                 {
6846                         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
6847                         DE_NULL,
6848                         vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
6849
6850                         descriptorCount,
6851                         1u,
6852                         &poolSizes,
6853                 };
6854
6855                 m_descriptorPool = vk::createDescriptorPool(vkd, device, &createInfo);
6856                 m_descriptorSets.resize(descriptorCount, (vk::VkDescriptorSet)0);
6857                 m_bufferViews.resize(descriptorCount, (vk::VkBufferView)0);
6858         }
6859
6860         for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
6861         {
6862                 const deUint32                                                  count                   = (deUint32)(m_bufferSize < (descriptorSetNdx + 1) * m_maxStorageTexelCount * 4
6863                                                                                                                                 ? m_bufferSize - descriptorSetNdx * m_maxStorageTexelCount * 4
6864                                                                                                                                 : m_maxStorageTexelCount * 4) / 4;
6865                 const vk::VkDescriptorSetLayout                 layout                  = *m_resources.descriptorSetLayout;
6866                 const vk::VkDescriptorSetAllocateInfo   allocateInfo    =
6867                 {
6868                         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
6869                         DE_NULL,
6870
6871                         *m_descriptorPool,
6872                         1,
6873                         &layout
6874                 };
6875
6876                 m_descriptorSets[descriptorSetNdx] = vk::allocateDescriptorSet(vkd, device, &allocateInfo).disown();
6877
6878                 {
6879                         const vk::VkBufferViewCreateInfo createInfo =
6880                         {
6881                                 vk::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
6882                                 DE_NULL,
6883                                 0u,
6884
6885                                 context.getBuffer(),
6886                                 vk::VK_FORMAT_R32_UINT,
6887                                 descriptorSetNdx * m_maxStorageTexelCount * 4,
6888                                 count * 4
6889                         };
6890
6891                         VK_CHECK(vkd.createBufferView(device, &createInfo, DE_NULL, &m_bufferViews[descriptorSetNdx]));
6892                 }
6893
6894                 {
6895                         const vk::VkWriteDescriptorSet                  write           =
6896                         {
6897                                 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
6898                                 DE_NULL,
6899                                 m_descriptorSets[descriptorSetNdx],
6900                                 0u,
6901                                 0u,
6902                                 1u,
6903                                 vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
6904                                 DE_NULL,
6905                                 DE_NULL,
6906                                 &m_bufferViews[descriptorSetNdx]
6907                         };
6908
6909                         vkd.updateDescriptorSets(device, 1u, &write, 0u, DE_NULL);
6910                 }
6911         }
6912 }
6913
6914 void RenderFragmentStorageTexelBuffer::submit (SubmitContext& context)
6915 {
6916         const vk::DeviceInterface&      vkd                             = context.getContext().getDeviceInterface();
6917         const vk::VkCommandBuffer       commandBuffer   = context.getCommandBuffer();
6918
6919         vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
6920
6921         for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
6922         {
6923                 const struct
6924                 {
6925                         const deUint32  callId;
6926                         const deUint32  valuesPerPixel;
6927                         const deUint32  maxStorageTexelCount;
6928                         const deUint32  width;
6929                 } callParams =
6930                 {
6931                         (deUint32)descriptorSetNdx,
6932                         (deUint32)divRoundUp<size_t>(m_descriptorSets.size() * de::min<size_t>(m_maxStorageTexelCount, (size_t)m_bufferSize / 4), m_targetWidth * m_targetHeight),
6933                         m_maxStorageTexelCount,
6934                         (deUint32)(m_bufferSize < (descriptorSetNdx + 1u) * m_maxStorageTexelCount * 4u
6935                                                                 ? m_bufferSize - descriptorSetNdx * m_maxStorageTexelCount * 4u
6936                                                                 : m_maxStorageTexelCount * 4u) / 4u
6937                 };
6938
6939                 vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &m_descriptorSets[descriptorSetNdx], 0u, DE_NULL);
6940                 vkd.cmdPushConstants(commandBuffer, *m_resources.pipelineLayout, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, (deUint32)sizeof(callParams), &callParams);
6941                 vkd.cmdDraw(commandBuffer, 6, 1, 0, 0);
6942         }
6943 }
6944
6945 void RenderFragmentStorageTexelBuffer::verify (VerifyRenderPassContext& context, size_t)
6946 {
6947         const deUint32  valuesPerPixel  = (deUint32)divRoundUp<size_t>(m_descriptorSets.size() * de::min<size_t>(m_maxStorageTexelCount, (size_t)m_bufferSize / 4), m_targetWidth * m_targetHeight);
6948
6949         for (int y = 0; y < context.getReferenceTarget().getSize().y(); y++)
6950         for (int x = 0; x < context.getReferenceTarget().getSize().x(); x++)
6951         {
6952                 const size_t firstDescriptorSetNdx = de::min<size_t>((y * 256u + x) / (m_maxStorageTexelCount / valuesPerPixel), m_descriptorSets.size() - 1);
6953
6954                 for (size_t descriptorSetNdx = firstDescriptorSetNdx; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
6955                 {
6956                         const size_t    offset  = descriptorSetNdx * m_maxStorageTexelCount * 4;
6957                         const deUint32  callId  = (deUint32)descriptorSetNdx;
6958
6959                         const deUint32  id              = (deUint32)y * 256u + (deUint32)x;
6960                         const deUint32  count   = (deUint32)(m_bufferSize < (descriptorSetNdx + 1) * m_maxStorageTexelCount * 4
6961                                                                         ? m_bufferSize - descriptorSetNdx * m_maxStorageTexelCount * 4
6962                                                                         : m_maxStorageTexelCount * 4) / 4;
6963
6964                         if (y * 256u + x < callId * (m_maxStorageTexelCount / valuesPerPixel))
6965                                 continue;
6966                         else
6967                         {
6968                                 deUint32 value = id;
6969
6970                                 for (deUint32 i = 0; i < valuesPerPixel; i++)
6971                                 {
6972                                         value   = ((deUint32)context.getReference().get( offset + (value % count) * 4 + 0))
6973                                                         | (((deUint32)context.getReference().get(offset + (value % count) * 4 + 1)) << 8u)
6974                                                         | (((deUint32)context.getReference().get(offset + (value % count) * 4 + 2)) << 16u)
6975                                                         | (((deUint32)context.getReference().get(offset + (value % count) * 4 + 3)) << 24u);
6976
6977                                 }
6978                                 const UVec4     vec     ((value >>  0u) & 0xFFu,
6979                                                                  (value >>  8u) & 0xFFu,
6980                                                                  (value >> 16u) & 0xFFu,
6981                                                                  (value >> 24u) & 0xFFu);
6982
6983                                 context.getReferenceTarget().getAccess().setPixel(vec.asFloat() / Vec4(255.0f), x, y);
6984                         }
6985                 }
6986         }
6987 }
6988
6989 class RenderFragmentStorageImage : public RenderPassCommand
6990 {
6991 public:
6992                                                                         RenderFragmentStorageImage      (void) {}
6993                                                                         ~RenderFragmentStorageImage     (void);
6994
6995         const char*                                             getName                                         (void) const { return "RenderFragmentStorageImage"; }
6996         void                                                    logPrepare                                      (TestLog&, size_t) const;
6997         void                                                    logSubmit                                       (TestLog&, size_t) const;
6998         void                                                    prepare                                         (PrepareRenderPassContext&);
6999         void                                                    submit                                          (SubmitContext& context);
7000         void                                                    verify                                          (VerifyRenderPassContext&, size_t);
7001
7002 private:
7003         PipelineResources                               m_resources;
7004         vk::Move<vk::VkDescriptorPool>  m_descriptorPool;
7005         vk::Move<vk::VkDescriptorSet>   m_descriptorSet;
7006         vk::Move<vk::VkImageView>               m_imageView;
7007 };
7008
7009 RenderFragmentStorageImage::~RenderFragmentStorageImage (void)
7010 {
7011 }
7012
7013 void RenderFragmentStorageImage::logPrepare (TestLog& log, size_t commandIndex) const
7014 {
7015         log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render storage image." << TestLog::EndMessage;
7016 }
7017
7018 void RenderFragmentStorageImage::logSubmit (TestLog& log, size_t commandIndex) const
7019 {
7020         log << TestLog::Message << commandIndex << ":" << getName() << " Render using storage image." << TestLog::EndMessage;
7021 }
7022
7023 void RenderFragmentStorageImage::prepare (PrepareRenderPassContext& context)
7024 {
7025         const vk::DeviceInterface&                                      vkd                                             = context.getContext().getDeviceInterface();
7026         const vk::VkDevice                                                      device                                  = context.getContext().getDevice();
7027         const vk::VkRenderPass                                          renderPass                              = context.getRenderPass();
7028         const deUint32                                                          subpass                                 = 0;
7029         const vk::Unique<vk::VkShaderModule>            vertexShaderModule              (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-quad.vert"), 0));
7030         const vk::Unique<vk::VkShaderModule>            fragmentShaderModule    (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("storage-image.frag"), 0));
7031         vector<vk::VkDescriptorSetLayoutBinding>        bindings;
7032
7033         {
7034                 const vk::VkDescriptorSetLayoutBinding binding =
7035                 {
7036                         0u,
7037                         vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
7038                         1,
7039                         vk::VK_SHADER_STAGE_FRAGMENT_BIT,
7040                         DE_NULL
7041                 };
7042
7043                 bindings.push_back(binding);
7044         }
7045
7046         createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
7047                                                                 vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), bindings, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, DE_NULL, m_resources);
7048
7049         {
7050                 const vk::VkDescriptorPoolSize                  poolSizes               =
7051                 {
7052                         vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
7053                         1
7054                 };
7055                 const vk::VkDescriptorPoolCreateInfo    createInfo              =
7056                 {
7057                         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
7058                         DE_NULL,
7059                         vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
7060
7061                         1u,
7062                         1u,
7063                         &poolSizes,
7064                 };
7065
7066                 m_descriptorPool = vk::createDescriptorPool(vkd, device, &createInfo);
7067         }
7068
7069         {
7070                 const vk::VkDescriptorSetLayout                 layout                  = *m_resources.descriptorSetLayout;
7071                 const vk::VkDescriptorSetAllocateInfo   allocateInfo    =
7072                 {
7073                         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
7074                         DE_NULL,
7075
7076                         *m_descriptorPool,
7077                         1,
7078                         &layout
7079                 };
7080
7081                 m_descriptorSet = vk::allocateDescriptorSet(vkd, device, &allocateInfo);
7082
7083                 {
7084                         const vk::VkImageViewCreateInfo createInfo =
7085                         {
7086                                 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
7087                                 DE_NULL,
7088                                 0u,
7089
7090                                 context.getImage(),
7091                                 vk::VK_IMAGE_VIEW_TYPE_2D,
7092                                 vk::VK_FORMAT_R8G8B8A8_UNORM,
7093                                 vk::makeComponentMappingRGBA(),
7094                                 {
7095                                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
7096                                         0u,
7097                                         1u,
7098                                         0u,
7099                                         1u
7100                                 }
7101                         };
7102
7103                         m_imageView = vk::createImageView(vkd, device, &createInfo);
7104                 }
7105
7106                 {
7107                         const vk::VkDescriptorImageInfo                 imageInfo       =
7108                         {
7109                                 0,
7110                                 *m_imageView,
7111                                 context.getImageLayout()
7112                         };
7113                         const vk::VkWriteDescriptorSet                  write           =
7114                         {
7115                                 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
7116                                 DE_NULL,
7117                                 *m_descriptorSet,
7118                                 0u,
7119                                 0u,
7120                                 1u,
7121                                 vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
7122                                 &imageInfo,
7123                                 DE_NULL,
7124                                 DE_NULL,
7125                         };
7126
7127                         vkd.updateDescriptorSets(device, 1u, &write, 0u, DE_NULL);
7128                 }
7129         }
7130 }
7131
7132 void RenderFragmentStorageImage::submit (SubmitContext& context)
7133 {
7134         const vk::DeviceInterface&      vkd                             = context.getContext().getDeviceInterface();
7135         const vk::VkCommandBuffer       commandBuffer   = context.getCommandBuffer();
7136
7137         vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
7138
7139         vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &(*m_descriptorSet), 0u, DE_NULL);
7140         vkd.cmdDraw(commandBuffer, 6, 1, 0, 0);
7141 }
7142
7143 void RenderFragmentStorageImage::verify (VerifyRenderPassContext& context, size_t)
7144 {
7145         const UVec2             size                    = UVec2(context.getReferenceImage().getWidth(), context.getReferenceImage().getHeight());
7146         const deUint32  valuesPerPixel  = de::max<deUint32>(1u, (size.x() * size.y()) / (256u * 256u));
7147
7148         for (int y = 0; y < context.getReferenceTarget().getSize().y(); y++)
7149         for (int x = 0; x < context.getReferenceTarget().getSize().x(); x++)
7150         {
7151                 UVec4   value   = UVec4(x, y, 0u, 0u);
7152
7153                 for (deUint32 i = 0; i < valuesPerPixel; i++)
7154                 {
7155                         const UVec2     pos                     = UVec2(value.z() * 256u + (value.x() ^ value.z()), value.w() * 256u + (value.y() ^ value.w()));
7156                         const Vec4      floatValue      = context.getReferenceImage().getAccess().getPixel(pos.x() % size.x(), pos.y() % size.y());
7157
7158                         value = UVec4((deUint32)(floatValue.x() * 255.0f),
7159                                                   (deUint32)(floatValue.y() * 255.0f),
7160                                                   (deUint32)(floatValue.z() * 255.0f),
7161                                                   (deUint32)(floatValue.w() * 255.0f));
7162
7163                 }
7164                 context.getReferenceTarget().getAccess().setPixel(value.asFloat() / Vec4(255.0f), x, y);
7165         }
7166 }
7167
7168 class RenderFragmentSampledImage : public RenderPassCommand
7169 {
7170 public:
7171                                 RenderFragmentSampledImage      (void) {}
7172                                 ~RenderFragmentSampledImage     (void);
7173
7174         const char*     getName                                         (void) const { return "RenderFragmentSampledImage"; }
7175         void            logPrepare                                      (TestLog&, size_t) const;
7176         void            logSubmit                                       (TestLog&, size_t) const;
7177         void            prepare                                         (PrepareRenderPassContext&);
7178         void            submit                                          (SubmitContext& context);
7179         void            verify                                          (VerifyRenderPassContext&, size_t);
7180
7181 private:
7182         PipelineResources                               m_resources;
7183         vk::Move<vk::VkDescriptorPool>  m_descriptorPool;
7184         vk::Move<vk::VkDescriptorSet>   m_descriptorSet;
7185         vk::Move<vk::VkImageView>               m_imageView;
7186         vk::Move<vk::VkSampler>                 m_sampler;
7187 };
7188
7189 RenderFragmentSampledImage::~RenderFragmentSampledImage (void)
7190 {
7191 }
7192
7193 void RenderFragmentSampledImage::logPrepare (TestLog& log, size_t commandIndex) const
7194 {
7195         log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render storage image." << TestLog::EndMessage;
7196 }
7197
7198 void RenderFragmentSampledImage::logSubmit (TestLog& log, size_t commandIndex) const
7199 {
7200         log << TestLog::Message << commandIndex << ":" << getName() << " Render using storage image." << TestLog::EndMessage;
7201 }
7202
7203 void RenderFragmentSampledImage::prepare (PrepareRenderPassContext& context)
7204 {
7205         const vk::DeviceInterface&                                      vkd                                             = context.getContext().getDeviceInterface();
7206         const vk::VkDevice                                                      device                                  = context.getContext().getDevice();
7207         const vk::VkRenderPass                                          renderPass                              = context.getRenderPass();
7208         const deUint32                                                          subpass                                 = 0;
7209         const vk::Unique<vk::VkShaderModule>            vertexShaderModule              (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-quad.vert"), 0));
7210         const vk::Unique<vk::VkShaderModule>            fragmentShaderModule    (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("sampled-image.frag"), 0));
7211         vector<vk::VkDescriptorSetLayoutBinding>        bindings;
7212
7213         {
7214                 const vk::VkDescriptorSetLayoutBinding binding =
7215                 {
7216                         0u,
7217                         vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7218                         1,
7219                         vk::VK_SHADER_STAGE_FRAGMENT_BIT,
7220                         DE_NULL
7221                 };
7222
7223                 bindings.push_back(binding);
7224         }
7225
7226         createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
7227                                                                 vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), bindings, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, DE_NULL, m_resources);
7228
7229         {
7230                 const vk::VkDescriptorPoolSize                  poolSizes               =
7231                 {
7232                         vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7233                         1
7234                 };
7235                 const vk::VkDescriptorPoolCreateInfo    createInfo              =
7236                 {
7237                         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
7238                         DE_NULL,
7239                         vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
7240
7241                         1u,
7242                         1u,
7243                         &poolSizes,
7244                 };
7245
7246                 m_descriptorPool = vk::createDescriptorPool(vkd, device, &createInfo);
7247         }
7248
7249         {
7250                 const vk::VkDescriptorSetLayout                 layout                  = *m_resources.descriptorSetLayout;
7251                 const vk::VkDescriptorSetAllocateInfo   allocateInfo    =
7252                 {
7253                         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
7254                         DE_NULL,
7255
7256                         *m_descriptorPool,
7257                         1,
7258                         &layout
7259                 };
7260
7261                 m_descriptorSet = vk::allocateDescriptorSet(vkd, device, &allocateInfo);
7262
7263                 {
7264                         const vk::VkImageViewCreateInfo createInfo =
7265                         {
7266                                 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
7267                                 DE_NULL,
7268                                 0u,
7269
7270                                 context.getImage(),
7271                                 vk::VK_IMAGE_VIEW_TYPE_2D,
7272                                 vk::VK_FORMAT_R8G8B8A8_UNORM,
7273                                 vk::makeComponentMappingRGBA(),
7274                                 {
7275                                         vk::VK_IMAGE_ASPECT_COLOR_BIT,
7276                                         0u,
7277                                         1u,
7278                                         0u,
7279                                         1u
7280                                 }
7281                         };
7282
7283                         m_imageView = vk::createImageView(vkd, device, &createInfo);
7284                 }
7285
7286                 {
7287                         const vk::VkSamplerCreateInfo createInfo =
7288                         {
7289                                 vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
7290                                 DE_NULL,
7291                                 0u,
7292
7293                                 vk::VK_FILTER_NEAREST,
7294                                 vk::VK_FILTER_NEAREST,
7295
7296                                 vk::VK_SAMPLER_MIPMAP_MODE_LINEAR,
7297                                 vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
7298                                 vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
7299                                 vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
7300                                 0.0f,
7301                                 VK_FALSE,
7302                                 1.0f,
7303                                 VK_FALSE,
7304                                 vk::VK_COMPARE_OP_ALWAYS,
7305                                 0.0f,
7306                                 0.0f,
7307                                 vk::VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
7308                                 VK_FALSE
7309                         };
7310
7311                         m_sampler = vk::createSampler(vkd, device, &createInfo);
7312                 }
7313
7314                 {
7315                         const vk::VkDescriptorImageInfo                 imageInfo       =
7316                         {
7317                                 *m_sampler,
7318                                 *m_imageView,
7319                                 context.getImageLayout()
7320                         };
7321                         const vk::VkWriteDescriptorSet                  write           =
7322                         {
7323                                 vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
7324                                 DE_NULL,
7325                                 *m_descriptorSet,
7326                                 0u,
7327                                 0u,
7328                                 1u,
7329                                 vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7330                                 &imageInfo,
7331                                 DE_NULL,
7332                                 DE_NULL,
7333                         };
7334
7335                         vkd.updateDescriptorSets(device, 1u, &write, 0u, DE_NULL);
7336                 }
7337         }
7338 }
7339
7340 void RenderFragmentSampledImage::submit (SubmitContext& context)
7341 {
7342         const vk::DeviceInterface&      vkd                             = context.getContext().getDeviceInterface();
7343         const vk::VkCommandBuffer       commandBuffer   = context.getCommandBuffer();
7344
7345         vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
7346
7347         vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &(*m_descriptorSet), 0u, DE_NULL);
7348         vkd.cmdDraw(commandBuffer, 6u, 1u, 0u, 0u);
7349 }
7350
7351 void RenderFragmentSampledImage::verify (VerifyRenderPassContext& context, size_t)
7352 {
7353         const UVec2             size                    = UVec2(context.getReferenceImage().getWidth(), context.getReferenceImage().getHeight());
7354         const deUint32  valuesPerPixel  = de::max<deUint32>(1u, (size.x() * size.y()) / (256u * 256u));
7355
7356         for (int y = 0; y < context.getReferenceTarget().getSize().y(); y++)
7357         for (int x = 0; x < context.getReferenceTarget().getSize().x(); x++)
7358         {
7359                 UVec4   value   = UVec4(x, y, 0u, 0u);
7360
7361                 for (deUint32 i = 0; i < valuesPerPixel; i++)
7362                 {
7363                         const UVec2     pos                     = UVec2(value.z() * 256u + (value.x() ^ value.z()), value.w() * 256u + (value.y() ^ value.w()));
7364                         const Vec4      floatValue      = context.getReferenceImage().getAccess().getPixel(pos.x() % size.x(), pos.y() % size.y());
7365
7366                         value = UVec4((deUint32)(floatValue.x() * 255.0f),
7367                                                   (deUint32)(floatValue.y() * 255.0f),
7368                                                   (deUint32)(floatValue.z() * 255.0f),
7369                                                   (deUint32)(floatValue.w() * 255.0f));
7370
7371                 }
7372
7373                 context.getReferenceTarget().getAccess().setPixel(value.asFloat() / Vec4(255.0f), x, y);
7374         }
7375 }
7376
7377 enum Op
7378 {
7379         OP_MAP,
7380         OP_UNMAP,
7381
7382         OP_MAP_FLUSH,
7383         OP_MAP_INVALIDATE,
7384
7385         OP_MAP_READ,
7386         OP_MAP_WRITE,
7387         OP_MAP_MODIFY,
7388
7389         OP_BUFFER_CREATE,
7390         OP_BUFFER_DESTROY,
7391         OP_BUFFER_BINDMEMORY,
7392
7393         OP_QUEUE_WAIT_FOR_IDLE,
7394         OP_DEVICE_WAIT_FOR_IDLE,
7395
7396         OP_COMMAND_BUFFER_BEGIN,
7397         OP_COMMAND_BUFFER_END,
7398
7399         // Buffer transfer operations
7400         OP_BUFFER_FILL,
7401         OP_BUFFER_UPDATE,
7402
7403         OP_BUFFER_COPY_TO_BUFFER,
7404         OP_BUFFER_COPY_FROM_BUFFER,
7405
7406         OP_BUFFER_COPY_TO_IMAGE,
7407         OP_BUFFER_COPY_FROM_IMAGE,
7408
7409         OP_IMAGE_CREATE,
7410         OP_IMAGE_DESTROY,
7411         OP_IMAGE_BINDMEMORY,
7412
7413         OP_IMAGE_TRANSITION_LAYOUT,
7414
7415         OP_IMAGE_COPY_TO_BUFFER,
7416         OP_IMAGE_COPY_FROM_BUFFER,
7417
7418         OP_IMAGE_COPY_TO_IMAGE,
7419         OP_IMAGE_COPY_FROM_IMAGE,
7420
7421         OP_IMAGE_BLIT_TO_IMAGE,
7422         OP_IMAGE_BLIT_FROM_IMAGE,
7423
7424         OP_IMAGE_RESOLVE,
7425
7426         OP_PIPELINE_BARRIER_GLOBAL,
7427         OP_PIPELINE_BARRIER_BUFFER,
7428         OP_PIPELINE_BARRIER_IMAGE,
7429
7430         // Renderpass operations
7431         OP_RENDERPASS_BEGIN,
7432         OP_RENDERPASS_END,
7433
7434         // Commands inside render pass
7435         OP_RENDER_VERTEX_BUFFER,
7436         OP_RENDER_INDEX_BUFFER,
7437
7438         OP_RENDER_VERTEX_UNIFORM_BUFFER,
7439         OP_RENDER_FRAGMENT_UNIFORM_BUFFER,
7440
7441         OP_RENDER_VERTEX_UNIFORM_TEXEL_BUFFER,
7442         OP_RENDER_FRAGMENT_UNIFORM_TEXEL_BUFFER,
7443
7444         OP_RENDER_VERTEX_STORAGE_BUFFER,
7445         OP_RENDER_FRAGMENT_STORAGE_BUFFER,
7446
7447         OP_RENDER_VERTEX_STORAGE_TEXEL_BUFFER,
7448         OP_RENDER_FRAGMENT_STORAGE_TEXEL_BUFFER,
7449
7450         OP_RENDER_VERTEX_STORAGE_IMAGE,
7451         OP_RENDER_FRAGMENT_STORAGE_IMAGE,
7452
7453         OP_RENDER_VERTEX_SAMPLED_IMAGE,
7454         OP_RENDER_FRAGMENT_SAMPLED_IMAGE,
7455 };
7456
7457 enum Stage
7458 {
7459         STAGE_HOST,
7460         STAGE_COMMAND_BUFFER,
7461
7462         STAGE_RENDER_PASS
7463 };
7464
7465 vk::VkAccessFlags getWriteAccessFlags (void)
7466 {
7467         return vk::VK_ACCESS_SHADER_WRITE_BIT
7468                 | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
7469                 | vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
7470                 | vk::VK_ACCESS_TRANSFER_WRITE_BIT
7471                 | vk::VK_ACCESS_HOST_WRITE_BIT
7472                 | vk::VK_ACCESS_MEMORY_WRITE_BIT;
7473 }
7474
7475 bool isWriteAccess (vk::VkAccessFlagBits access)
7476 {
7477         return (getWriteAccessFlags() & access) != 0;
7478 }
7479
7480 class CacheState
7481 {
7482 public:
7483                                                                         CacheState                              (vk::VkPipelineStageFlags allowedStages, vk::VkAccessFlags allowedAccesses);
7484
7485         bool                                                    isValid                                 (vk::VkPipelineStageFlagBits    stage,
7486                                                                                                                          vk::VkAccessFlagBits                   access) const;
7487
7488         void                                                    perform                                 (vk::VkPipelineStageFlagBits    stage,
7489                                                                                                                          vk::VkAccessFlagBits                   access);
7490
7491         void                                                    submitCommandBuffer             (void);
7492         void                                                    waitForIdle                             (void);
7493
7494         void                                                    getFullBarrier                  (vk::VkPipelineStageFlags&      srcStages,
7495                                                                                                                          vk::VkAccessFlags&                     srcAccesses,
7496                                                                                                                          vk::VkPipelineStageFlags&      dstStages,
7497                                                                                                                          vk::VkAccessFlags&                     dstAccesses) const;
7498
7499         void                                                    barrier                                 (vk::VkPipelineStageFlags       srcStages,
7500                                                                                                                          vk::VkAccessFlags                      srcAccesses,
7501                                                                                                                          vk::VkPipelineStageFlags       dstStages,
7502                                                                                                                          vk::VkAccessFlags                      dstAccesses);
7503
7504         void                                                    imageLayoutBarrier              (vk::VkPipelineStageFlags       srcStages,
7505                                                                                                                          vk::VkAccessFlags                      srcAccesses,
7506                                                                                                                          vk::VkPipelineStageFlags       dstStages,
7507                                                                                                                          vk::VkAccessFlags                      dstAccesses);
7508
7509         void                                                    checkImageLayoutBarrier (vk::VkPipelineStageFlags       srcStages,
7510                                                                                                                          vk::VkAccessFlags                      srcAccesses,
7511                                                                                                                          vk::VkPipelineStageFlags       dstStages,
7512                                                                                                                          vk::VkAccessFlags                      dstAccesses);
7513
7514         // Everything is clean and there is no need for barriers
7515         bool                                                    isClean                                 (void) const;
7516
7517         vk::VkPipelineStageFlags                getAllowedStages                (void) const { return m_allowedStages; }
7518         vk::VkAccessFlags                               getAllowedAcceses               (void) const { return m_allowedAccesses; }
7519 private:
7520         // Limit which stages and accesses are used by the CacheState tracker
7521         const vk::VkPipelineStageFlags  m_allowedStages;
7522         const vk::VkAccessFlags                 m_allowedAccesses;
7523
7524         // [dstStage][srcStage] = srcAccesses
7525         // In stage dstStage write srcAccesses from srcStage are not yet available
7526         vk::VkAccessFlags                               m_unavailableWriteOperations[PIPELINESTAGE_LAST][PIPELINESTAGE_LAST];
7527         // Latest pipeline transition is not available in stage
7528         bool                                                    m_unavailableLayoutTransition[PIPELINESTAGE_LAST];
7529         // [dstStage] = dstAccesses
7530         // In stage dstStage ops with dstAccesses are not yet visible
7531         vk::VkAccessFlags                               m_invisibleOperations[PIPELINESTAGE_LAST];
7532
7533         // [dstStage] = srcStage
7534         // Memory operation in srcStage have not completed before dstStage
7535         vk::VkPipelineStageFlags                m_incompleteOperations[PIPELINESTAGE_LAST];
7536 };
7537
7538 CacheState::CacheState (vk::VkPipelineStageFlags allowedStages, vk::VkAccessFlags allowedAccesses)
7539         : m_allowedStages       (allowedStages)
7540         , m_allowedAccesses     (allowedAccesses)
7541 {
7542         for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
7543         {
7544                 const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
7545
7546                 if ((dstStage_ & m_allowedStages) == 0)
7547                         continue;
7548
7549                 // All operations are initially visible
7550                 m_invisibleOperations[dstStage] = 0;
7551
7552                 // There are no incomplete read operations initially
7553                 m_incompleteOperations[dstStage] = 0;
7554
7555                 // There are no incomplete layout transitions
7556                 m_unavailableLayoutTransition[dstStage] = false;
7557
7558                 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
7559                 {
7560                         const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
7561
7562                         if ((srcStage_ & m_allowedStages) == 0)
7563                                 continue;
7564
7565                         // There are no write operations that are not yet available
7566                         // initially.
7567                         m_unavailableWriteOperations[dstStage][srcStage] = 0;
7568                 }
7569         }
7570 }
7571
7572 bool CacheState::isValid (vk::VkPipelineStageFlagBits   stage,
7573                                                   vk::VkAccessFlagBits                  access) const
7574 {
7575         DE_ASSERT((access & (~m_allowedAccesses)) == 0);
7576         DE_ASSERT((stage & (~m_allowedStages)) == 0);
7577
7578         const PipelineStage     dstStage        = pipelineStageFlagToPipelineStage(stage);
7579
7580         // Previous operations are not visible to access on stage
7581         if (m_unavailableLayoutTransition[dstStage] || (m_invisibleOperations[dstStage] & access) != 0)
7582                 return false;
7583
7584         if (isWriteAccess(access))
7585         {
7586                 // Memory operations from other stages have not completed before
7587                 // dstStage
7588                 if (m_incompleteOperations[dstStage] != 0)
7589                         return false;
7590         }
7591
7592         return true;
7593 }
7594
7595 void CacheState::perform (vk::VkPipelineStageFlagBits   stage,
7596                                                   vk::VkAccessFlagBits                  access)
7597 {
7598         DE_ASSERT((access & (~m_allowedAccesses)) == 0);
7599         DE_ASSERT((stage & (~m_allowedStages)) == 0);
7600
7601         const PipelineStage srcStage = pipelineStageFlagToPipelineStage(stage);
7602
7603         for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
7604         {
7605                 const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
7606
7607                 if ((dstStage_ & m_allowedStages) == 0)
7608                         continue;
7609
7610                 // Mark stage as incomplete for all stages
7611                 m_incompleteOperations[dstStage] |= stage;
7612
7613                 if (isWriteAccess(access))
7614                 {
7615                         // Mark all accesses from all stages invisible
7616                         m_invisibleOperations[dstStage] |= m_allowedAccesses;
7617
7618                         // Mark write access from srcStage unavailable to all stages
7619                         m_unavailableWriteOperations[dstStage][srcStage] |= access;
7620                 }
7621         }
7622 }
7623
7624 void CacheState::submitCommandBuffer (void)
7625 {
7626         // Flush all host writes and reads
7627         barrier(m_allowedStages & vk::VK_PIPELINE_STAGE_HOST_BIT,
7628                         m_allowedAccesses & (vk::VK_ACCESS_HOST_READ_BIT | vk::VK_ACCESS_HOST_WRITE_BIT),
7629                         m_allowedStages,
7630                         m_allowedAccesses);
7631 }
7632
7633 void CacheState::waitForIdle (void)
7634 {
7635         // Make all writes available
7636         barrier(m_allowedStages,
7637                         m_allowedAccesses & getWriteAccessFlags(),
7638                         m_allowedStages,
7639                         0);
7640
7641         // Make all writes visible on device side
7642         barrier(m_allowedStages,
7643                         0,
7644                         m_allowedStages & (~vk::VK_PIPELINE_STAGE_HOST_BIT),
7645                         m_allowedAccesses);
7646 }
7647
7648 void CacheState::getFullBarrier (vk::VkPipelineStageFlags&      srcStages,
7649                                                                  vk::VkAccessFlags&                     srcAccesses,
7650                                                                  vk::VkPipelineStageFlags&      dstStages,
7651                                                                  vk::VkAccessFlags&                     dstAccesses) const
7652 {
7653         srcStages       = 0;
7654         srcAccesses     = 0;
7655         dstStages       = 0;
7656         dstAccesses     = 0;
7657
7658         for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
7659         {
7660                 const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
7661
7662                 if ((dstStage_ & m_allowedStages) == 0)
7663                         continue;
7664
7665                 // Make sure all previous operation are complete in all stages
7666                 if (m_incompleteOperations[dstStage])
7667                 {
7668                         dstStages |= dstStage_;
7669                         srcStages |= m_incompleteOperations[dstStage];
7670                 }
7671
7672                 // Make sure all read operations are visible in dstStage
7673                 if (m_invisibleOperations[dstStage])
7674                 {
7675                         dstStages |= dstStage_;
7676                         dstAccesses |= m_invisibleOperations[dstStage];
7677                 }
7678
7679                 // Make sure all write operations fro mall stages are available
7680                 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
7681                 {
7682                         const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
7683
7684                         if ((srcStage_ & m_allowedStages) == 0)
7685                                 continue;
7686
7687                         if (m_unavailableWriteOperations[dstStage][srcStage])
7688                         {
7689                                 dstStages |= dstStage_;
7690                                 srcStages |= dstStage_;
7691                                 srcAccesses |= m_unavailableWriteOperations[dstStage][srcStage];
7692                         }
7693
7694                         if (m_unavailableLayoutTransition[dstStage] && !m_unavailableLayoutTransition[srcStage])
7695                         {
7696                                 // Add dependency between srcStage and dstStage if layout transition has not completed in dstStage,
7697                                 // but has completed in srcStage.
7698                                 dstStages |= dstStage_;
7699                                 srcStages |= dstStage_;
7700                         }
7701                 }
7702         }
7703
7704         DE_ASSERT((srcStages & (~m_allowedStages)) == 0);
7705         DE_ASSERT((srcAccesses & (~m_allowedAccesses)) == 0);
7706         DE_ASSERT((dstStages & (~m_allowedStages)) == 0);
7707         DE_ASSERT((dstAccesses & (~m_allowedAccesses)) == 0);
7708 }
7709
7710 void CacheState::checkImageLayoutBarrier (vk::VkPipelineStageFlags      srcStages,
7711                                                                                  vk::VkAccessFlags                      srcAccesses,
7712                                                                                  vk::VkPipelineStageFlags       dstStages,
7713                                                                                  vk::VkAccessFlags                      dstAccesses)
7714 {
7715         DE_ASSERT((srcStages & (~m_allowedStages)) == 0);
7716         DE_ASSERT((srcAccesses & (~m_allowedAccesses)) == 0);
7717         DE_ASSERT((dstStages & (~m_allowedStages)) == 0);
7718         DE_ASSERT((dstAccesses & (~m_allowedAccesses)) == 0);
7719
7720         DE_UNREF(srcStages);
7721         DE_UNREF(srcAccesses);
7722
7723         DE_UNREF(dstStages);
7724         DE_UNREF(dstAccesses);
7725
7726 #if defined(DE_DEBUG)
7727         // Check that all stages have completed before srcStages or are in srcStages.
7728         {
7729                 vk::VkPipelineStageFlags completedStages = srcStages;
7730
7731                 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= srcStages; srcStage_ <<= 1)
7732                 {
7733                         const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
7734
7735                         if ((srcStage_ & srcStages) == 0)
7736                                 continue;
7737
7738                         completedStages |= (~m_incompleteOperations[srcStage]);
7739                 }
7740
7741                 DE_ASSERT((completedStages & m_allowedStages) == m_allowedStages);
7742         }
7743
7744         // Check that any write is available at least in one stage. Since all stages are complete even single flush is enough.
7745         if ((getWriteAccessFlags() & m_allowedAccesses) != 0 && (srcAccesses & getWriteAccessFlags()) == 0)
7746         {
7747                 bool anyWriteAvailable = false;
7748
7749                 for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
7750                 {
7751                         const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
7752
7753                         if ((dstStage_ & m_allowedStages) == 0)
7754                                 continue;
7755
7756                         for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
7757                         {
7758                                 const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
7759
7760                                 if ((srcStage_ & m_allowedStages) == 0)
7761                                         continue;
7762
7763                                 if (m_unavailableWriteOperations[dstStage][srcStage] != (getWriteAccessFlags() & m_allowedAccesses))
7764                                 {
7765                                         anyWriteAvailable = true;
7766                                         break;
7767                                 }
7768                         }
7769                 }
7770
7771                 DE_ASSERT(anyWriteAvailable);
7772         }
7773 #endif
7774 }
7775
7776 void CacheState::imageLayoutBarrier (vk::VkPipelineStageFlags   srcStages,
7777                                                                          vk::VkAccessFlags                      srcAccesses,
7778                                                                          vk::VkPipelineStageFlags       dstStages,
7779                                                                          vk::VkAccessFlags                      dstAccesses)
7780 {
7781         checkImageLayoutBarrier(srcStages, srcAccesses, dstStages, dstAccesses);
7782
7783         for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
7784         {
7785                 const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
7786
7787                 if ((dstStage_ & m_allowedStages) == 0)
7788                         continue;
7789
7790                 // All stages are incomplete after the barrier except each dstStage in it self.
7791                 m_incompleteOperations[dstStage] = m_allowedStages & (~dstStage_);
7792
7793                 // All memory operations are invisible unless they are listed in dstAccess
7794                 m_invisibleOperations[dstStage] = m_allowedAccesses & (~dstAccesses);
7795
7796                 // Layout transition is unavailable in stage unless it was listed in dstStages
7797                 m_unavailableLayoutTransition[dstStage]= (dstStage_ & dstStages) == 0;
7798
7799                 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
7800                 {
7801                         const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
7802
7803                         if ((srcStage_ & m_allowedStages) == 0)
7804                                 continue;
7805
7806                         // All write operations are available after layout transition
7807                         m_unavailableWriteOperations[dstStage][srcStage] = 0;
7808                 }
7809         }
7810 }
7811
7812 void CacheState::barrier (vk::VkPipelineStageFlags      srcStages,
7813                                                   vk::VkAccessFlags                     srcAccesses,
7814                                                   vk::VkPipelineStageFlags      dstStages,
7815                                                   vk::VkAccessFlags                     dstAccesses)
7816 {
7817         DE_ASSERT((srcStages & (~m_allowedStages)) == 0);
7818         DE_ASSERT((srcAccesses & (~m_allowedAccesses)) == 0);
7819         DE_ASSERT((dstStages & (~m_allowedStages)) == 0);
7820         DE_ASSERT((dstAccesses & (~m_allowedAccesses)) == 0);
7821
7822         // Transitivity
7823         {
7824                 vk::VkPipelineStageFlags                oldIncompleteOperations[PIPELINESTAGE_LAST];
7825                 vk::VkAccessFlags                               oldUnavailableWriteOperations[PIPELINESTAGE_LAST][PIPELINESTAGE_LAST];
7826                 bool                                                    oldUnavailableLayoutTransition[PIPELINESTAGE_LAST];
7827
7828                 deMemcpy(oldIncompleteOperations, m_incompleteOperations, sizeof(oldIncompleteOperations));
7829                 deMemcpy(oldUnavailableWriteOperations, m_unavailableWriteOperations, sizeof(oldUnavailableWriteOperations));
7830                 deMemcpy(oldUnavailableLayoutTransition, m_unavailableLayoutTransition, sizeof(oldUnavailableLayoutTransition));
7831
7832                 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= srcStages; srcStage_ <<= 1)
7833                 {
7834                         const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
7835
7836                         if ((srcStage_ & srcStages) == 0)
7837                                 continue;
7838
7839                         for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= dstStages; dstStage_ <<= 1)
7840                         {
7841                                 const PipelineStage     dstStage                        = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
7842
7843                                 if ((dstStage_ & dstStages) == 0)
7844                                         continue;
7845
7846                                 // Stages that have completed before srcStage have also completed before dstStage
7847                                 m_incompleteOperations[dstStage] &= oldIncompleteOperations[srcStage];
7848
7849                                 // Image layout transition in srcStage are now available in dstStage
7850                                 m_unavailableLayoutTransition[dstStage] &= oldUnavailableLayoutTransition[srcStage];
7851
7852                                 for (vk::VkPipelineStageFlags sharedStage_ = 1; sharedStage_ <= m_allowedStages; sharedStage_ <<= 1)
7853                                 {
7854                                         const PipelineStage     sharedStage                     = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)sharedStage_);
7855
7856                                         if ((sharedStage_ & m_allowedStages) == 0)
7857                                                 continue;
7858
7859                                         // Writes that are available in srcStage are also available in dstStage
7860                                         m_unavailableWriteOperations[dstStage][sharedStage] &= oldUnavailableWriteOperations[srcStage][sharedStage];
7861                                 }
7862                         }
7863                 }
7864         }
7865
7866         // Barrier
7867         for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= dstStages; dstStage_ <<= 1)
7868         {
7869                 const PipelineStage     dstStage                        = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
7870                 bool                            allWritesAvailable      = true;
7871
7872                 if ((dstStage_ & dstStages) == 0)
7873                         continue;
7874
7875                 // Operations in srcStages have completed before any stage in dstStages
7876                 m_incompleteOperations[dstStage] &= ~srcStages;
7877
7878                 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
7879                 {
7880                         const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
7881
7882                         if ((srcStage_ & m_allowedStages) == 0)
7883                                 continue;
7884
7885                         // Make srcAccesses from srcStage available in dstStage
7886                         if ((srcStage_ & srcStages) != 0)
7887                                 m_unavailableWriteOperations[dstStage][srcStage] &= ~srcAccesses;
7888
7889                         if (m_unavailableWriteOperations[dstStage][srcStage] != 0)
7890                                 allWritesAvailable = false;
7891                 }
7892
7893                 // If all writes are available in dstStage make dstAccesses also visible
7894                 if (allWritesAvailable)
7895                         m_invisibleOperations[dstStage] &= ~dstAccesses;
7896         }
7897 }
7898
7899 bool CacheState::isClean (void) const
7900 {
7901         for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
7902         {
7903                 const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
7904
7905                 if ((dstStage_ & m_allowedStages) == 0)
7906                         continue;
7907
7908                 // Some operations are not visible to some stages
7909                 if (m_invisibleOperations[dstStage] != 0)
7910                         return false;
7911
7912                 // There are operation that have not completed yet
7913                 if (m_incompleteOperations[dstStage] != 0)
7914                         return false;
7915
7916                 // Layout transition has not completed yet
7917                 if (m_unavailableLayoutTransition[dstStage])
7918                         return false;
7919
7920                 for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
7921                 {
7922                         const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
7923
7924                         if ((srcStage_ & m_allowedStages) == 0)
7925                                 continue;
7926
7927                         // Some write operations are not available yet
7928                         if (m_unavailableWriteOperations[dstStage][srcStage] != 0)
7929                                 return false;
7930                 }
7931         }
7932
7933         return true;
7934 }
7935
7936 bool layoutSupportedByUsage (Usage usage, vk::VkImageLayout layout)
7937 {
7938         switch (layout)
7939         {
7940                 case vk::VK_IMAGE_LAYOUT_GENERAL:
7941                         return true;
7942
7943                 case vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
7944                         return (usage & USAGE_COLOR_ATTACHMENT) != 0;
7945
7946                 case vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
7947                         return (usage & USAGE_DEPTH_STENCIL_ATTACHMENT) != 0;
7948
7949                 case vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
7950                         return (usage & USAGE_DEPTH_STENCIL_ATTACHMENT) != 0;
7951
7952                 case vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
7953                         // \todo [2016-03-09 mika] Should include input attachment
7954                         return (usage & USAGE_SAMPLED_IMAGE) != 0;
7955
7956                 case vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
7957                         return (usage & USAGE_TRANSFER_SRC) != 0;
7958
7959                 case vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
7960                         return (usage & USAGE_TRANSFER_DST) != 0;
7961
7962                 case vk::VK_IMAGE_LAYOUT_PREINITIALIZED:
7963                         return true;
7964
7965                 default:
7966                         DE_FATAL("Unknown layout");
7967                         return false;
7968         }
7969 }
7970
7971 size_t getNumberOfSupportedLayouts (Usage usage)
7972 {
7973         const vk::VkImageLayout layouts[] =
7974         {
7975                 vk::VK_IMAGE_LAYOUT_GENERAL,
7976                 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
7977                 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
7978                 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
7979                 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
7980                 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
7981                 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
7982         };
7983         size_t supportedLayoutCount = 0;
7984
7985         for (size_t layoutNdx = 0; layoutNdx < DE_LENGTH_OF_ARRAY(layouts); layoutNdx++)
7986         {
7987                 const vk::VkImageLayout layout = layouts[layoutNdx];
7988
7989                 if (layoutSupportedByUsage(usage, layout))
7990                         supportedLayoutCount++;
7991         }
7992
7993         return supportedLayoutCount;
7994 }
7995
7996 vk::VkImageLayout getRandomNextLayout (de::Random&                      rng,
7997                                                                            Usage                                usage,
7998                                                                            vk::VkImageLayout    previousLayout)
7999 {
8000         const vk::VkImageLayout layouts[] =
8001         {
8002                 vk::VK_IMAGE_LAYOUT_GENERAL,
8003                 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
8004                 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
8005                 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
8006                 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
8007                 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
8008                 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
8009         };
8010         const size_t                    supportedLayoutCount = getNumberOfSupportedLayouts(usage);
8011
8012         DE_ASSERT(supportedLayoutCount > 0);
8013
8014         size_t nextLayoutNdx = ((size_t)rng.getUint64()) % (previousLayout == vk::VK_IMAGE_LAYOUT_UNDEFINED
8015                                                                                                                 ? supportedLayoutCount
8016                                                                                                                 : supportedLayoutCount - 1);
8017
8018         for (size_t layoutNdx = 0; layoutNdx < DE_LENGTH_OF_ARRAY(layouts); layoutNdx++)
8019         {
8020                 const vk::VkImageLayout layout = layouts[layoutNdx];
8021
8022                 if (layoutSupportedByUsage(usage, layout) && layout != previousLayout)
8023                 {
8024                         if (nextLayoutNdx == 0)
8025                                 return layout;
8026                         else
8027                                 nextLayoutNdx--;
8028                 }
8029         }
8030
8031         DE_FATAL("Unreachable");
8032         return vk::VK_IMAGE_LAYOUT_UNDEFINED;
8033 }
8034
8035 struct State
8036 {
8037         State (Usage usage, deUint32 seed)
8038                 : stage                                 (STAGE_HOST)
8039                 , cache                                 (usageToStageFlags(usage), usageToAccessFlags(usage))
8040                 , rng                                   (seed)
8041                 , mapped                                (false)
8042                 , hostInvalidated               (true)
8043                 , hostFlushed                   (true)
8044                 , memoryDefined                 (false)
8045                 , hasBuffer                             (false)
8046                 , hasBoundBufferMemory  (false)
8047                 , hasImage                              (false)
8048                 , hasBoundImageMemory   (false)
8049                 , imageLayout                   (vk::VK_IMAGE_LAYOUT_UNDEFINED)
8050                 , imageDefined                  (false)
8051                 , queueIdle                             (true)
8052                 , deviceIdle                    (true)
8053                 , commandBufferIsEmpty  (true)
8054                 , renderPassIsEmpty             (true)
8055         {
8056         }
8057
8058         Stage                           stage;
8059         CacheState                      cache;
8060         de::Random                      rng;
8061
8062         bool                            mapped;
8063         bool                            hostInvalidated;
8064         bool                            hostFlushed;
8065         bool                            memoryDefined;
8066
8067         bool                            hasBuffer;
8068         bool                            hasBoundBufferMemory;
8069
8070         bool                            hasImage;
8071         bool                            hasBoundImageMemory;
8072         vk::VkImageLayout       imageLayout;
8073         bool                            imageDefined;
8074
8075         bool                            queueIdle;
8076         bool                            deviceIdle;
8077
8078         bool                            commandBufferIsEmpty;
8079         bool                            renderPassIsEmpty;
8080 };
8081
8082 void getAvailableOps (const State& state, bool supportsBuffers, bool supportsImages, Usage usage, vector<Op>& ops)
8083 {
8084         if (state.stage == STAGE_HOST)
8085         {
8086                 if (usage & (USAGE_HOST_READ | USAGE_HOST_WRITE))
8087                 {
8088                         // Host memory operations
8089                         if (state.mapped)
8090                         {
8091                                 ops.push_back(OP_UNMAP);
8092
8093                                 // Avoid flush and finish if they are not needed
8094                                 if (!state.hostFlushed)
8095                                         ops.push_back(OP_MAP_FLUSH);
8096
8097                                 if (!state.hostInvalidated
8098                                         && state.queueIdle
8099                                         && ((usage & USAGE_HOST_READ) == 0
8100                                                 || state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_READ_BIT))
8101                                         && ((usage & USAGE_HOST_WRITE) == 0
8102                                                 || state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_WRITE_BIT)))
8103                                 {
8104                                         ops.push_back(OP_MAP_INVALIDATE);
8105                                 }
8106
8107                                 if (usage & USAGE_HOST_READ
8108                                         && usage & USAGE_HOST_WRITE
8109                                         && state.memoryDefined
8110                                         && state.hostInvalidated
8111                                         && state.queueIdle
8112                                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_WRITE_BIT)
8113                                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_READ_BIT))
8114                                 {
8115                                         ops.push_back(OP_MAP_MODIFY);
8116                                 }
8117
8118                                 if (usage & USAGE_HOST_READ
8119                                         && state.memoryDefined
8120                                         && state.hostInvalidated
8121                                         && state.queueIdle
8122                                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_READ_BIT))
8123                                 {
8124                                         ops.push_back(OP_MAP_READ);
8125                                 }
8126
8127                                 if (usage & USAGE_HOST_WRITE
8128                                         && state.hostInvalidated
8129                                         && state.queueIdle
8130                                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_ACCESS_HOST_WRITE_BIT))
8131                                 {
8132                                         ops.push_back(OP_MAP_WRITE);
8133                                 }
8134                         }
8135                         else
8136                                 ops.push_back(OP_MAP);
8137                 }
8138
8139                 if (state.hasBoundBufferMemory && state.queueIdle)
8140                 {
8141                         // \note Destroy only buffers after they have been bound
8142                         ops.push_back(OP_BUFFER_DESTROY);
8143                 }
8144                 else
8145                 {
8146                         if (state.hasBuffer)
8147                         {
8148                                 if (!state.hasBoundBufferMemory)
8149                                         ops.push_back(OP_BUFFER_BINDMEMORY);
8150                         }
8151                         else if (!state.hasImage && supportsBuffers)    // Avoid creating buffer if there is already image
8152                                 ops.push_back(OP_BUFFER_CREATE);
8153                 }
8154
8155                 if (state.hasBoundImageMemory && state.queueIdle)
8156                 {
8157                         // \note Destroy only image after they have been bound
8158                         ops.push_back(OP_IMAGE_DESTROY);
8159                 }
8160                 else
8161                 {
8162                         if (state.hasImage)
8163                         {
8164                                 if (!state.hasBoundImageMemory)
8165                                         ops.push_back(OP_IMAGE_BINDMEMORY);
8166                         }
8167                         else if (!state.hasBuffer && supportsImages)    // Avoid creating image if there is already buffer
8168                                 ops.push_back(OP_IMAGE_CREATE);
8169                 }
8170
8171                 // Host writes must be flushed before GPU commands and there must be
8172                 // buffer or image for GPU commands
8173                 if (state.hostFlushed
8174                         && (state.memoryDefined || supportsDeviceBufferWrites(usage) || state.imageDefined || supportsDeviceImageWrites(usage))
8175                         && (state.hasBoundBufferMemory || state.hasBoundImageMemory) // Avoid command buffers if there is no object to use
8176                         && (usageToStageFlags(usage) & (~vk::VK_PIPELINE_STAGE_HOST_BIT)) != 0) // Don't start command buffer if there are no ways to use memory from gpu
8177                 {
8178                         ops.push_back(OP_COMMAND_BUFFER_BEGIN);
8179                 }
8180
8181                 if (!state.deviceIdle)
8182                         ops.push_back(OP_DEVICE_WAIT_FOR_IDLE);
8183
8184                 if (!state.queueIdle)
8185                         ops.push_back(OP_QUEUE_WAIT_FOR_IDLE);
8186         }
8187         else if (state.stage == STAGE_COMMAND_BUFFER)
8188         {
8189                 if (!state.cache.isClean())
8190                 {
8191                         ops.push_back(OP_PIPELINE_BARRIER_GLOBAL);
8192
8193                         if (state.hasImage)
8194                                 ops.push_back(OP_PIPELINE_BARRIER_IMAGE);
8195
8196                         if (state.hasBuffer)
8197                                 ops.push_back(OP_PIPELINE_BARRIER_BUFFER);
8198                 }
8199
8200                 if (state.hasBoundBufferMemory)
8201                 {
8202                         if (usage & USAGE_TRANSFER_DST
8203                                 && state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT))
8204                         {
8205                                 ops.push_back(OP_BUFFER_FILL);
8206                                 ops.push_back(OP_BUFFER_UPDATE);
8207                                 ops.push_back(OP_BUFFER_COPY_FROM_BUFFER);
8208                                 ops.push_back(OP_BUFFER_COPY_FROM_IMAGE);
8209                         }
8210
8211                         if (usage & USAGE_TRANSFER_SRC
8212                                 && state.memoryDefined
8213                                 && state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT))
8214                         {
8215                                 ops.push_back(OP_BUFFER_COPY_TO_BUFFER);
8216                                 ops.push_back(OP_BUFFER_COPY_TO_IMAGE);
8217                         }
8218                 }
8219
8220                 if (state.hasBoundImageMemory
8221                         && (state.imageLayout == vk::VK_IMAGE_LAYOUT_UNDEFINED
8222                                 || getNumberOfSupportedLayouts(usage) > 1))
8223                 {
8224                         ops.push_back(OP_IMAGE_TRANSITION_LAYOUT);
8225
8226                         {
8227                                 if (usage & USAGE_TRANSFER_DST
8228                                         && (state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL
8229                                                 || state.imageLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
8230                                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT))
8231                                 {
8232                                         ops.push_back(OP_IMAGE_COPY_FROM_BUFFER);
8233                                         ops.push_back(OP_IMAGE_COPY_FROM_IMAGE);
8234                                         ops.push_back(OP_IMAGE_BLIT_FROM_IMAGE);
8235                                 }
8236
8237                                 if (usage & USAGE_TRANSFER_SRC
8238                                         && (state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL
8239                                                 || state.imageLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
8240                                         && state.imageDefined
8241                                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT))
8242                                 {
8243                                         ops.push_back(OP_IMAGE_COPY_TO_BUFFER);
8244                                         ops.push_back(OP_IMAGE_COPY_TO_IMAGE);
8245                                         ops.push_back(OP_IMAGE_BLIT_TO_IMAGE);
8246                                 }
8247                         }
8248                 }
8249
8250                 // \todo [2016-03-09 mika] Add other usages?
8251                 if ((state.memoryDefined
8252                                 && state.hasBoundBufferMemory
8253                                 && (((usage & USAGE_VERTEX_BUFFER)
8254                                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT))
8255                                 || ((usage & USAGE_INDEX_BUFFER)
8256                                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_INDEX_READ_BIT))
8257                                 || ((usage & USAGE_UNIFORM_BUFFER)
8258                                         && (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT)
8259                                                 || state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT)))
8260                                 || ((usage & USAGE_UNIFORM_TEXEL_BUFFER)
8261                                         && (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT)
8262                                                 || state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT)))
8263                                 || ((usage & USAGE_STORAGE_BUFFER)
8264                                         && (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT)
8265                                                 || state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT)))
8266                                 || ((usage & USAGE_STORAGE_TEXEL_BUFFER)
8267                                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))))
8268                         || (state.imageDefined
8269                                 && state.hasBoundImageMemory
8270                                 && (((usage & USAGE_STORAGE_IMAGE)
8271                                                 && state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL
8272                                                 && (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT)
8273                                                         || state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT)))
8274                                         || ((usage & USAGE_SAMPLED_IMAGE)
8275                                                 && (state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL
8276                                                         || state.imageLayout == vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
8277                                                 && (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT)
8278                                                         || state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))))))
8279                 {
8280                         ops.push_back(OP_RENDERPASS_BEGIN);
8281                 }
8282
8283                 // \note This depends on previous operations and has to be always the
8284                 // last command buffer operation check
8285                 if (ops.empty() || !state.commandBufferIsEmpty)
8286                         ops.push_back(OP_COMMAND_BUFFER_END);
8287         }
8288         else if (state.stage == STAGE_RENDER_PASS)
8289         {
8290                 if ((usage & USAGE_VERTEX_BUFFER) != 0
8291                         && state.memoryDefined
8292                         && state.hasBoundBufferMemory
8293                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT))
8294                 {
8295                         ops.push_back(OP_RENDER_VERTEX_BUFFER);
8296                 }
8297
8298                 if ((usage & USAGE_INDEX_BUFFER) != 0
8299                         && state.memoryDefined
8300                         && state.hasBoundBufferMemory
8301                         && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_INDEX_READ_BIT))
8302                 {
8303                         ops.push_back(OP_RENDER_INDEX_BUFFER);
8304                 }
8305
8306                 if ((usage & USAGE_UNIFORM_BUFFER) != 0
8307                         && state.memoryDefined
8308                         && state.hasBoundBufferMemory)
8309                 {
8310                         if (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT))
8311                                 ops.push_back(OP_RENDER_VERTEX_UNIFORM_BUFFER);
8312
8313                         if (state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT))
8314                                 ops.push_back(OP_RENDER_FRAGMENT_UNIFORM_BUFFER);
8315                 }
8316
8317                 if ((usage & USAGE_UNIFORM_TEXEL_BUFFER) != 0
8318                         && state.memoryDefined
8319                         && state.hasBoundBufferMemory)
8320                 {
8321                         if (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT))
8322                                 ops.push_back(OP_RENDER_VERTEX_UNIFORM_TEXEL_BUFFER);
8323
8324                         if (state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT))
8325                                 ops.push_back(OP_RENDER_FRAGMENT_UNIFORM_TEXEL_BUFFER);
8326                 }
8327
8328                 if ((usage & USAGE_STORAGE_BUFFER) != 0
8329                         && state.memoryDefined
8330                         && state.hasBoundBufferMemory)
8331                 {
8332                         if (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))
8333                                 ops.push_back(OP_RENDER_VERTEX_STORAGE_BUFFER);
8334
8335                         if (state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))
8336                                 ops.push_back(OP_RENDER_FRAGMENT_STORAGE_BUFFER);
8337                 }
8338
8339                 if ((usage & USAGE_STORAGE_TEXEL_BUFFER) != 0
8340                         && state.memoryDefined
8341                         && state.hasBoundBufferMemory)
8342                 {
8343                         if (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))
8344                                 ops.push_back(OP_RENDER_VERTEX_STORAGE_TEXEL_BUFFER);
8345
8346                         if (state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))
8347                                 ops.push_back(OP_RENDER_FRAGMENT_STORAGE_TEXEL_BUFFER);
8348                 }
8349
8350                 if ((usage & USAGE_STORAGE_IMAGE) != 0
8351                         && state.imageDefined
8352                         && state.hasBoundImageMemory
8353                         && (state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL))
8354                 {
8355                         if (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))
8356                                 ops.push_back(OP_RENDER_VERTEX_STORAGE_IMAGE);
8357
8358                         if (state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))
8359                                 ops.push_back(OP_RENDER_FRAGMENT_STORAGE_IMAGE);
8360                 }
8361
8362                 if ((usage & USAGE_SAMPLED_IMAGE) != 0
8363                         && state.imageDefined
8364                         && state.hasBoundImageMemory
8365                         && (state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL
8366                                 || state.imageLayout == vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL))
8367                 {
8368                         if (state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))
8369                                 ops.push_back(OP_RENDER_VERTEX_SAMPLED_IMAGE);
8370
8371                         if (state.cache.isValid(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT))
8372                                 ops.push_back(OP_RENDER_FRAGMENT_SAMPLED_IMAGE);
8373                 }
8374
8375                 if (!state.renderPassIsEmpty)
8376                         ops.push_back(OP_RENDERPASS_END);
8377         }
8378         else
8379                 DE_FATAL("Unknown stage");
8380 }
8381
8382 void applyOp (State& state, const Memory& memory, Op op, Usage usage)
8383 {
8384         switch (op)
8385         {
8386                 case OP_MAP:
8387                         DE_ASSERT(state.stage == STAGE_HOST);
8388                         DE_ASSERT(!state.mapped);
8389                         state.mapped = true;
8390                         break;
8391
8392                 case OP_UNMAP:
8393                         DE_ASSERT(state.stage == STAGE_HOST);
8394                         DE_ASSERT(state.mapped);
8395                         state.mapped = false;
8396                         break;
8397
8398                 case OP_MAP_FLUSH:
8399                         DE_ASSERT(state.stage == STAGE_HOST);
8400                         DE_ASSERT(!state.hostFlushed);
8401                         state.hostFlushed = true;
8402                         break;
8403
8404                 case OP_MAP_INVALIDATE:
8405                         DE_ASSERT(state.stage == STAGE_HOST);
8406                         DE_ASSERT(!state.hostInvalidated);
8407                         state.hostInvalidated = true;
8408                         break;
8409
8410                 case OP_MAP_READ:
8411                         DE_ASSERT(state.stage == STAGE_HOST);
8412                         DE_ASSERT(state.hostInvalidated);
8413                         state.rng.getUint32();
8414                         break;
8415
8416                 case OP_MAP_WRITE:
8417                         DE_ASSERT(state.stage == STAGE_HOST);
8418                         if ((memory.getMemoryType().propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
8419                                 state.hostFlushed = false;
8420
8421                         state.memoryDefined = true;
8422                         state.imageDefined = false;
8423                         state.imageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
8424                         state.rng.getUint32();
8425                         break;
8426
8427                 case OP_MAP_MODIFY:
8428                         DE_ASSERT(state.stage == STAGE_HOST);
8429                         DE_ASSERT(state.hostInvalidated);
8430
8431                         if ((memory.getMemoryType().propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
8432                                 state.hostFlushed = false;
8433
8434                         state.rng.getUint32();
8435                         break;
8436
8437                 case OP_BUFFER_CREATE:
8438                         DE_ASSERT(state.stage == STAGE_HOST);
8439                         DE_ASSERT(!state.hasBuffer);
8440
8441                         state.hasBuffer = true;
8442                         break;
8443
8444                 case OP_BUFFER_DESTROY:
8445                         DE_ASSERT(state.stage == STAGE_HOST);
8446                         DE_ASSERT(state.hasBuffer);
8447                         DE_ASSERT(state.hasBoundBufferMemory);
8448
8449                         state.hasBuffer = false;
8450                         state.hasBoundBufferMemory = false;
8451                         break;
8452
8453                 case OP_BUFFER_BINDMEMORY:
8454                         DE_ASSERT(state.stage == STAGE_HOST);
8455                         DE_ASSERT(state.hasBuffer);
8456                         DE_ASSERT(!state.hasBoundBufferMemory);
8457
8458                         state.hasBoundBufferMemory = true;
8459                         break;
8460
8461                 case OP_IMAGE_CREATE:
8462                         DE_ASSERT(state.stage == STAGE_HOST);
8463                         DE_ASSERT(!state.hasImage);
8464                         DE_ASSERT(!state.hasBuffer);
8465
8466                         state.hasImage = true;
8467                         break;
8468
8469                 case OP_IMAGE_DESTROY:
8470                         DE_ASSERT(state.stage == STAGE_HOST);
8471                         DE_ASSERT(state.hasImage);
8472                         DE_ASSERT(state.hasBoundImageMemory);
8473
8474                         state.hasImage = false;
8475                         state.hasBoundImageMemory = false;
8476                         state.imageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
8477                         state.imageDefined = false;
8478                         break;
8479
8480                 case OP_IMAGE_BINDMEMORY:
8481                         DE_ASSERT(state.stage == STAGE_HOST);
8482                         DE_ASSERT(state.hasImage);
8483                         DE_ASSERT(!state.hasBoundImageMemory);
8484
8485                         state.hasBoundImageMemory = true;
8486                         break;
8487
8488                 case OP_IMAGE_TRANSITION_LAYOUT:
8489                 {
8490                         DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
8491                         DE_ASSERT(state.hasImage);
8492                         DE_ASSERT(state.hasBoundImageMemory);
8493
8494                         // \todo [2016-03-09 mika] Support linear tiling and predefined data
8495                         const vk::VkImageLayout         srcLayout       = state.rng.getFloat() < 0.9f ? state.imageLayout : vk::VK_IMAGE_LAYOUT_UNDEFINED;
8496                         const vk::VkImageLayout         dstLayout       = getRandomNextLayout(state.rng, usage, srcLayout);
8497
8498                         vk::VkPipelineStageFlags        dirtySrcStages;
8499                         vk::VkAccessFlags                       dirtySrcAccesses;
8500                         vk::VkPipelineStageFlags        dirtyDstStages;
8501                         vk::VkAccessFlags                       dirtyDstAccesses;
8502
8503                         vk::VkPipelineStageFlags        srcStages;
8504                         vk::VkAccessFlags                       srcAccesses;
8505                         vk::VkPipelineStageFlags        dstStages;
8506                         vk::VkAccessFlags                       dstAccesses;
8507
8508                         state.cache.getFullBarrier(dirtySrcStages, dirtySrcAccesses, dirtyDstStages, dirtyDstAccesses);
8509
8510                         // Try masking some random bits
8511                         srcStages       = dirtySrcStages;
8512                         srcAccesses     = dirtySrcAccesses;
8513
8514                         dstStages       = state.cache.getAllowedStages() & state.rng.getUint32();
8515                         dstAccesses     = state.cache.getAllowedAcceses() & state.rng.getUint32();
8516
8517                         // If there are no bits in dst stage mask use all stages
8518                         dstStages       = dstStages ? dstStages : state.cache.getAllowedStages();
8519
8520                         if (!srcStages)
8521                                 srcStages = dstStages;
8522
8523                         if (srcLayout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
8524                                 state.imageDefined = false;
8525
8526                         state.commandBufferIsEmpty = false;
8527                         state.imageLayout = dstLayout;
8528                         state.memoryDefined = false;
8529                         state.cache.imageLayoutBarrier(srcStages, srcAccesses, dstStages, dstAccesses);
8530                         break;
8531                 }
8532
8533                 case OP_QUEUE_WAIT_FOR_IDLE:
8534                         DE_ASSERT(state.stage == STAGE_HOST);
8535                         DE_ASSERT(!state.queueIdle);
8536
8537                         state.queueIdle = true;
8538
8539                         state.cache.waitForIdle();
8540                         break;
8541
8542                 case OP_DEVICE_WAIT_FOR_IDLE:
8543                         DE_ASSERT(state.stage == STAGE_HOST);
8544                         DE_ASSERT(!state.deviceIdle);
8545
8546                         state.queueIdle = true;
8547                         state.deviceIdle = true;
8548
8549                         state.cache.waitForIdle();
8550                         break;
8551
8552                 case OP_COMMAND_BUFFER_BEGIN:
8553                         DE_ASSERT(state.stage == STAGE_HOST);
8554                         state.stage = STAGE_COMMAND_BUFFER;
8555                         state.commandBufferIsEmpty = true;
8556                         // Makes host writes visible to command buffer
8557                         state.cache.submitCommandBuffer();
8558                         break;
8559
8560                 case OP_COMMAND_BUFFER_END:
8561                         DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
8562                         state.stage = STAGE_HOST;
8563                         state.queueIdle = false;
8564                         state.deviceIdle = false;
8565                         break;
8566
8567                 case OP_BUFFER_COPY_FROM_BUFFER:
8568                 case OP_BUFFER_COPY_FROM_IMAGE:
8569                 case OP_BUFFER_UPDATE:
8570                 case OP_BUFFER_FILL:
8571                         state.rng.getUint32();
8572                         DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
8573
8574                         if ((memory.getMemoryType().propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
8575                                 state.hostInvalidated = false;
8576
8577                         state.commandBufferIsEmpty = false;
8578                         state.memoryDefined = true;
8579                         state.imageDefined = false;
8580                         state.imageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
8581                         state.cache.perform(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT);
8582                         break;
8583
8584                 case OP_BUFFER_COPY_TO_BUFFER:
8585                 case OP_BUFFER_COPY_TO_IMAGE:
8586                         DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
8587
8588                         state.commandBufferIsEmpty = false;
8589                         state.cache.perform(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT);
8590                         break;
8591
8592                 case OP_IMAGE_BLIT_FROM_IMAGE:
8593                         state.rng.getBool();
8594                         // Fall through
8595                 case OP_IMAGE_COPY_FROM_BUFFER:
8596                 case OP_IMAGE_COPY_FROM_IMAGE:
8597                         state.rng.getUint32();
8598                         DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
8599
8600                         if ((memory.getMemoryType().propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
8601                                 state.hostInvalidated = false;
8602
8603                         state.commandBufferIsEmpty = false;
8604                         state.memoryDefined = false;
8605                         state.imageDefined = true;
8606                         state.cache.perform(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT);
8607                         break;
8608
8609                 case OP_IMAGE_BLIT_TO_IMAGE:
8610                         state.rng.getBool();
8611                         // Fall through
8612                 case OP_IMAGE_COPY_TO_BUFFER:
8613                 case OP_IMAGE_COPY_TO_IMAGE:
8614                         DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
8615
8616                         state.commandBufferIsEmpty = false;
8617                         state.cache.perform(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT);
8618                         break;
8619
8620                 case OP_PIPELINE_BARRIER_GLOBAL:
8621                 case OP_PIPELINE_BARRIER_BUFFER:
8622                 case OP_PIPELINE_BARRIER_IMAGE:
8623                 {
8624                         DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
8625
8626                         vk::VkPipelineStageFlags        dirtySrcStages;
8627                         vk::VkAccessFlags                       dirtySrcAccesses;
8628                         vk::VkPipelineStageFlags        dirtyDstStages;
8629                         vk::VkAccessFlags                       dirtyDstAccesses;
8630
8631                         vk::VkPipelineStageFlags        srcStages;
8632                         vk::VkAccessFlags                       srcAccesses;
8633                         vk::VkPipelineStageFlags        dstStages;
8634                         vk::VkAccessFlags                       dstAccesses;
8635
8636                         state.cache.getFullBarrier(dirtySrcStages, dirtySrcAccesses, dirtyDstStages, dirtyDstAccesses);
8637
8638                         // Try masking some random bits
8639                         srcStages       = dirtySrcStages & state.rng.getUint32();
8640                         srcAccesses     = dirtySrcAccesses & state.rng.getUint32();
8641
8642                         dstStages       = dirtyDstStages & state.rng.getUint32();
8643                         dstAccesses     = dirtyDstAccesses & state.rng.getUint32();
8644
8645                         // If there are no bits in stage mask use the original dirty stages
8646                         srcStages       = srcStages ? srcStages : dirtySrcStages;
8647                         dstStages       = dstStages ? dstStages : dirtyDstStages;
8648
8649                         if (!srcStages)
8650                                 srcStages = dstStages;
8651
8652                         state.commandBufferIsEmpty = false;
8653                         state.cache.barrier(srcStages, srcAccesses, dstStages, dstAccesses);
8654                         break;
8655                 }
8656
8657                 case OP_RENDERPASS_BEGIN:
8658                 {
8659                         DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
8660
8661                         state.renderPassIsEmpty = true;
8662                         state.stage                             = STAGE_RENDER_PASS;
8663                         break;
8664                 }
8665
8666                 case OP_RENDERPASS_END:
8667                 {
8668                         DE_ASSERT(state.stage == STAGE_RENDER_PASS);
8669
8670                         state.renderPassIsEmpty = true;
8671                         state.stage                             = STAGE_COMMAND_BUFFER;
8672                         break;
8673                 }
8674
8675                 case OP_RENDER_VERTEX_BUFFER:
8676                 {
8677                         DE_ASSERT(state.stage == STAGE_RENDER_PASS);
8678
8679                         state.renderPassIsEmpty = false;
8680                         state.cache.perform(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT);
8681                         break;
8682                 }
8683
8684                 case OP_RENDER_INDEX_BUFFER:
8685                 {
8686                         DE_ASSERT(state.stage == STAGE_RENDER_PASS);
8687
8688                         state.renderPassIsEmpty = false;
8689                         state.cache.perform(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_INDEX_READ_BIT);
8690                         break;
8691                 }
8692
8693                 case OP_RENDER_VERTEX_UNIFORM_BUFFER:
8694                 case OP_RENDER_VERTEX_UNIFORM_TEXEL_BUFFER:
8695                 {
8696                         DE_ASSERT(state.stage == STAGE_RENDER_PASS);
8697
8698                         state.renderPassIsEmpty = false;
8699                         state.cache.perform(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT);
8700                         break;
8701                 }
8702
8703                 case OP_RENDER_FRAGMENT_UNIFORM_BUFFER:
8704                 case OP_RENDER_FRAGMENT_UNIFORM_TEXEL_BUFFER:
8705                 {
8706                         DE_ASSERT(state.stage == STAGE_RENDER_PASS);
8707
8708                         state.renderPassIsEmpty = false;
8709                         state.cache.perform(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT);
8710                         break;
8711                 }
8712
8713                 case OP_RENDER_VERTEX_STORAGE_BUFFER:
8714                 case OP_RENDER_VERTEX_STORAGE_TEXEL_BUFFER:
8715                 {
8716                         DE_ASSERT(state.stage == STAGE_RENDER_PASS);
8717
8718                         state.renderPassIsEmpty = false;
8719                         state.cache.perform(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT);
8720                         break;
8721                 }
8722
8723                 case OP_RENDER_FRAGMENT_STORAGE_BUFFER:
8724                 case OP_RENDER_FRAGMENT_STORAGE_TEXEL_BUFFER:
8725                 {
8726                         DE_ASSERT(state.stage == STAGE_RENDER_PASS);
8727
8728                         state.renderPassIsEmpty = false;
8729                         state.cache.perform(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT);
8730                         break;
8731                 }
8732
8733                 case OP_RENDER_FRAGMENT_STORAGE_IMAGE:
8734                 case OP_RENDER_FRAGMENT_SAMPLED_IMAGE:
8735                 {
8736                         DE_ASSERT(state.stage == STAGE_RENDER_PASS);
8737
8738                         state.renderPassIsEmpty = false;
8739                         state.cache.perform(vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT);
8740                         break;
8741                 }
8742
8743                 case OP_RENDER_VERTEX_STORAGE_IMAGE:
8744                 case OP_RENDER_VERTEX_SAMPLED_IMAGE:
8745                 {
8746                         DE_ASSERT(state.stage == STAGE_RENDER_PASS);
8747
8748                         state.renderPassIsEmpty = false;
8749                         state.cache.perform(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_SHADER_READ_BIT);
8750                         break;
8751                 }
8752
8753                 default:
8754                         DE_FATAL("Unknown op");
8755         }
8756 }
8757
8758 de::MovePtr<Command> createHostCommand (Op                                      op,
8759                                                                                 de::Random&                     rng,
8760                                                                                 Usage                           usage,
8761                                                                                 vk::VkSharingMode       sharing)
8762 {
8763         switch (op)
8764         {
8765                 case OP_MAP:                                    return de::MovePtr<Command>(new Map());
8766                 case OP_UNMAP:                                  return de::MovePtr<Command>(new UnMap());
8767
8768                 case OP_MAP_FLUSH:                              return de::MovePtr<Command>(new Flush());
8769                 case OP_MAP_INVALIDATE:                 return de::MovePtr<Command>(new Invalidate());
8770
8771                 case OP_MAP_READ:                               return de::MovePtr<Command>(new HostMemoryAccess(true, false, rng.getUint32()));
8772                 case OP_MAP_WRITE:                              return de::MovePtr<Command>(new HostMemoryAccess(false, true, rng.getUint32()));
8773                 case OP_MAP_MODIFY:                             return de::MovePtr<Command>(new HostMemoryAccess(true, true, rng.getUint32()));
8774
8775                 case OP_BUFFER_CREATE:                  return de::MovePtr<Command>(new CreateBuffer(usageToBufferUsageFlags(usage), sharing));
8776                 case OP_BUFFER_DESTROY:                 return de::MovePtr<Command>(new DestroyBuffer());
8777                 case OP_BUFFER_BINDMEMORY:              return de::MovePtr<Command>(new BindBufferMemory());
8778
8779                 case OP_IMAGE_CREATE:                   return de::MovePtr<Command>(new CreateImage(usageToImageUsageFlags(usage), sharing));
8780                 case OP_IMAGE_DESTROY:                  return de::MovePtr<Command>(new DestroyImage());
8781                 case OP_IMAGE_BINDMEMORY:               return de::MovePtr<Command>(new BindImageMemory());
8782
8783                 case OP_QUEUE_WAIT_FOR_IDLE:    return de::MovePtr<Command>(new QueueWaitIdle());
8784                 case OP_DEVICE_WAIT_FOR_IDLE:   return de::MovePtr<Command>(new DeviceWaitIdle());
8785
8786                 default:
8787                         DE_FATAL("Unknown op");
8788                         return de::MovePtr<Command>(DE_NULL);
8789         }
8790 }
8791
8792 de::MovePtr<CmdCommand> createCmdCommand (de::Random&   rng,
8793                                                                                   const State&  state,
8794                                                                                   Op                    op,
8795                                                                                   Usage                 usage)
8796 {
8797         switch (op)
8798         {
8799                 case OP_BUFFER_FILL:                                    return de::MovePtr<CmdCommand>(new FillBuffer(rng.getUint32()));
8800                 case OP_BUFFER_UPDATE:                                  return de::MovePtr<CmdCommand>(new UpdateBuffer(rng.getUint32()));
8801                 case OP_BUFFER_COPY_TO_BUFFER:                  return de::MovePtr<CmdCommand>(new BufferCopyToBuffer());
8802                 case OP_BUFFER_COPY_FROM_BUFFER:                return de::MovePtr<CmdCommand>(new BufferCopyFromBuffer(rng.getUint32()));
8803
8804                 case OP_BUFFER_COPY_TO_IMAGE:                   return de::MovePtr<CmdCommand>(new BufferCopyToImage());
8805                 case OP_BUFFER_COPY_FROM_IMAGE:                 return de::MovePtr<CmdCommand>(new BufferCopyFromImage(rng.getUint32()));
8806
8807                 case OP_IMAGE_TRANSITION_LAYOUT:
8808                 {
8809                         DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
8810                         DE_ASSERT(state.hasImage);
8811                         DE_ASSERT(state.hasBoundImageMemory);
8812
8813                         const vk::VkImageLayout         srcLayout       = rng.getFloat() < 0.9f ? state.imageLayout : vk::VK_IMAGE_LAYOUT_UNDEFINED;
8814                         const vk::VkImageLayout         dstLayout       = getRandomNextLayout(rng, usage, srcLayout);
8815
8816                         vk::VkPipelineStageFlags        dirtySrcStages;
8817                         vk::VkAccessFlags                       dirtySrcAccesses;
8818                         vk::VkPipelineStageFlags        dirtyDstStages;
8819                         vk::VkAccessFlags                       dirtyDstAccesses;
8820
8821                         vk::VkPipelineStageFlags        srcStages;
8822                         vk::VkAccessFlags                       srcAccesses;
8823                         vk::VkPipelineStageFlags        dstStages;
8824                         vk::VkAccessFlags                       dstAccesses;
8825
8826                         state.cache.getFullBarrier(dirtySrcStages, dirtySrcAccesses, dirtyDstStages, dirtyDstAccesses);
8827
8828                         // Try masking some random bits
8829                         srcStages       = dirtySrcStages;
8830                         srcAccesses     = dirtySrcAccesses;
8831
8832                         dstStages       = state.cache.getAllowedStages() & rng.getUint32();
8833                         dstAccesses     = state.cache.getAllowedAcceses() & rng.getUint32();
8834
8835                         // If there are no bits in dst stage mask use all stages
8836                         dstStages       = dstStages ? dstStages : state.cache.getAllowedStages();
8837
8838                         if (!srcStages)
8839                                 srcStages = dstStages;
8840
8841                         return de::MovePtr<CmdCommand>(new ImageTransition(srcStages, srcAccesses, dstStages, dstAccesses, srcLayout, dstLayout));
8842                 }
8843
8844                 case OP_IMAGE_COPY_TO_BUFFER:                   return de::MovePtr<CmdCommand>(new ImageCopyToBuffer(state.imageLayout));
8845                 case OP_IMAGE_COPY_FROM_BUFFER:                 return de::MovePtr<CmdCommand>(new ImageCopyFromBuffer(rng.getUint32(), state.imageLayout));
8846                 case OP_IMAGE_COPY_TO_IMAGE:                    return de::MovePtr<CmdCommand>(new ImageCopyToImage(state.imageLayout));
8847                 case OP_IMAGE_COPY_FROM_IMAGE:                  return de::MovePtr<CmdCommand>(new ImageCopyFromImage(rng.getUint32(), state.imageLayout));
8848                 case OP_IMAGE_BLIT_TO_IMAGE:
8849                 {
8850                         const BlitScale scale = rng.getBool() ? BLIT_SCALE_20 : BLIT_SCALE_10;
8851                         return de::MovePtr<CmdCommand>(new ImageBlitToImage(scale, state.imageLayout));
8852                 }
8853
8854                 case OP_IMAGE_BLIT_FROM_IMAGE:
8855                 {
8856                         const BlitScale scale = rng.getBool() ? BLIT_SCALE_20 : BLIT_SCALE_10;
8857                         return de::MovePtr<CmdCommand>(new ImageBlitFromImage(rng.getUint32(), scale, state.imageLayout));
8858                 }
8859
8860                 case OP_PIPELINE_BARRIER_GLOBAL:
8861                 case OP_PIPELINE_BARRIER_BUFFER:
8862                 case OP_PIPELINE_BARRIER_IMAGE:
8863                 {
8864                         vk::VkPipelineStageFlags        dirtySrcStages;
8865                         vk::VkAccessFlags                       dirtySrcAccesses;
8866                         vk::VkPipelineStageFlags        dirtyDstStages;
8867                         vk::VkAccessFlags                       dirtyDstAccesses;
8868
8869                         vk::VkPipelineStageFlags        srcStages;
8870                         vk::VkAccessFlags                       srcAccesses;
8871                         vk::VkPipelineStageFlags        dstStages;
8872                         vk::VkAccessFlags                       dstAccesses;
8873
8874                         state.cache.getFullBarrier(dirtySrcStages, dirtySrcAccesses, dirtyDstStages, dirtyDstAccesses);
8875
8876                         // Try masking some random bits
8877                         srcStages       = dirtySrcStages & rng.getUint32();
8878                         srcAccesses     = dirtySrcAccesses & rng.getUint32();
8879
8880                         dstStages       = dirtyDstStages & rng.getUint32();
8881                         dstAccesses     = dirtyDstAccesses & rng.getUint32();
8882
8883                         // If there are no bits in stage mask use the original dirty stages
8884                         srcStages       = srcStages ? srcStages : dirtySrcStages;
8885                         dstStages       = dstStages ? dstStages : dirtyDstStages;
8886
8887                         if (!srcStages)
8888                                 srcStages = dstStages;
8889
8890                         PipelineBarrier::Type type;
8891
8892                         if (op == OP_PIPELINE_BARRIER_IMAGE)
8893                                 type = PipelineBarrier::TYPE_IMAGE;
8894                         else if (op == OP_PIPELINE_BARRIER_BUFFER)
8895                                 type = PipelineBarrier::TYPE_BUFFER;
8896                         else if (op == OP_PIPELINE_BARRIER_GLOBAL)
8897                                 type = PipelineBarrier::TYPE_GLOBAL;
8898                         else
8899                         {
8900                                 type = PipelineBarrier::TYPE_LAST;
8901                                 DE_FATAL("Unknown op");
8902                         }
8903
8904                         if (type == PipelineBarrier::TYPE_IMAGE)
8905                                 return de::MovePtr<CmdCommand>(new PipelineBarrier(srcStages, srcAccesses, dstStages, dstAccesses, type, tcu::just(state.imageLayout)));
8906                         else
8907                                 return de::MovePtr<CmdCommand>(new PipelineBarrier(srcStages, srcAccesses, dstStages, dstAccesses, type, tcu::nothing<vk::VkImageLayout>()));
8908                 }
8909
8910                 default:
8911                         DE_FATAL("Unknown op");
8912                         return de::MovePtr<CmdCommand>(DE_NULL);
8913         }
8914 }
8915
8916 de::MovePtr<RenderPassCommand> createRenderPassCommand (de::Random&,
8917                                                                                                                 const State&,
8918                                                                                                                 Op                              op)
8919 {
8920         switch (op)
8921         {
8922                 case OP_RENDER_VERTEX_BUFFER:                                   return de::MovePtr<RenderPassCommand>(new RenderVertexBuffer());
8923                 case OP_RENDER_INDEX_BUFFER:                                    return de::MovePtr<RenderPassCommand>(new RenderIndexBuffer());
8924
8925                 case OP_RENDER_VERTEX_UNIFORM_BUFFER:                   return de::MovePtr<RenderPassCommand>(new RenderVertexUniformBuffer());
8926                 case OP_RENDER_FRAGMENT_UNIFORM_BUFFER:                 return de::MovePtr<RenderPassCommand>(new RenderFragmentUniformBuffer());
8927
8928                 case OP_RENDER_VERTEX_UNIFORM_TEXEL_BUFFER:             return de::MovePtr<RenderPassCommand>(new RenderVertexUniformTexelBuffer());
8929                 case OP_RENDER_FRAGMENT_UNIFORM_TEXEL_BUFFER:   return de::MovePtr<RenderPassCommand>(new RenderFragmentUniformTexelBuffer());
8930
8931                 case OP_RENDER_VERTEX_STORAGE_BUFFER:                   return de::MovePtr<RenderPassCommand>(new RenderVertexStorageBuffer());
8932                 case OP_RENDER_FRAGMENT_STORAGE_BUFFER:                 return de::MovePtr<RenderPassCommand>(new RenderFragmentStorageBuffer());
8933
8934                 case OP_RENDER_VERTEX_STORAGE_TEXEL_BUFFER:             return de::MovePtr<RenderPassCommand>(new RenderVertexStorageTexelBuffer());
8935                 case OP_RENDER_FRAGMENT_STORAGE_TEXEL_BUFFER:   return de::MovePtr<RenderPassCommand>(new RenderFragmentStorageTexelBuffer());
8936
8937                 case OP_RENDER_VERTEX_STORAGE_IMAGE:                    return de::MovePtr<RenderPassCommand>(new RenderVertexStorageImage());
8938                 case OP_RENDER_FRAGMENT_STORAGE_IMAGE:                  return de::MovePtr<RenderPassCommand>(new RenderFragmentStorageImage());
8939
8940                 case OP_RENDER_VERTEX_SAMPLED_IMAGE:                    return de::MovePtr<RenderPassCommand>(new RenderVertexSampledImage());
8941                 case OP_RENDER_FRAGMENT_SAMPLED_IMAGE:                  return de::MovePtr<RenderPassCommand>(new RenderFragmentSampledImage());
8942
8943                 default:
8944                         DE_FATAL("Unknown op");
8945                         return de::MovePtr<RenderPassCommand>(DE_NULL);
8946         }
8947 }
8948
8949 de::MovePtr<CmdCommand> createRenderPassCommands (const Memory& memory,
8950                                                                                                   de::Random&   nextOpRng,
8951                                                                                                   State&                state,
8952                                                                                                   Usage                 usage,
8953                                                                                                   size_t&               opNdx,
8954                                                                                                   size_t                opCount)
8955 {
8956         vector<RenderPassCommand*>      commands;
8957
8958         try
8959         {
8960                 for (; opNdx < opCount; opNdx++)
8961                 {
8962                         vector<Op>      ops;
8963
8964                         getAvailableOps(state, memory.getSupportBuffers(), memory.getSupportImages(), usage, ops);
8965
8966                         DE_ASSERT(!ops.empty());
8967
8968                         {
8969                                 const Op op = nextOpRng.choose<Op>(ops.begin(), ops.end());
8970
8971                                 if (op == OP_RENDERPASS_END)
8972                                 {
8973                                         break;
8974                                 }
8975                                 else
8976                                 {
8977                                         de::Random      rng     (state.rng);
8978
8979                                         commands.push_back(createRenderPassCommand(rng, state, op).release());
8980                                         applyOp(state, memory, op, usage);
8981
8982                                         DE_ASSERT(state.rng == rng);
8983                                 }
8984                         }
8985                 }
8986
8987                 applyOp(state, memory, OP_RENDERPASS_END, usage);
8988                 return de::MovePtr<CmdCommand>(new SubmitRenderPass(commands));
8989         }
8990         catch (...)
8991         {
8992                 for (size_t commandNdx = 0; commandNdx < commands.size(); commandNdx++)
8993                         delete commands[commandNdx];
8994
8995                 throw;
8996         }
8997 }
8998
8999 de::MovePtr<Command> createCmdCommands (const Memory&   memory,
9000                                                                                 de::Random&             nextOpRng,
9001                                                                                 State&                  state,
9002                                                                                 Usage                   usage,
9003                                                                                 size_t&                 opNdx,
9004                                                                                 size_t                  opCount)
9005 {
9006         vector<CmdCommand*>     commands;
9007
9008         try
9009         {
9010                 for (; opNdx < opCount; opNdx++)
9011                 {
9012                         vector<Op>      ops;
9013
9014                         getAvailableOps(state, memory.getSupportBuffers(), memory.getSupportImages(), usage, ops);
9015
9016                         DE_ASSERT(!ops.empty());
9017
9018                         {
9019                                 const Op op = nextOpRng.choose<Op>(ops.begin(), ops.end());
9020
9021                                 if (op == OP_COMMAND_BUFFER_END)
9022                                 {
9023                                         break;
9024                                 }
9025                                 else
9026                                 {
9027                                         // \note Command needs to known the state before the operation
9028                                         if (op == OP_RENDERPASS_BEGIN)
9029                                         {
9030                                                 applyOp(state, memory, op, usage);
9031                                                 commands.push_back(createRenderPassCommands(memory, nextOpRng, state, usage, opNdx, opCount).release());
9032                                         }
9033                                         else
9034                                         {
9035                                                 de::Random      rng     (state.rng);
9036
9037                                                 commands.push_back(createCmdCommand(rng, state, op, usage).release());
9038                                                 applyOp(state, memory, op, usage);
9039
9040                                                 DE_ASSERT(state.rng == rng);
9041                                         }
9042
9043                                 }
9044                         }
9045                 }
9046
9047                 applyOp(state, memory, OP_COMMAND_BUFFER_END, usage);
9048                 return de::MovePtr<Command>(new SubmitCommandBuffer(commands));
9049         }
9050         catch (...)
9051         {
9052                 for (size_t commandNdx = 0; commandNdx < commands.size(); commandNdx++)
9053                         delete commands[commandNdx];
9054
9055                 throw;
9056         }
9057 }
9058
9059 void createCommands (vector<Command*>&  commands,
9060                                          deUint32                       seed,
9061                                          const Memory&          memory,
9062                                          Usage                          usage,
9063                                          vk::VkSharingMode      sharingMode,
9064                                          size_t                         opCount)
9065 {
9066         State                   state           (usage, seed);
9067         // Used to select next operation only
9068         de::Random              nextOpRng       (seed ^ 12930809);
9069
9070         commands.reserve(opCount);
9071
9072         for (size_t opNdx = 0; opNdx < opCount; opNdx++)
9073         {
9074                 vector<Op>      ops;
9075
9076                 getAvailableOps(state, memory.getSupportBuffers(), memory.getSupportImages(), usage, ops);
9077
9078                 DE_ASSERT(!ops.empty());
9079
9080                 {
9081                         const Op        op      = nextOpRng.choose<Op>(ops.begin(), ops.end());
9082
9083                         if (op == OP_COMMAND_BUFFER_BEGIN)
9084                         {
9085                                 applyOp(state, memory, op, usage);
9086                                 commands.push_back(createCmdCommands(memory, nextOpRng, state, usage, opNdx, opCount).release());
9087                         }
9088                         else
9089                         {
9090                                 de::Random      rng     (state.rng);
9091
9092                                 commands.push_back(createHostCommand(op, rng, usage, sharingMode).release());
9093                                 applyOp(state, memory, op, usage);
9094
9095                                 // Make sure that random generator is in sync
9096                                 DE_ASSERT(state.rng == rng);
9097                         }
9098                 }
9099         }
9100
9101         // Clean up resources
9102         if (state.hasBuffer && state.hasImage)
9103         {
9104                 if (!state.queueIdle)
9105                         commands.push_back(new QueueWaitIdle());
9106
9107                 if (state.hasBuffer)
9108                         commands.push_back(new DestroyBuffer());
9109
9110                 if (state.hasImage)
9111                         commands.push_back(new DestroyImage());
9112         }
9113 }
9114
9115 class MemoryTestInstance : public TestInstance
9116 {
9117 public:
9118
9119         typedef bool(MemoryTestInstance::*StageFunc)(void);
9120
9121                                                                                                 MemoryTestInstance                              (::vkt::Context& context, const TestConfig& config);
9122                                                                                                 ~MemoryTestInstance                             (void);
9123
9124         tcu::TestStatus                                                         iterate                                                 (void);
9125
9126 private:
9127         const TestConfig                                                        m_config;
9128         const size_t                                                            m_iterationCount;
9129         const size_t                                                            m_opCount;
9130         const vk::VkPhysicalDeviceMemoryProperties      m_memoryProperties;
9131         deUint32                                                                        m_memoryTypeNdx;
9132         size_t                                                                          m_iteration;
9133         StageFunc                                                                       m_stage;
9134         tcu::ResultCollector                                            m_resultCollector;
9135
9136         vector<Command*>                                                        m_commands;
9137         MovePtr<Memory>                                                         m_memory;
9138         MovePtr<Context>                                                        m_renderContext;
9139         MovePtr<PrepareContext>                                         m_prepareContext;
9140
9141         bool                                                                            nextIteration                                   (void);
9142         bool                                                                            nextMemoryType                                  (void);
9143
9144         bool                                                                            createCommandsAndAllocateMemory (void);
9145         bool                                                                            prepare                                                 (void);
9146         bool                                                                            execute                                                 (void);
9147         bool                                                                            verify                                                  (void);
9148         void                                                                            resetResources                                  (void);
9149 };
9150
9151 void MemoryTestInstance::resetResources (void)
9152 {
9153         const vk::DeviceInterface&      vkd             = m_context.getDeviceInterface();
9154         const vk::VkDevice                      device  = m_context.getDevice();
9155
9156         VK_CHECK(vkd.deviceWaitIdle(device));
9157
9158         for (size_t commandNdx = 0; commandNdx < m_commands.size(); commandNdx++)
9159         {
9160                 delete m_commands[commandNdx];
9161                 m_commands[commandNdx] = DE_NULL;
9162         }
9163
9164         m_commands.clear();
9165         m_prepareContext.clear();
9166         m_memory.clear();
9167 }
9168
9169 bool MemoryTestInstance::nextIteration (void)
9170 {
9171         m_iteration++;
9172
9173         if (m_iteration < m_iterationCount)
9174         {
9175                 resetResources();
9176                 m_stage = &MemoryTestInstance::createCommandsAndAllocateMemory;
9177                 return true;
9178         }
9179         else
9180                 return nextMemoryType();
9181 }
9182
9183 bool MemoryTestInstance::nextMemoryType (void)
9184 {
9185         resetResources();
9186
9187         DE_ASSERT(m_commands.empty());
9188
9189         m_memoryTypeNdx++;
9190
9191         if (m_memoryTypeNdx < m_memoryProperties.memoryTypeCount)
9192         {
9193                 m_iteration     = 0;
9194                 m_stage         = &MemoryTestInstance::createCommandsAndAllocateMemory;
9195
9196                 return true;
9197         }
9198         else
9199         {
9200                 m_stage = DE_NULL;
9201                 return false;
9202         }
9203 }
9204
9205 MemoryTestInstance::MemoryTestInstance (::vkt::Context& context, const TestConfig& config)
9206         : TestInstance                  (context)
9207         , m_config                              (config)
9208         , m_iterationCount              (5)
9209         , m_opCount                             (50)
9210         , m_memoryProperties    (vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()))
9211         , m_memoryTypeNdx               (0)
9212         , m_iteration                   (0)
9213         , m_stage                               (&MemoryTestInstance::createCommandsAndAllocateMemory)
9214         , m_resultCollector             (context.getTestContext().getLog())
9215
9216         , m_memory                              (DE_NULL)
9217 {
9218         TestLog&        log     = context.getTestContext().getLog();
9219         {
9220                 const tcu::ScopedLogSection section (log, "TestCaseInfo", "Test Case Info");
9221
9222                 log << TestLog::Message << "Buffer size: " << config.size << TestLog::EndMessage;
9223                 log << TestLog::Message << "Sharing: " << config.sharing << TestLog::EndMessage;
9224                 log << TestLog::Message << "Access: " << config.usage << TestLog::EndMessage;
9225         }
9226
9227         {
9228                 const tcu::ScopedLogSection section (log, "MemoryProperties", "Memory Properties");
9229
9230                 for (deUint32 heapNdx = 0; heapNdx < m_memoryProperties.memoryHeapCount; heapNdx++)
9231                 {
9232                         const tcu::ScopedLogSection heapSection (log, "Heap" + de::toString(heapNdx), "Heap " + de::toString(heapNdx));
9233
9234                         log << TestLog::Message << "Size: " << m_memoryProperties.memoryHeaps[heapNdx].size << TestLog::EndMessage;
9235                         log << TestLog::Message << "Flags: " << m_memoryProperties.memoryHeaps[heapNdx].flags << TestLog::EndMessage;
9236                 }
9237
9238                 for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < m_memoryProperties.memoryTypeCount; memoryTypeNdx++)
9239                 {
9240                         const tcu::ScopedLogSection memoryTypeSection (log, "MemoryType" + de::toString(memoryTypeNdx), "Memory type " + de::toString(memoryTypeNdx));
9241
9242                         log << TestLog::Message << "Properties: " << m_memoryProperties.memoryTypes[memoryTypeNdx].propertyFlags << TestLog::EndMessage;
9243                         log << TestLog::Message << "Heap: " << m_memoryProperties.memoryTypes[memoryTypeNdx].heapIndex << TestLog::EndMessage;
9244                 }
9245         }
9246
9247         {
9248                 const vk::InstanceInterface&                    vki                                     = context.getInstanceInterface();
9249                 const vk::VkPhysicalDevice                              physicalDevice          = context.getPhysicalDevice();
9250                 const vk::DeviceInterface&                              vkd                                     = context.getDeviceInterface();
9251                 const vk::VkDevice                                              device                          = context.getDevice();
9252                 const vk::VkQueue                                               queue                           = context.getUniversalQueue();
9253                 const deUint32                                                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
9254                 vector<pair<deUint32, vk::VkQueue> >    queues;
9255
9256                 queues.push_back(std::make_pair(queueFamilyIndex, queue));
9257
9258                 m_renderContext = MovePtr<Context>(new Context(vki, vkd, physicalDevice, device, queue, queueFamilyIndex, queues, context.getBinaryCollection()));
9259         }
9260 }
9261
9262 MemoryTestInstance::~MemoryTestInstance (void)
9263 {
9264         resetResources();
9265 }
9266
9267 bool MemoryTestInstance::createCommandsAndAllocateMemory (void)
9268 {
9269         const vk::VkDevice                                                      device                          = m_context.getDevice();
9270         TestLog&                                                                        log                                     = m_context.getTestContext().getLog();
9271         const vk::InstanceInterface&                            vki                                     = m_context.getInstanceInterface();
9272         const vk::VkPhysicalDevice                                      physicalDevice          = m_context.getPhysicalDevice();
9273         const vk::DeviceInterface&                                      vkd                                     = m_context.getDeviceInterface();
9274         const vk::VkPhysicalDeviceMemoryProperties      memoryProperties        = vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice);
9275         const tcu::ScopedLogSection                                     section                         (log, "MemoryType" + de::toString(m_memoryTypeNdx) + "CreateCommands" + de::toString(m_iteration),
9276                                                                                                                                                   "Memory type " + de::toString(m_memoryTypeNdx) + " create commands iteration " + de::toString(m_iteration));
9277         const vector<deUint32>&                                         queues                          = m_renderContext->getQueueFamilies();
9278
9279         DE_ASSERT(m_commands.empty());
9280
9281         if (m_config.usage & (USAGE_HOST_READ | USAGE_HOST_WRITE)
9282                 && !(memoryProperties.memoryTypes[m_memoryTypeNdx].propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
9283         {
9284                 log << TestLog::Message << "Memory type not supported" << TestLog::EndMessage;
9285
9286                 return nextMemoryType();
9287         }
9288         else
9289         {
9290                 try
9291                 {
9292                         const vk::VkBufferUsageFlags    bufferUsage             = usageToBufferUsageFlags(m_config.usage);
9293                         const vk::VkImageUsageFlags             imageUsage              = usageToImageUsageFlags(m_config.usage);
9294                         const vk::VkDeviceSize                  maxBufferSize   = bufferUsage != 0
9295                                                                                                                         ? roundBufferSizeToWxHx4(findMaxBufferSize(vkd, device, bufferUsage, m_config.sharing, queues, m_config.size, m_memoryTypeNdx))
9296                                                                                                                         : 0;
9297                         const IVec2                                             maxImageSize    = imageUsage != 0
9298                                                                                                                         ? findMaxRGBA8ImageSize(vkd, device, imageUsage, m_config.sharing, queues, m_config.size, m_memoryTypeNdx)
9299                                                                                                                         : IVec2(0, 0);
9300
9301                         log << TestLog::Message << "Max buffer size: " << maxBufferSize << TestLog::EndMessage;
9302                         log << TestLog::Message << "Max RGBA8 image size: " << maxImageSize << TestLog::EndMessage;
9303
9304                         // Skip tests if there are no supported operations
9305                         if (maxBufferSize == 0
9306                                 && maxImageSize[0] == 0
9307                                 && (m_config.usage & (USAGE_HOST_READ|USAGE_HOST_WRITE)) == 0)
9308                         {
9309                                 log << TestLog::Message << "Skipping memory type. None of the usages are supported." << TestLog::EndMessage;
9310
9311                                 return nextMemoryType();
9312                         }
9313                         else
9314                         {
9315                                 const deUint32  seed    = 2830980989u ^ deUint32Hash((deUint32)(m_iteration) * m_memoryProperties.memoryTypeCount +  m_memoryTypeNdx);
9316
9317                                 m_memory        = MovePtr<Memory>(new Memory(vki, vkd, physicalDevice, device, m_config.size, m_memoryTypeNdx, maxBufferSize, maxImageSize[0], maxImageSize[1]));
9318
9319                                 log << TestLog::Message << "Create commands" << TestLog::EndMessage;
9320                                 createCommands(m_commands, seed, *m_memory, m_config.usage, m_config.sharing, m_opCount);
9321
9322                                 m_stage = &MemoryTestInstance::prepare;
9323                                 return true;
9324                         }
9325                 }
9326                 catch (const tcu::TestError& e)
9327                 {
9328                         m_resultCollector.fail("Failed, got exception: " + string(e.getMessage()));
9329                         return nextMemoryType();
9330                 }
9331         }
9332 }
9333
9334 bool MemoryTestInstance::prepare (void)
9335 {
9336         TestLog&                                        log             = m_context.getTestContext().getLog();
9337         const tcu::ScopedLogSection     section (log, "MemoryType" + de::toString(m_memoryTypeNdx) + "Prepare" + de::toString(m_iteration),
9338                                                                                           "Memory type " + de::toString(m_memoryTypeNdx) + " prepare iteration" + de::toString(m_iteration));
9339
9340         m_prepareContext = MovePtr<PrepareContext>(new PrepareContext(*m_renderContext, *m_memory));
9341
9342         DE_ASSERT(!m_commands.empty());
9343
9344         for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
9345         {
9346                 Command& command = *m_commands[cmdNdx];
9347
9348                 try
9349                 {
9350                         command.prepare(*m_prepareContext);
9351                 }
9352                 catch (const tcu::TestError& e)
9353                 {
9354                         m_resultCollector.fail(de::toString(cmdNdx) + ":" + command.getName() + " failed to prepare, got exception: " + string(e.getMessage()));
9355                         return nextMemoryType();
9356                 }
9357         }
9358
9359         m_stage = &MemoryTestInstance::execute;
9360         return true;
9361 }
9362
9363 bool MemoryTestInstance::execute (void)
9364 {
9365         TestLog&                                        log                             = m_context.getTestContext().getLog();
9366         const tcu::ScopedLogSection     section                 (log, "MemoryType" + de::toString(m_memoryTypeNdx) + "Execute" + de::toString(m_iteration),
9367                                                                                                           "Memory type " + de::toString(m_memoryTypeNdx) + " execute iteration " + de::toString(m_iteration));
9368         ExecuteContext                          executeContext  (*m_renderContext);
9369         const vk::VkDevice                      device                  = m_context.getDevice();
9370         const vk::DeviceInterface&      vkd                             = m_context.getDeviceInterface();
9371
9372         DE_ASSERT(!m_commands.empty());
9373
9374         for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
9375         {
9376                 Command& command = *m_commands[cmdNdx];
9377
9378                 try
9379                 {
9380                         command.execute(executeContext);
9381                 }
9382                 catch (const tcu::TestError& e)
9383                 {
9384                         m_resultCollector.fail(de::toString(cmdNdx) + ":" + command.getName() + " failed to execute, got exception: " + string(e.getMessage()));
9385                         return nextIteration();
9386                 }
9387         }
9388
9389         VK_CHECK(vkd.deviceWaitIdle(device));
9390
9391         m_stage = &MemoryTestInstance::verify;
9392         return true;
9393 }
9394
9395 bool MemoryTestInstance::verify (void)
9396 {
9397         DE_ASSERT(!m_commands.empty());
9398
9399         TestLog&                                        log                             = m_context.getTestContext().getLog();
9400         const tcu::ScopedLogSection     section                 (log, "MemoryType" + de::toString(m_memoryTypeNdx) + "Verify" + de::toString(m_iteration),
9401                                                                                                           "Memory type " + de::toString(m_memoryTypeNdx) + " verify iteration " + de::toString(m_iteration));
9402         VerifyContext                           verifyContext   (log, m_resultCollector, *m_renderContext, m_config.size);
9403
9404         log << TestLog::Message << "Begin verify" << TestLog::EndMessage;
9405
9406         for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
9407         {
9408                 Command& command = *m_commands[cmdNdx];
9409
9410                 try
9411                 {
9412                         command.verify(verifyContext, cmdNdx);
9413                 }
9414                 catch (const tcu::TestError& e)
9415                 {
9416                         m_resultCollector.fail(de::toString(cmdNdx) + ":" + command.getName() + " failed to verify, got exception: " + string(e.getMessage()));
9417                         return nextIteration();
9418                 }
9419         }
9420
9421         return nextIteration();
9422 }
9423
9424 tcu::TestStatus MemoryTestInstance::iterate (void)
9425 {
9426         if ((this->*m_stage)())
9427                 return tcu::TestStatus::incomplete();
9428         else
9429                 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
9430 }
9431
9432 struct AddPrograms
9433 {
9434         void init (vk::SourceCollections& sources, TestConfig config) const
9435         {
9436                 // Vertex buffer rendering
9437                 if (config.usage & USAGE_VERTEX_BUFFER)
9438                 {
9439                         const char* const vertexShader =
9440                                 "#version 310 es\n"
9441                                 "layout(location = 0) in highp vec2 a_position;\n"
9442                                 "void main (void) {\n"
9443                                 "\tgl_PointSize = 1.0;\n"
9444                                 "\tgl_Position = vec4(1.998 * a_position - vec2(0.999), 0.0, 1.0);\n"
9445                                 "}\n";
9446
9447                         sources.glslSources.add("vertex-buffer.vert")
9448                                 << glu::VertexSource(vertexShader);
9449                 }
9450
9451                 // Index buffer rendering
9452                 if (config.usage & USAGE_INDEX_BUFFER)
9453                 {
9454                         const char* const vertexShader =
9455                                 "#version 310 es\n"
9456                                 "precision highp float;\n"
9457                                 "void main (void) {\n"
9458                                 "\tgl_PointSize = 1.0;\n"
9459                                 "\thighp vec2 pos = vec2(gl_VertexIndex % 256, gl_VertexIndex / 256) / vec2(255.0);\n"
9460                                 "\tgl_Position = vec4(1.998 * pos - vec2(0.999), 0.0, 1.0);\n"
9461                                 "}\n";
9462
9463                         sources.glslSources.add("index-buffer.vert")
9464                                 << glu::VertexSource(vertexShader);
9465                 }
9466
9467                 if (config.usage & USAGE_UNIFORM_BUFFER)
9468                 {
9469                         {
9470                                 std::ostringstream vertexShader;
9471
9472                                 vertexShader <<
9473                                         "#version 310 es\n"
9474                                         "precision highp float;\n"
9475                                         "layout(set=0, binding=0) uniform Block\n"
9476                                         "{\n"
9477                                         "\thighp uvec4 values[" << de::toString<size_t>(MAX_UNIFORM_BUFFER_SIZE / (sizeof(deUint32) * 4)) << "];\n"
9478                                         "} block;\n"
9479                                         "void main (void) {\n"
9480                                         "\tgl_PointSize = 1.0;\n"
9481                                         "\thighp uvec4 vecVal = block.values[gl_VertexIndex / 8];\n"
9482                                         "\thighp uint val;\n"
9483                                         "\tif (((gl_VertexIndex / 2) % 4 == 0))\n"
9484                                         "\t\tval = vecVal.x;\n"
9485                                         "\telse if (((gl_VertexIndex / 2) % 4 == 1))\n"
9486                                         "\t\tval = vecVal.y;\n"
9487                                         "\telse if (((gl_VertexIndex / 2) % 4 == 2))\n"
9488                                         "\t\tval = vecVal.z;\n"
9489                                         "\telse if (((gl_VertexIndex / 2) % 4 == 3))\n"
9490                                         "\t\tval = vecVal.w;\n"
9491                                         "\tif ((gl_VertexIndex % 2) == 0)\n"
9492                                         "\t\tval = val & 0xFFFFu;\n"
9493                                         "\telse\n"
9494                                         "\t\tval = val >> 16u;\n"
9495                                         "\thighp vec2 pos = vec2(val & 0xFFu, val >> 8u) / vec2(255.0);\n"
9496                                         "\tgl_Position = vec4(1.998 * pos - vec2(0.999), 0.0, 1.0);\n"
9497                                         "}\n";
9498
9499                                 sources.glslSources.add("uniform-buffer.vert")
9500                                         << glu::VertexSource(vertexShader.str());
9501                         }
9502
9503                         {
9504                                 const size_t            arraySize               = MAX_UNIFORM_BUFFER_SIZE / (sizeof(deUint32) * 4);
9505                                 const size_t            arrayIntSize    = arraySize * 4;
9506                                 std::ostringstream      fragmentShader;
9507
9508                                 fragmentShader <<
9509                                         "#version 310 es\n"
9510                                         "precision highp float;\n"
9511                                         "layout(location = 0) out highp vec4 o_color;\n"
9512                                         "layout(set=0, binding=0) uniform Block\n"
9513                                         "{\n"
9514                                         "\thighp uvec4 values[" << arraySize << "];\n"
9515                                         "} block;\n"
9516                                         "layout(push_constant) uniform PushC\n"
9517                                         "{\n"
9518                                         "\tuint callId;\n"
9519                                         "\tuint valuesPerPixel;\n"
9520                                         "} pushC;\n"
9521                                         "void main (void) {\n"
9522                                         "\thighp uint id = pushC.callId * (" << arrayIntSize << "u / pushC.valuesPerPixel) + uint(gl_FragCoord.y) * 256u + uint(gl_FragCoord.x);\n"
9523                                         "\tif (uint(gl_FragCoord.y) * 256u + uint(gl_FragCoord.x) < pushC.callId * (" << arrayIntSize  << "u / pushC.valuesPerPixel))\n"
9524                                         "\t\tdiscard;\n"
9525                                         "\thighp uint value = id;\n"
9526                                         "\tfor (uint i = 0u; i < pushC.valuesPerPixel; i++)\n"
9527                                         "\t{\n"
9528                                         "\t\thighp uvec4 vecVal = block.values[(value / 4u) % " << arraySize << "u];\n"
9529                                         "\t\tif ((value % 4u) == 0u)\n"
9530                                         "\t\t\tvalue = vecVal.x;\n"
9531                                         "\t\telse if ((value % 4u) == 1u)\n"
9532                                         "\t\t\tvalue = vecVal.y;\n"
9533                                         "\t\telse if ((value % 4u) == 2u)\n"
9534                                         "\t\t\tvalue = vecVal.z;\n"
9535                                         "\t\telse if ((value % 4u) == 3u)\n"
9536                                         "\t\t\tvalue = vecVal.w;\n"
9537                                         "\t}\n"
9538                                         "\tuvec4 valueOut = uvec4(value & 0xFFu, (value >> 8u) & 0xFFu, (value >> 16u) & 0xFFu, (value >> 24u) & 0xFFu);\n"
9539                                         "\to_color = vec4(valueOut) / vec4(255.0);\n"
9540                                         "}\n";
9541
9542                                 sources.glslSources.add("uniform-buffer.frag")
9543                                         << glu::FragmentSource(fragmentShader.str());
9544                         }
9545                 }
9546
9547                 if (config.usage & USAGE_STORAGE_BUFFER)
9548                 {
9549                         {
9550                                 // Vertex storage buffer rendering
9551                                 const char* const vertexShader =
9552                                         "#version 310 es\n"
9553                                         "precision highp float;\n"
9554                                         "layout(set=0, binding=0) buffer Block\n"
9555                                         "{\n"
9556                                         "\thighp uvec4 values[];\n"
9557                                         "} block;\n"
9558                                         "void main (void) {\n"
9559                                         "\tgl_PointSize = 1.0;\n"
9560                                         "\thighp uvec4 vecVal = block.values[gl_VertexIndex / 8];\n"
9561                                         "\thighp uint val;\n"
9562                                         "\tif (((gl_VertexIndex / 2) % 4 == 0))\n"
9563                                         "\t\tval = vecVal.x;\n"
9564                                         "\telse if (((gl_VertexIndex / 2) % 4 == 1))\n"
9565                                         "\t\tval = vecVal.y;\n"
9566                                         "\telse if (((gl_VertexIndex / 2) % 4 == 2))\n"
9567                                         "\t\tval = vecVal.z;\n"
9568                                         "\telse if (((gl_VertexIndex / 2) % 4 == 3))\n"
9569                                         "\t\tval = vecVal.w;\n"
9570                                         "\tif ((gl_VertexIndex % 2) == 0)\n"
9571                                         "\t\tval = val & 0xFFFFu;\n"
9572                                         "\telse\n"
9573                                         "\t\tval = val >> 16u;\n"
9574                                         "\thighp vec2 pos = vec2(val & 0xFFu, val >> 8u) / vec2(255.0);\n"
9575                                         "\tgl_Position = vec4(1.998 * pos - vec2(0.999), 0.0, 1.0);\n"
9576                                         "}\n";
9577
9578                                 sources.glslSources.add("storage-buffer.vert")
9579                                         << glu::VertexSource(vertexShader);
9580                         }
9581
9582                         {
9583                                 std::ostringstream      fragmentShader;
9584
9585                                 fragmentShader <<
9586                                         "#version 310 es\n"
9587                                         "precision highp float;\n"
9588                                         "precision highp int;\n"
9589                                         "layout(location = 0) out highp vec4 o_color;\n"
9590                                         "layout(set=0, binding=0) buffer Block\n"
9591                                         "{\n"
9592                                         "\thighp uvec4 values[];\n"
9593                                         "} block;\n"
9594                                         "layout(push_constant) uniform PushC\n"
9595                                         "{\n"
9596                                         "\tuint valuesPerPixel;\n"
9597                                         "\tuint bufferSize;\n"
9598                                         "} pushC;\n"
9599                                         "void main (void) {\n"
9600                                         "\thighp uint arrayIntSize = pushC.bufferSize / 4u;\n"
9601                                         "\thighp uint id = uint(gl_FragCoord.y) * 256u + uint(gl_FragCoord.x);\n"
9602                                         "\thighp uint value = id;\n"
9603                                         "\tfor (uint i = 0u; i < pushC.valuesPerPixel; i++)\n"
9604                                         "\t{\n"
9605                                         "\t\thighp uvec4 vecVal = block.values[(value / 4u) % (arrayIntSize / 4u)];\n"
9606                                         "\t\tif ((value % 4u) == 0u)\n"
9607                                         "\t\t\tvalue = vecVal.x;\n"
9608                                         "\t\telse if ((value % 4u) == 1u)\n"
9609                                         "\t\t\tvalue = vecVal.y;\n"
9610                                         "\t\telse if ((value % 4u) == 2u)\n"
9611                                         "\t\t\tvalue = vecVal.z;\n"
9612                                         "\t\telse if ((value % 4u) == 3u)\n"
9613                                         "\t\t\tvalue = vecVal.w;\n"
9614                                         "\t}\n"
9615                                         "\tuvec4 valueOut = uvec4(value & 0xFFu, (value >> 8u) & 0xFFu, (value >> 16u) & 0xFFu, (value >> 24u) & 0xFFu);\n"
9616                                         "\to_color = vec4(valueOut) / vec4(255.0);\n"
9617                                         "}\n";
9618
9619                                 sources.glslSources.add("storage-buffer.frag")
9620                                         << glu::FragmentSource(fragmentShader.str());
9621                         }
9622                 }
9623
9624                 if (config.usage & USAGE_UNIFORM_TEXEL_BUFFER)
9625                 {
9626                         {
9627                                 // Vertex uniform texel buffer rendering
9628                                 const char* const vertexShader =
9629                                         "#version 310 es\n"
9630                                         "#extension GL_EXT_texture_buffer : require\n"
9631                                         "precision highp float;\n"
9632                                         "layout(set=0, binding=0) uniform highp usamplerBuffer u_sampler;\n"
9633                                         "void main (void) {\n"
9634                                         "\tgl_PointSize = 1.0;\n"
9635                                         "\thighp uint val = texelFetch(u_sampler, gl_VertexIndex).x;\n"
9636                                         "\thighp vec2 pos = vec2(val & 0xFFu, val >> 8u) / vec2(255.0);\n"
9637                                         "\tgl_Position = vec4(1.998 * pos - vec2(0.999), 0.0, 1.0);\n"
9638                                         "}\n";
9639
9640                                 sources.glslSources.add("uniform-texel-buffer.vert")
9641                                         << glu::VertexSource(vertexShader);
9642                         }
9643
9644                         {
9645                                 // Fragment uniform texel buffer rendering
9646                                 const char* const fragmentShader =
9647                                         "#version 310 es\n"
9648                                         "#extension GL_EXT_texture_buffer : require\n"
9649                                         "precision highp float;\n"
9650                                         "layout(set=0, binding=0) uniform highp usamplerBuffer u_sampler;\n"
9651                                         "layout(location = 0) out highp vec4 o_color;\n"
9652                                         "layout(push_constant) uniform PushC\n"
9653                                         "{\n"
9654                                         "\tuint callId;\n"
9655                                         "\tuint valuesPerPixel;\n"
9656                                         "\tuint maxTexelCount;\n"
9657                                         "} pushC;\n"
9658                                         "void main (void) {\n"
9659                                         "\thighp uint id = uint(gl_FragCoord.y) * 256u + uint(gl_FragCoord.x);\n"
9660                                         "\thighp uint value = id;\n"
9661                                         "\tif (uint(gl_FragCoord.y) * 256u + uint(gl_FragCoord.x) < pushC.callId * (pushC.maxTexelCount / pushC.valuesPerPixel))\n"
9662                                         "\t\tdiscard;\n"
9663                                         "\tfor (uint i = 0u; i < pushC.valuesPerPixel; i++)\n"
9664                                         "\t{\n"
9665                                         "\t\tvalue = texelFetch(u_sampler, int(value % uint(textureSize(u_sampler)))).x;\n"
9666                                         "\t}\n"
9667                                         "\tuvec4 valueOut = uvec4(value & 0xFFu, (value >> 8u) & 0xFFu, (value >> 16u) & 0xFFu, (value >> 24u) & 0xFFu);\n"
9668                                         "\to_color = vec4(valueOut) / vec4(255.0);\n"
9669                                         "}\n";
9670
9671                                 sources.glslSources.add("uniform-texel-buffer.frag")
9672                                         << glu::FragmentSource(fragmentShader);
9673                         }
9674                 }
9675
9676                 if (config.usage & USAGE_STORAGE_TEXEL_BUFFER)
9677                 {
9678                         {
9679                                 // Vertex storage texel buffer rendering
9680                                 const char* const vertexShader =
9681                                         "#version 450\n"
9682                                         "#extension GL_EXT_texture_buffer : require\n"
9683                                         "precision highp float;\n"
9684                                         "layout(set=0, binding=0, r32ui) uniform readonly highp uimageBuffer u_sampler;\n"
9685                                         "out gl_PerVertex {\n"
9686                                         "\tvec4 gl_Position;\n"
9687                                         "\tfloat gl_PointSize;\n"
9688                                         "};\n"
9689                                         "void main (void) {\n"
9690                                         "\tgl_PointSize = 1.0;\n"
9691                                         "\thighp uint val = imageLoad(u_sampler, gl_VertexIndex / 2).x;\n"
9692                                         "\tif (gl_VertexIndex % 2 == 0)\n"
9693                                         "\t\tval = val & 0xFFFFu;\n"
9694                                         "\telse\n"
9695                                         "\t\tval = val >> 16;\n"
9696                                         "\thighp vec2 pos = vec2(val & 0xFFu, val >> 8u) / vec2(255.0);\n"
9697                                         "\tgl_Position = vec4(1.998 * pos - vec2(0.999), 0.0, 1.0);\n"
9698                                         "}\n";
9699
9700                                 sources.glslSources.add("storage-texel-buffer.vert")
9701                                         << glu::VertexSource(vertexShader);
9702                         }
9703                         {
9704                                 // Fragment storage texel buffer rendering
9705                                 const char* const fragmentShader =
9706                                         "#version 310 es\n"
9707                                         "#extension GL_EXT_texture_buffer : require\n"
9708                                         "precision highp float;\n"
9709                                         "layout(set=0, binding=0, r32ui) uniform readonly highp uimageBuffer u_sampler;\n"
9710                                         "layout(location = 0) out highp vec4 o_color;\n"
9711                                         "layout(push_constant) uniform PushC\n"
9712                                         "{\n"
9713                                         "\tuint callId;\n"
9714                                         "\tuint valuesPerPixel;\n"
9715                                         "\tuint maxTexelCount;\n"
9716                                         "\tuint width;\n"
9717                                         "} pushC;\n"
9718                                         "void main (void) {\n"
9719                                         "\thighp uint id = uint(gl_FragCoord.y) * 256u + uint(gl_FragCoord.x);\n"
9720                                         "\thighp uint value = id;\n"
9721                                         "\tif (uint(gl_FragCoord.y) * 256u + uint(gl_FragCoord.x) < pushC.callId * (pushC.maxTexelCount / pushC.valuesPerPixel))\n"
9722                                         "\t\tdiscard;\n"
9723                                         "\tfor (uint i = 0u; i < pushC.valuesPerPixel; i++)\n"
9724                                         "\t{\n"
9725                                         "\t\tvalue = imageLoad(u_sampler, int(value % pushC.width)).x;\n"
9726                                         "\t}\n"
9727                                         "\tuvec4 valueOut = uvec4(value & 0xFFu, (value >> 8u) & 0xFFu, (value >> 16u) & 0xFFu, (value >> 24u) & 0xFFu);\n"
9728                                         "\to_color = vec4(valueOut) / vec4(255.0);\n"
9729                                         "}\n";
9730
9731                                 sources.glslSources.add("storage-texel-buffer.frag")
9732                                         << glu::FragmentSource(fragmentShader);
9733                         }
9734                 }
9735
9736                 if (config.usage & USAGE_STORAGE_IMAGE)
9737                 {
9738                         {
9739                                 // Vertex storage image
9740                                 const char* const vertexShader =
9741                                         "#version 450\n"
9742                                         "precision highp float;\n"
9743                                         "layout(set=0, binding=0, rgba8) uniform image2D u_image;\n"
9744                                         "out gl_PerVertex {\n"
9745                                         "\tvec4 gl_Position;\n"
9746                                         "\tfloat gl_PointSize;\n"
9747                                         "};\n"
9748                                         "void main (void) {\n"
9749                                         "\tgl_PointSize = 1.0;\n"
9750                                         "\thighp vec4 val = imageLoad(u_image, ivec2((gl_VertexIndex / 2) / imageSize(u_image).x, (gl_VertexIndex / 2) % imageSize(u_image).x));\n"
9751                                         "\thighp vec2 pos;\n"
9752                                         "\tif (gl_VertexIndex % 2 == 0)\n"
9753                                         "\t\tpos = val.xy;\n"
9754                                         "\telse\n"
9755                                         "\t\tpos = val.zw;\n"
9756                                         "\tgl_Position = vec4(1.998 * pos - vec2(0.999), 0.0, 1.0);\n"
9757                                         "}\n";
9758
9759                                 sources.glslSources.add("storage-image.vert")
9760                                         << glu::VertexSource(vertexShader);
9761                         }
9762                         {
9763                                 // Fragment storage image
9764                                 const char* const fragmentShader =
9765                                         "#version 450\n"
9766                                         "#extension GL_EXT_texture_buffer : require\n"
9767                                         "precision highp float;\n"
9768                                         "layout(set=0, binding=0, rgba8) uniform image2D u_image;\n"
9769                                         "layout(location = 0) out highp vec4 o_color;\n"
9770                                         "void main (void) {\n"
9771                                         "\thighp uvec2 size = uvec2(imageSize(u_image).x, imageSize(u_image).y);\n"
9772                                         "\thighp uint valuesPerPixel = max(1u, (size.x * size.y) / (256u * 256u));\n"
9773                                         "\thighp uvec4 value = uvec4(uint(gl_FragCoord.x), uint(gl_FragCoord.y), 0u, 0u);\n"
9774                                         "\tfor (uint i = 0u; i < valuesPerPixel; i++)\n"
9775                                         "\t{\n"
9776                                         "\t\thighp vec4 floatValue = imageLoad(u_image, ivec2(int((value.z *  256u + (value.x ^ value.z)) % size.x), int((value.w * 256u + (value.y ^ value.w)) % size.y)));\n"
9777                                         "\t\tvalue = uvec4(uint(floatValue.x * 255.0), uint(floatValue.y * 255.0), uint(floatValue.z * 255.0), uint(floatValue.w * 255.0));\n"
9778                                         "\t}\n"
9779                                         "\to_color = vec4(value) / vec4(255.0);\n"
9780                                         "}\n";
9781
9782                                 sources.glslSources.add("storage-image.frag")
9783                                         << glu::FragmentSource(fragmentShader);
9784                         }
9785                 }
9786
9787                 if (config.usage & USAGE_SAMPLED_IMAGE)
9788                 {
9789                         {
9790                                 // Vertex storage image
9791                                 const char* const vertexShader =
9792                                         "#version 450\n"
9793                                         "precision highp float;\n"
9794                                         "layout(set=0, binding=0) uniform sampler2D u_sampler;\n"
9795                                         "out gl_PerVertex {\n"
9796                                         "\tvec4 gl_Position;\n"
9797                                         "\tfloat gl_PointSize;\n"
9798                                         "};\n"
9799                                         "void main (void) {\n"
9800                                         "\tgl_PointSize = 1.0;\n"
9801                                         "\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"
9802                                         "\thighp vec2 pos;\n"
9803                                         "\tif (gl_VertexIndex % 2 == 0)\n"
9804                                         "\t\tpos = val.xy;\n"
9805                                         "\telse\n"
9806                                         "\t\tpos = val.zw;\n"
9807                                         "\tgl_Position = vec4(1.998 * pos - vec2(0.999), 0.0, 1.0);\n"
9808                                         "}\n";
9809
9810                                 sources.glslSources.add("sampled-image.vert")
9811                                         << glu::VertexSource(vertexShader);
9812                         }
9813                         {
9814                                 // Fragment storage image
9815                                 const char* const fragmentShader =
9816                                         "#version 450\n"
9817                                         "#extension GL_EXT_texture_buffer : require\n"
9818                                         "precision highp float;\n"
9819                                         "layout(set=0, binding=0) uniform sampler2D u_sampler;\n"
9820                                         "layout(location = 0) out highp vec4 o_color;\n"
9821                                         "void main (void) {\n"
9822                                         "\thighp uvec2 size = uvec2(textureSize(u_sampler, 0).x, textureSize(u_sampler, 0).y);\n"
9823                                         "\thighp uint valuesPerPixel = max(1u, (size.x * size.y) / (256u * 256u));\n"
9824                                         "\thighp uvec4 value = uvec4(uint(gl_FragCoord.x), uint(gl_FragCoord.y), 0u, 0u);\n"
9825                                         "\tfor (uint i = 0u; i < valuesPerPixel; i++)\n"
9826                                         "\t{\n"
9827                                         "\t\thighp vec4 floatValue = texelFetch(u_sampler, ivec2(int((value.z *  256u + (value.x ^ value.z)) % size.x), int((value.w * 256u + (value.y ^ value.w)) % size.y)), 0);\n"
9828                                         "\t\tvalue = uvec4(uint(floatValue.x * 255.0), uint(floatValue.y * 255.0), uint(floatValue.z * 255.0), uint(floatValue.w * 255.0));\n"
9829                                         "\t}\n"
9830                                         "\to_color = vec4(value) / vec4(255.0);\n"
9831                                         "}\n";
9832
9833                                 sources.glslSources.add("sampled-image.frag")
9834                                         << glu::FragmentSource(fragmentShader);
9835                         }
9836                 }
9837
9838                 {
9839                         const char* const vertexShader =
9840                                 "#version 450\n"
9841                                 "out gl_PerVertex {\n"
9842                                 "\tvec4 gl_Position;\n"
9843                                 "};\n"
9844                                 "precision highp float;\n"
9845                                 "void main (void) {\n"
9846                                 "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
9847                                 "\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
9848                                 "}\n";
9849
9850                         sources.glslSources.add("render-quad.vert")
9851                                 << glu::VertexSource(vertexShader);
9852                 }
9853
9854                 {
9855                         const char* const fragmentShader =
9856                                 "#version 310 es\n"
9857                                 "layout(location = 0) out highp vec4 o_color;\n"
9858                                 "void main (void) {\n"
9859                                 "\to_color = vec4(1.0);\n"
9860                                 "}\n";
9861
9862                         sources.glslSources.add("render-white.frag")
9863                                 << glu::FragmentSource(fragmentShader);
9864                 }
9865         }
9866 };
9867
9868 } // anonymous
9869
9870 tcu::TestCaseGroup* createPipelineBarrierTests (tcu::TestContext& testCtx)
9871 {
9872         de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "pipeline_barrier", "Pipeline barrier tests."));
9873         const vk::VkDeviceSize                  sizes[]                 =
9874         {
9875                 1024,           // 1K
9876                 8*1024,         // 8K
9877                 64*1024,        // 64K
9878                 1024*1024,      // 1M
9879         };
9880         const Usage                                             usages[]                =
9881         {
9882                 USAGE_HOST_READ,
9883                 USAGE_HOST_WRITE,
9884                 USAGE_TRANSFER_SRC,
9885                 USAGE_TRANSFER_DST,
9886                 USAGE_VERTEX_BUFFER,
9887                 USAGE_INDEX_BUFFER,
9888                 USAGE_UNIFORM_BUFFER,
9889                 USAGE_UNIFORM_TEXEL_BUFFER,
9890                 USAGE_STORAGE_BUFFER,
9891                 USAGE_STORAGE_TEXEL_BUFFER,
9892                 USAGE_STORAGE_IMAGE,
9893                 USAGE_SAMPLED_IMAGE
9894         };
9895         const Usage                                             readUsages[]            =
9896         {
9897                 USAGE_HOST_READ,
9898                 USAGE_TRANSFER_SRC,
9899                 USAGE_VERTEX_BUFFER,
9900                 USAGE_INDEX_BUFFER,
9901                 USAGE_UNIFORM_BUFFER,
9902                 USAGE_UNIFORM_TEXEL_BUFFER,
9903                 USAGE_STORAGE_BUFFER,
9904                 USAGE_STORAGE_TEXEL_BUFFER,
9905                 USAGE_STORAGE_IMAGE,
9906                 USAGE_SAMPLED_IMAGE
9907         };
9908
9909         const Usage                                             writeUsages[]   =
9910         {
9911                 USAGE_HOST_WRITE,
9912                 USAGE_TRANSFER_DST
9913         };
9914
9915         for (size_t writeUsageNdx = 0; writeUsageNdx < DE_LENGTH_OF_ARRAY(writeUsages); writeUsageNdx++)
9916         {
9917                 const Usage     writeUsage      = writeUsages[writeUsageNdx];
9918
9919                 for (size_t readUsageNdx = 0; readUsageNdx < DE_LENGTH_OF_ARRAY(readUsages); readUsageNdx++)
9920                 {
9921                         const Usage                                             readUsage               = readUsages[readUsageNdx];
9922                         const Usage                                             usage                   = writeUsage | readUsage;
9923                         const string                                    usageGroupName  (usageToName(usage));
9924                         de::MovePtr<tcu::TestCaseGroup> usageGroup              (new tcu::TestCaseGroup(testCtx, usageGroupName.c_str(), usageGroupName.c_str()));
9925
9926                         for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); sizeNdx++)
9927                         {
9928                                 const vk::VkDeviceSize  size            = sizes[sizeNdx];
9929                                 const string                    testName        (de::toString((deUint64)(size)));
9930                                 const TestConfig                config          =
9931                                 {
9932                                         usage,
9933                                         size,
9934                                         vk::VK_SHARING_MODE_EXCLUSIVE
9935                                 };
9936
9937                                 usageGroup->addChild(new InstanceFactory1<MemoryTestInstance, TestConfig, AddPrograms>(testCtx,tcu::NODETYPE_SELF_VALIDATE,  testName, testName, AddPrograms(), config));
9938                         }
9939
9940                         group->addChild(usageGroup.get());
9941                         usageGroup.release();
9942                 }
9943         }
9944
9945         {
9946                 Usage all = (Usage)0;
9947
9948                 for (size_t usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usages); usageNdx++)
9949                         all = all | usages[usageNdx];
9950
9951                 {
9952                         const string                                    usageGroupName  ("all");
9953                         de::MovePtr<tcu::TestCaseGroup> usageGroup              (new tcu::TestCaseGroup(testCtx, usageGroupName.c_str(), usageGroupName.c_str()));
9954
9955                         for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); sizeNdx++)
9956                         {
9957                                 const vk::VkDeviceSize  size            = sizes[sizeNdx];
9958                                 const string                    testName        (de::toString((deUint64)(size)));
9959                                 const TestConfig                config          =
9960                                 {
9961                                         all,
9962                                         size,
9963                                         vk::VK_SHARING_MODE_EXCLUSIVE
9964                                 };
9965
9966                                 usageGroup->addChild(new InstanceFactory1<MemoryTestInstance, TestConfig, AddPrograms>(testCtx,tcu::NODETYPE_SELF_VALIDATE,  testName, testName, AddPrograms(), config));
9967                         }
9968
9969                         group->addChild(usageGroup.get());
9970                         usageGroup.release();
9971                 }
9972
9973                 {
9974                         const string                                    usageGroupName  ("all_device");
9975                         de::MovePtr<tcu::TestCaseGroup> usageGroup              (new tcu::TestCaseGroup(testCtx, usageGroupName.c_str(), usageGroupName.c_str()));
9976
9977                         for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); sizeNdx++)
9978                         {
9979                                 const vk::VkDeviceSize  size            = sizes[sizeNdx];
9980                                 const string                    testName        (de::toString((deUint64)(size)));
9981                                 const TestConfig                config          =
9982                                 {
9983                                         (Usage)(all & (~(USAGE_HOST_READ|USAGE_HOST_WRITE))),
9984                                         size,
9985                                         vk::VK_SHARING_MODE_EXCLUSIVE
9986                                 };
9987
9988                                 usageGroup->addChild(new InstanceFactory1<MemoryTestInstance, TestConfig, AddPrograms>(testCtx,tcu::NODETYPE_SELF_VALIDATE,  testName, testName, AddPrograms(), config));
9989                         }
9990
9991                         group->addChild(usageGroup.get());
9992                         usageGroup.release();
9993                 }
9994         }
9995
9996         return group.release();
9997 }
9998
9999 } // memory
10000 } // vkt