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