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