Fix warning introduced in 2c9e3ec9 am: d8b452a753 am: 03dde47b9d am: 9333757172
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / pipeline / vktPipelineVertexInputTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Imagination Technologies Ltd.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Vertex Input Tests
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktPipelineVertexInputTests.hpp"
26 #include "vktTestGroupUtil.hpp"
27 #include "vktPipelineClearUtil.hpp"
28 #include "vktPipelineImageUtil.hpp"
29 #include "vktPipelineVertexUtil.hpp"
30 #include "vktPipelineReferenceRenderer.hpp"
31 #include "vktTestCase.hpp"
32 #include "vktTestCaseUtil.hpp"
33 #include "vkImageUtil.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkQueryUtil.hpp"
37 #include "vkRef.hpp"
38 #include "vkRefUtil.hpp"
39 #include "tcuFloat.hpp"
40 #include "tcuImageCompare.hpp"
41 #include "deFloat16.h"
42 #include "deMemory.h"
43 #include "deRandom.hpp"
44 #include "deStringUtil.hpp"
45 #include "deUniquePtr.hpp"
46
47 #include <sstream>
48 #include <vector>
49
50 namespace vkt
51 {
52 namespace pipeline
53 {
54
55 using namespace vk;
56
57 namespace
58 {
59
60 bool isSupportedVertexFormat (Context& context, VkFormat format)
61 {
62         if (isVertexFormatDouble(format) && !context.getDeviceFeatures().shaderFloat64)
63                 return false;
64
65         VkFormatProperties  formatProps;
66         deMemset(&formatProps, 0, sizeof(VkFormatProperties));
67         context.getInstanceInterface().getPhysicalDeviceFormatProperties(context.getPhysicalDevice(), format, &formatProps);
68
69         return (formatProps.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) != 0u;
70 }
71
72 float getRepresentableDifferenceUnorm (VkFormat format)
73 {
74         DE_ASSERT(isVertexFormatUnorm(format) || isVertexFormatSRGB(format));
75
76         return 1.0f / float((1 << (getVertexFormatComponentSize(format) * 8)) - 1);
77 }
78
79 float getRepresentableDifferenceSnorm (VkFormat format)
80 {
81         DE_ASSERT(isVertexFormatSnorm(format));
82
83         return 1.0f / float((1 << (getVertexFormatComponentSize(format) * 8 - 1)) - 1);
84 }
85
86 deUint32 getNextMultipleOffset (deUint32 divisor, deUint32 value)
87 {
88         if (value % divisor == 0)
89                 return 0;
90         else
91                 return divisor - (value % divisor);
92 }
93
94 class VertexInputTest : public vkt::TestCase
95 {
96 public:
97         enum GlslType
98         {
99                 GLSL_TYPE_INT,
100                 GLSL_TYPE_IVEC2,
101                 GLSL_TYPE_IVEC3,
102                 GLSL_TYPE_IVEC4,
103
104                 GLSL_TYPE_UINT,
105                 GLSL_TYPE_UVEC2,
106                 GLSL_TYPE_UVEC3,
107                 GLSL_TYPE_UVEC4,
108
109                 GLSL_TYPE_FLOAT,
110                 GLSL_TYPE_VEC2,
111                 GLSL_TYPE_VEC3,
112                 GLSL_TYPE_VEC4,
113                 GLSL_TYPE_MAT2,
114                 GLSL_TYPE_MAT3,
115                 GLSL_TYPE_MAT4,
116
117                 GLSL_TYPE_DOUBLE,
118                 GLSL_TYPE_DVEC2,
119                 GLSL_TYPE_DVEC3,
120                 GLSL_TYPE_DVEC4,
121                 GLSL_TYPE_DMAT2,
122                 GLSL_TYPE_DMAT3,
123                 GLSL_TYPE_DMAT4,
124
125                 GLSL_TYPE_COUNT
126         };
127
128         enum GlslBasicType
129         {
130                 GLSL_BASIC_TYPE_INT,
131                 GLSL_BASIC_TYPE_UINT,
132                 GLSL_BASIC_TYPE_FLOAT,
133                 GLSL_BASIC_TYPE_DOUBLE
134         };
135
136         enum BindingMapping
137         {
138                 BINDING_MAPPING_ONE_TO_ONE,             //!< Vertex input bindings will not contain data for more than one attribute.
139                 BINDING_MAPPING_ONE_TO_MANY             //!< Vertex input bindings can contain data for more than one attribute.
140         };
141
142         enum AttributeLayout
143         {
144                 ATTRIBUTE_LAYOUT_INTERLEAVED,   //!< Attribute data is bundled together as if in a structure: [pos 0][color 0][pos 1][color 1]...
145                 ATTRIBUTE_LAYOUT_SEQUENTIAL             //!< Data for each attribute is laid out separately: [pos 0][pos 1]...[color 0][color 1]...
146                                                                                 //   Sequential only makes a difference if ONE_TO_MANY mapping is used (more than one attribute in a binding).
147         };
148
149         struct AttributeInfo
150         {
151                 GlslType                                glslType;
152                 VkFormat                                vkType;
153                 VkVertexInputRate               inputRate;
154         };
155
156         struct GlslTypeDescription
157         {
158                 const char*             name;
159                 int                             vertexInputComponentCount;
160                 int                             vertexInputCount;
161                 GlslBasicType   basicType;
162         };
163
164         static const GlslTypeDescription                s_glslTypeDescriptions[GLSL_TYPE_COUNT];
165
166                                                                                         VertexInputTest                         (tcu::TestContext&                                      testContext,
167                                                                                                                                                  const std::string&                                     name,
168                                                                                                                                                  const std::string&                                     description,
169                                                                                                                                                  const std::vector<AttributeInfo>&      attributeInfos,
170                                                                                                                                                  BindingMapping                                         bindingMapping,
171                                                                                                                                                  AttributeLayout                                        attributeLayout);
172
173         virtual                                                                 ~VertexInputTest                        (void) {}
174         virtual void                                                    initPrograms                            (SourceCollections& programCollection) const;
175         virtual TestInstance*                                   createInstance                          (Context& context) const;
176         static bool                                                             isCompatibleType                        (VkFormat format, GlslType glslType);
177
178 private:
179         AttributeInfo                                                   getAttributeInfo                        (size_t attributeNdx) const;
180         size_t                                                                  getNumAttributes                        (void) const;
181         std::string                                                             getGlslInputDeclarations        (void) const;
182         std::string                                                             getGlslVertexCheck                      (void) const;
183         std::string                                                             getGlslAttributeConditions      (const AttributeInfo& attributeInfo, const std::string attributeIndex) const;
184         static tcu::Vec4                                                getFormatThreshold                      (VkFormat format);
185
186         const std::vector<AttributeInfo>                m_attributeInfos;
187         const BindingMapping                                    m_bindingMapping;
188         const AttributeLayout                                   m_attributeLayout;
189         const bool                                                              m_queryMaxAttributes;
190         bool                                                                    m_usesDoubleType;
191         mutable size_t                                                  m_maxAttributes;
192 };
193
194 class VertexInputInstance : public vkt::TestInstance
195 {
196 public:
197         struct VertexInputAttributeDescription
198         {
199                 VertexInputTest::GlslType                       glslType;
200                 int                                                                     vertexInputIndex;
201                 VkVertexInputAttributeDescription       vkDescription;
202         };
203
204         typedef std::vector<VertexInputAttributeDescription>    AttributeDescriptionList;
205
206                                                                                         VertexInputInstance                     (Context&                                                                                               context,
207                                                                                                                                                  const AttributeDescriptionList&                                                attributeDescriptions,
208                                                                                                                                                  const std::vector<VkVertexInputBindingDescription>&    bindingDescriptions,
209                                                                                                                                                  const std::vector<VkDeviceSize>&                                               bindingOffsets);
210
211         virtual                                                                 ~VertexInputInstance            (void);
212         virtual tcu::TestStatus                                 iterate                                         (void);
213
214
215         static void                                                             writeVertexInputData            (deUint8* destPtr, const VkVertexInputBindingDescription& bindingDescription, const VkDeviceSize bindingOffset, const AttributeDescriptionList& attributes);
216         static void                                                             writeVertexInputValue           (deUint8* destPtr, const VertexInputAttributeDescription& attributes, int indexId);
217
218 private:
219         tcu::TestStatus                                                 verifyImage                                     (void);
220
221 private:
222         std::vector<VkBuffer>                                   m_vertexBuffers;
223         std::vector<Allocation*>                                m_vertexBufferAllocs;
224
225         const tcu::UVec2                                                m_renderSize;
226         const VkFormat                                                  m_colorFormat;
227
228         Move<VkImage>                                                   m_colorImage;
229         de::MovePtr<Allocation>                                 m_colorImageAlloc;
230         Move<VkImage>                                                   m_depthImage;
231         Move<VkImageView>                                               m_colorAttachmentView;
232         Move<VkRenderPass>                                              m_renderPass;
233         Move<VkFramebuffer>                                             m_framebuffer;
234
235         Move<VkShaderModule>                                    m_vertexShaderModule;
236         Move<VkShaderModule>                                    m_fragmentShaderModule;
237
238         Move<VkPipelineLayout>                                  m_pipelineLayout;
239         Move<VkPipeline>                                                m_graphicsPipeline;
240
241         Move<VkCommandPool>                                             m_cmdPool;
242         Move<VkCommandBuffer>                                   m_cmdBuffer;
243
244         Move<VkFence>                                                   m_fence;
245 };
246
247 const VertexInputTest::GlslTypeDescription VertexInputTest::s_glslTypeDescriptions[GLSL_TYPE_COUNT] =
248 {
249         { "int",        1, 1, GLSL_BASIC_TYPE_INT },
250         { "ivec2",      2, 1, GLSL_BASIC_TYPE_INT },
251         { "ivec3",      3, 1, GLSL_BASIC_TYPE_INT },
252         { "ivec4",      4, 1, GLSL_BASIC_TYPE_INT },
253
254         { "uint",       1, 1, GLSL_BASIC_TYPE_UINT },
255         { "uvec2",      2, 1, GLSL_BASIC_TYPE_UINT },
256         { "uvec3",      3, 1, GLSL_BASIC_TYPE_UINT },
257         { "uvec4",      4, 1, GLSL_BASIC_TYPE_UINT },
258
259         { "float",      1, 1, GLSL_BASIC_TYPE_FLOAT },
260         { "vec2",       2, 1, GLSL_BASIC_TYPE_FLOAT },
261         { "vec3",       3, 1, GLSL_BASIC_TYPE_FLOAT },
262         { "vec4",       4, 1, GLSL_BASIC_TYPE_FLOAT },
263         { "mat2",       2, 2, GLSL_BASIC_TYPE_FLOAT },
264         { "mat3",       3, 3, GLSL_BASIC_TYPE_FLOAT },
265         { "mat4",       4, 4, GLSL_BASIC_TYPE_FLOAT },
266
267         { "double",     1, 1, GLSL_BASIC_TYPE_DOUBLE },
268         { "dvec2",      2, 1, GLSL_BASIC_TYPE_DOUBLE },
269         { "dvec3",      3, 1, GLSL_BASIC_TYPE_DOUBLE },
270         { "dvec4",      4, 1, GLSL_BASIC_TYPE_DOUBLE },
271         { "dmat2",      2, 2, GLSL_BASIC_TYPE_DOUBLE },
272         { "dmat3",      3, 3, GLSL_BASIC_TYPE_DOUBLE },
273         { "dmat4",      4, 4, GLSL_BASIC_TYPE_DOUBLE }
274 };
275
276
277 VertexInputTest::VertexInputTest (tcu::TestContext&                                             testContext,
278                                                                   const std::string&                                    name,
279                                                                   const std::string&                                    description,
280                                                                   const std::vector<AttributeInfo>&             attributeInfos,
281                                                                   BindingMapping                                                bindingMapping,
282                                                                   AttributeLayout                                               attributeLayout)
283
284         : vkt::TestCase                 (testContext, name, description)
285         , m_attributeInfos              (attributeInfos)
286         , m_bindingMapping              (bindingMapping)
287         , m_attributeLayout             (attributeLayout)
288         , m_queryMaxAttributes  (attributeInfos.size() == 0)
289         , m_maxAttributes               (16)
290 {
291         DE_ASSERT(m_attributeLayout == ATTRIBUTE_LAYOUT_INTERLEAVED || m_bindingMapping == BINDING_MAPPING_ONE_TO_MANY);
292
293         m_usesDoubleType = false;
294
295         for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++)
296         {
297                 if (s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].basicType == GLSL_BASIC_TYPE_DOUBLE)
298                 {
299                         m_usesDoubleType = true;
300                         break;
301                 }
302         }
303 }
304
305 deUint32 getAttributeBinding (const VertexInputTest::BindingMapping bindingMapping, const VkVertexInputRate firstInputRate, const VkVertexInputRate inputRate, const deUint32 attributeNdx)
306 {
307         if (bindingMapping == VertexInputTest::BINDING_MAPPING_ONE_TO_ONE)
308         {
309                 // Each attribute uses a unique binding
310                 return attributeNdx;
311         }
312         else // bindingMapping == BINDING_MAPPING_ONE_TO_MANY
313         {
314                 // Alternate between two bindings
315                 return deUint32(firstInputRate + inputRate) % 2u;
316         }
317 }
318
319 //! Number of locations used up by an attribute.
320 deUint32 getConsumedLocations (const VertexInputTest::AttributeInfo& attributeInfo)
321 {
322         // double formats with more than 2 components will take 2 locations
323         const VertexInputTest::GlslType type = attributeInfo.glslType;
324         if ((type == VertexInputTest::GLSL_TYPE_DMAT2 || type == VertexInputTest::GLSL_TYPE_DMAT3 || type == VertexInputTest::GLSL_TYPE_DMAT4) &&
325                 (attributeInfo.vkType == VK_FORMAT_R64G64B64_SFLOAT || attributeInfo.vkType == VK_FORMAT_R64G64B64A64_SFLOAT))
326         {
327                 return 2u;
328         }
329         else
330                 return 1u;
331 }
332
333 VertexInputTest::AttributeInfo VertexInputTest::getAttributeInfo (size_t attributeNdx) const
334 {
335         if (m_queryMaxAttributes)
336         {
337                 AttributeInfo attributeInfo =
338                 {
339                         GLSL_TYPE_VEC4,
340                         VK_FORMAT_R8G8B8A8_SNORM,
341                         (attributeNdx % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE
342                 };
343
344                 return attributeInfo;
345         }
346         else
347         {
348                 return m_attributeInfos.at(attributeNdx);
349         }
350 }
351
352 size_t VertexInputTest::getNumAttributes (void) const
353 {
354         if (m_queryMaxAttributes)
355                 return m_maxAttributes;
356         else
357                 return m_attributeInfos.size();
358 }
359
360 TestInstance* VertexInputTest::createInstance (Context& context) const
361 {
362         typedef VertexInputInstance::VertexInputAttributeDescription VertexInputAttributeDescription;
363
364         // Check upfront for maximum number of vertex input attributes
365         {
366                 const InstanceInterface&                vki                             = context.getInstanceInterface();
367                 const VkPhysicalDevice                  physDevice              = context.getPhysicalDevice();
368                 const VkPhysicalDeviceLimits    limits                  = getPhysicalDeviceProperties(vki, physDevice).limits;
369
370                 const deUint32                                  maxAttributes   = limits.maxVertexInputAttributes;
371
372                 if (m_attributeInfos.size() > maxAttributes)
373                 {
374                         const std::string notSupportedStr = "Unsupported number of vertex input attributes, maxVertexInputAttributes: " + de::toString(maxAttributes);
375                         TCU_THROW(NotSupportedError, notSupportedStr.c_str());
376                 }
377
378                 // Use VkPhysicalDeviceLimits::maxVertexInputAttributes
379                 if (m_queryMaxAttributes)
380                         m_maxAttributes = maxAttributes;
381         }
382
383         // Create enough binding descriptions with random offsets
384         std::vector<VkVertexInputBindingDescription>    bindingDescriptions;
385         std::vector<VkDeviceSize>                                               bindingOffsets;
386         const size_t                                                                    numAttributes           = getNumAttributes();
387         const size_t                                                                    numBindings                     = (m_bindingMapping == BINDING_MAPPING_ONE_TO_ONE) ? numAttributes : ((numAttributes > 1) ? 2 : 1);
388         const VkVertexInputRate                                                 firstInputrate          = getAttributeInfo(0).inputRate;
389
390         for (size_t bindingNdx = 0; bindingNdx < numBindings; ++bindingNdx)
391         {
392                 // Bindings alternate between STEP_RATE_VERTEX and STEP_RATE_INSTANCE
393                 const VkVertexInputRate                                         inputRate                       = ((firstInputrate + bindingNdx) % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
394
395                 // Stride will be updated when creating the attribute descriptions
396                 const VkVertexInputBindingDescription           bindingDescription      =
397                 {
398                         static_cast<deUint32>(bindingNdx),              // deUint32                             binding;
399                         0u,                                                                             // deUint32                             stride;
400                         inputRate                                                               // VkVertexInputRate    inputRate;
401                 };
402
403                 bindingDescriptions.push_back(bindingDescription);
404                 bindingOffsets.push_back(4 * bindingNdx);
405         }
406
407         std::vector<VertexInputAttributeDescription>    attributeDescriptions;
408         deUint32                                                                                attributeLocation               = 0;
409         std::vector<deUint32>                                                   attributeOffsets                (bindingDescriptions.size(), 0);
410         std::vector<deUint32>                                                   attributeMaxSizes               (bindingDescriptions.size(), 0);        // max component or vector size, depending on which layout we are using
411
412         // To place the attributes sequentially we need to know the largest attribute and use its size in stride and offset calculations.
413         if (m_attributeLayout == ATTRIBUTE_LAYOUT_SEQUENTIAL)
414                 for (size_t attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx)
415                 {
416                         const AttributeInfo&    attributeInfo                   = getAttributeInfo(attributeNdx);
417                         const deUint32                  attributeBinding                = getAttributeBinding(m_bindingMapping, firstInputrate, attributeInfo.inputRate, static_cast<deUint32>(attributeNdx));
418                         const deUint32                  inputSize                               = getVertexFormatSize(attributeInfo.vkType);
419
420                         attributeMaxSizes[attributeBinding]                             = de::max(attributeMaxSizes[attributeBinding], inputSize);
421                 }
422
423         // Create attribute descriptions, assign them to bindings and update stride.
424         for (size_t attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx)
425         {
426                 const AttributeInfo&            attributeInfo                   = getAttributeInfo(attributeNdx);
427                 const GlslTypeDescription&      glslTypeDescription             = s_glslTypeDescriptions[attributeInfo.glslType];
428                 const deUint32                          inputSize                               = getVertexFormatSize(attributeInfo.vkType);
429                 const deUint32                          attributeBinding                = getAttributeBinding(m_bindingMapping, firstInputrate, attributeInfo.inputRate, static_cast<deUint32>(attributeNdx));
430                 const deUint32                          vertexCount                             = (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) ? (4 * 2) : 2;
431
432                 VertexInputAttributeDescription attributeDescription =
433                 {
434                         attributeInfo.glslType,                                                 // GlslType             glslType;
435                         0,                                                                                              // int                  vertexInputIndex;
436                         {
437                                 0u,                                                                                     // uint32_t    location;
438                                 attributeBinding,                                                       // uint32_t    binding;
439                                 attributeInfo.vkType,                                           // VkFormat    format;
440                                 0u,                                                                                     // uint32_t    offset;
441                         },
442                 };
443
444                 // Matrix types add each column as a separate attribute.
445                 for (int descNdx = 0; descNdx < glslTypeDescription.vertexInputCount; ++descNdx)
446                 {
447                         attributeDescription.vertexInputIndex           = descNdx;
448                         attributeDescription.vkDescription.location     = attributeLocation;
449
450                         if (m_attributeLayout == ATTRIBUTE_LAYOUT_INTERLEAVED)
451                         {
452                                 const deUint32  offsetToComponentAlignment               = getNextMultipleOffset(getVertexFormatComponentSize(attributeInfo.vkType),
453                                                                                                                                                                                  (deUint32)bindingOffsets[attributeBinding] + attributeOffsets[attributeBinding]);
454                                 attributeOffsets[attributeBinding]                              += offsetToComponentAlignment;
455
456                                 attributeDescription.vkDescription.offset                = attributeOffsets[attributeBinding];
457                                 attributeDescriptions.push_back(attributeDescription);
458
459                                 bindingDescriptions[attributeBinding].stride    += offsetToComponentAlignment + inputSize;
460                                 attributeOffsets[attributeBinding]                              += inputSize;
461                                 attributeMaxSizes[attributeBinding]                              = de::max(attributeMaxSizes[attributeBinding], getVertexFormatComponentSize(attributeInfo.vkType));
462                         }
463                         else // m_attributeLayout == ATTRIBUTE_LAYOUT_SEQUENTIAL
464                         {
465                                 attributeDescription.vkDescription.offset                = attributeOffsets[attributeBinding];
466                                 attributeDescriptions.push_back(attributeDescription);
467
468                                 attributeOffsets[attributeBinding]                              += vertexCount * attributeMaxSizes[attributeBinding];
469                         }
470
471                         attributeLocation += getConsumedLocations(attributeInfo);
472                 }
473
474                 if (m_attributeLayout == ATTRIBUTE_LAYOUT_SEQUENTIAL)
475                         bindingDescriptions[attributeBinding].stride = attributeMaxSizes[attributeBinding];
476         }
477
478         // Make sure the stride results in aligned access
479         for (size_t bindingNdx = 0; bindingNdx < bindingDescriptions.size(); ++bindingNdx)
480         {
481                 if (attributeMaxSizes[bindingNdx] > 0)
482                         bindingDescriptions[bindingNdx].stride += getNextMultipleOffset(attributeMaxSizes[bindingNdx], bindingDescriptions[bindingNdx].stride);
483         }
484
485         // Check upfront for maximum number of vertex input bindings
486         {
487                 const InstanceInterface&                vki                             = context.getInstanceInterface();
488                 const VkPhysicalDevice                  physDevice              = context.getPhysicalDevice();
489                 const VkPhysicalDeviceLimits    limits                  = getPhysicalDeviceProperties(vki, physDevice).limits;
490
491                 const deUint32                                  maxBindings             = limits.maxVertexInputBindings;
492
493                 if (bindingDescriptions.size() > maxBindings)
494                 {
495                         const std::string notSupportedStr = "Unsupported number of vertex input bindings, maxVertexInputBindings: " + de::toString(maxBindings);
496                         TCU_THROW(NotSupportedError, notSupportedStr.c_str());
497                 }
498         }
499
500         return new VertexInputInstance(context, attributeDescriptions, bindingDescriptions, bindingOffsets);
501 }
502
503 void VertexInputTest::initPrograms (SourceCollections& programCollection) const
504 {
505         std::ostringstream vertexSrc;
506
507         vertexSrc << "#version 440\n"
508                           << "layout(constant_id = 0) const int numAttributes = " << m_maxAttributes << ";\n"
509                           << getGlslInputDeclarations()
510                           << "layout(location = 0) out highp vec4 vtxColor;\n"
511                           << "out gl_PerVertex {\n"
512                           << "  vec4 gl_Position;\n"
513                           << "};\n";
514
515         // NOTE: double abs(double x) undefined in glslang ??
516         if (m_usesDoubleType)
517                 vertexSrc << "double abs (double x) { if (x < 0.0LF) return -x; else return x; }\n";
518
519         vertexSrc << "void main (void)\n"
520                           << "{\n"
521                           << getGlslVertexCheck()
522                           << "}\n";
523
524         programCollection.glslSources.add("attribute_test_vert") << glu::VertexSource(vertexSrc.str());
525
526         programCollection.glslSources.add("attribute_test_frag") << glu::FragmentSource(
527                 "#version 440\n"
528                 "layout(location = 0) in highp vec4 vtxColor;\n"
529                 "layout(location = 0) out highp vec4 fragColor;\n"
530                 "void main (void)\n"
531                 "{\n"
532                 "       fragColor = vtxColor;\n"
533                 "}\n");
534 }
535
536 std::string VertexInputTest::getGlslInputDeclarations (void) const
537 {
538         std::ostringstream      glslInputs;
539         deUint32                        location = 0;
540
541         if (m_queryMaxAttributes)
542         {
543                 const GlslTypeDescription& glslTypeDesc = s_glslTypeDescriptions[GLSL_TYPE_VEC4];
544                 glslInputs << "layout(location = 0) in " << glslTypeDesc.name << " attr[numAttributes];\n";
545         }
546         else
547         {
548                 for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++)
549                 {
550                         const GlslTypeDescription& glslTypeDesc = s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType];
551
552                         glslInputs << "layout(location = " << location << ") in " << glslTypeDesc.name << " attr" << attributeNdx << ";\n";
553                         location += glslTypeDesc.vertexInputCount;
554                 }
555         }
556
557         return glslInputs.str();
558 }
559
560 std::string VertexInputTest::getGlslVertexCheck (void) const
561 {
562         std::ostringstream      glslCode;
563         int                                     totalInputComponentCount        = 0;
564
565         glslCode << "   int okCount = 0;\n";
566
567         if (m_queryMaxAttributes)
568         {
569                 const AttributeInfo attributeInfo = getAttributeInfo(0);
570
571                 glslCode << "   for (int checkNdx = 0; checkNdx < numAttributes; checkNdx++)\n"
572                                  <<     "       {\n"
573                                  << "           uint index = (checkNdx % 2 == 0) ? gl_VertexIndex : gl_InstanceIndex;\n";
574
575                 glslCode << getGlslAttributeConditions(attributeInfo, "checkNdx")
576                                  << "   }\n";
577
578                         const int vertexInputCount      = VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputCount;
579                         totalInputComponentCount        += vertexInputCount * VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputComponentCount;
580
581                 glslCode <<
582                         "       if (okCount == " << totalInputComponentCount << " * numAttributes)\n"
583                         "       {\n"
584                         "               if (gl_InstanceIndex == 0)\n"
585                         "                       vtxColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
586                         "               else\n"
587                         "                       vtxColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
588                         "       }\n"
589                         "       else\n"
590                         "       {\n"
591                         "               vtxColor = vec4(okCount / float(" << totalInputComponentCount << " * numAttributes), 0.0f, 0.0f, 1.0);\n" <<
592                         "       }\n\n"
593                         "       if (gl_InstanceIndex == 0)\n"
594                         "       {\n"
595                         "               if (gl_VertexIndex == 0) gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
596                         "               else if (gl_VertexIndex == 1) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n"
597                         "               else if (gl_VertexIndex == 2) gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
598                         "               else if (gl_VertexIndex == 3) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n"
599                         "               else gl_Position = vec4(0.0);\n"
600                         "       }\n"
601                         "       else\n"
602                         "       {\n"
603                         "               if (gl_VertexIndex == 0) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n"
604                         "               else if (gl_VertexIndex == 1) gl_Position = vec4(1.0, -1.0, 0.0, 1.0);\n"
605                         "               else if (gl_VertexIndex == 2) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n"
606                         "               else if (gl_VertexIndex == 3) gl_Position = vec4(1.0, 1.0, 0.0, 1.0);\n"
607                         "               else gl_Position = vec4(0.0);\n"
608                         "       }\n";
609         }
610         else
611         {
612                 for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++)
613                 {
614                         glslCode << getGlslAttributeConditions(m_attributeInfos[attributeNdx], de::toString(attributeNdx));
615
616                         const int vertexInputCount      = VertexInputTest::s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].vertexInputCount;
617                         totalInputComponentCount        += vertexInputCount * VertexInputTest::s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].vertexInputComponentCount;
618                 }
619
620                 glslCode <<
621                         "       if (okCount == " << totalInputComponentCount << ")\n"
622                         "       {\n"
623                         "               if (gl_InstanceIndex == 0)\n"
624                         "                       vtxColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
625                         "               else\n"
626                         "                       vtxColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
627                         "       }\n"
628                         "       else\n"
629                         "       {\n"
630                         "               vtxColor = vec4(okCount / float(" << totalInputComponentCount << "), 0.0f, 0.0f, 1.0);\n" <<
631                         "       }\n\n"
632                         "       if (gl_InstanceIndex == 0)\n"
633                         "       {\n"
634                         "               if (gl_VertexIndex == 0) gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
635                         "               else if (gl_VertexIndex == 1) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n"
636                         "               else if (gl_VertexIndex == 2) gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
637                         "               else if (gl_VertexIndex == 3) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n"
638                         "               else gl_Position = vec4(0.0);\n"
639                         "       }\n"
640                         "       else\n"
641                         "       {\n"
642                         "               if (gl_VertexIndex == 0) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n"
643                         "               else if (gl_VertexIndex == 1) gl_Position = vec4(1.0, -1.0, 0.0, 1.0);\n"
644                         "               else if (gl_VertexIndex == 2) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n"
645                         "               else if (gl_VertexIndex == 3) gl_Position = vec4(1.0, 1.0, 0.0, 1.0);\n"
646                         "               else gl_Position = vec4(0.0);\n"
647                         "       }\n";
648         }
649         return glslCode.str();
650 }
651
652 std::string VertexInputTest::getGlslAttributeConditions (const AttributeInfo& attributeInfo, const std::string attributeIndex) const
653 {
654         std::ostringstream      glslCode;
655         std::ostringstream      attributeVar;
656         const int                       componentCount          = VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputComponentCount;
657         const int                       vertexInputCount        = VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputCount;
658         const deUint32          totalComponentCount     = componentCount * vertexInputCount;
659         const tcu::Vec4         threshold                       = getFormatThreshold(attributeInfo.vkType);
660         deUint32                        componentIndex          = 0;
661         const std::string       indexStr                        = m_queryMaxAttributes ? "[" + attributeIndex + "]" : attributeIndex;
662         const std::string       indentStr                       = m_queryMaxAttributes ? "\t\t" : "\t";
663         std::string                     indexId;
664
665         if (m_queryMaxAttributes)
666                 indexId = "index";
667         else
668                 indexId = (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) ? "gl_VertexIndex" : "gl_InstanceIndex";
669
670         attributeVar << "attr" << indexStr;
671
672         glslCode << std::fixed;
673
674         for (int columnNdx = 0; columnNdx< vertexInputCount; columnNdx++)
675         {
676                 for (int rowNdx = 0; rowNdx < componentCount; rowNdx++)
677                 {
678                         std::string accessStr;
679                         {
680                                 // Build string representing the access to the attribute component
681                                 std::ostringstream accessStream;
682                                 accessStream << attributeVar.str();
683
684                                 if (vertexInputCount == 1)
685                                 {
686                                         if (componentCount > 1)
687                                                 accessStream << "[" << rowNdx << "]";
688                                 }
689                                 else
690                                 {
691                                         accessStream << "[" << columnNdx << "][" << rowNdx << "]";
692                                 }
693
694                                 accessStr = accessStream.str();
695                         }
696
697                         if (isVertexFormatSint(attributeInfo.vkType))
698                         {
699                                 glslCode << indentStr <<  "if (" << accessStr << " == -(" << totalComponentCount << " * " << indexId << " + " << componentIndex << "))\n";
700                         }
701                         else if (isVertexFormatUint(attributeInfo.vkType))
702                         {
703                                 glslCode << indentStr << "if (" << accessStr << " == uint(" << totalComponentCount << " * " << indexId << " + " << componentIndex << "))\n";
704                         }
705                         else if (isVertexFormatSfloat(attributeInfo.vkType))
706                         {
707                                 if (VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].basicType == VertexInputTest::GLSL_BASIC_TYPE_DOUBLE)
708                                 {
709                                         glslCode << indentStr << "if (abs(" << accessStr << " + double(0.01 * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < double(" << threshold[rowNdx] << "))\n";
710                                 }
711                                 else
712                                 {
713                                         glslCode << indentStr << "if (abs(" << accessStr << " + (0.01 * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n";
714                                 }
715                         }
716                         else if (isVertexFormatSscaled(attributeInfo.vkType))
717                         {
718                                 glslCode << indentStr << "if (abs(" << accessStr << " + (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0)) < " << threshold[rowNdx] << ")\n";
719                         }
720                         else if (isVertexFormatUscaled(attributeInfo.vkType))
721                         {
722                                 glslCode << indentStr << "if (abs(" << accessStr << " - (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0)) < " << threshold[rowNdx] << ")\n";
723                         }
724                         else if (isVertexFormatSnorm(attributeInfo.vkType))
725                         {
726                                 const float representableDiff = getRepresentableDifferenceSnorm(attributeInfo.vkType);
727
728                                 glslCode << indentStr << "if (abs(" << accessStr << " - (-1.0 + " << representableDiff << " * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n";
729                         }
730                         else if (isVertexFormatUnorm(attributeInfo.vkType) || isVertexFormatSRGB(attributeInfo.vkType))
731                         {
732                                 const float representableDiff = getRepresentableDifferenceUnorm(attributeInfo.vkType);
733
734                                 glslCode << indentStr << "if (abs(" << accessStr << " - " << "(" << representableDiff << " * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n";
735                         }
736                         else
737                         {
738                                 DE_ASSERT(false);
739                         }
740
741                         glslCode << indentStr << "\tokCount++;\n\n";
742
743                         componentIndex++;
744                 }
745         }
746         return glslCode.str();
747 }
748
749 tcu::Vec4 VertexInputTest::getFormatThreshold (VkFormat format)
750 {
751         using tcu::Vec4;
752
753         switch (format)
754         {
755                 case VK_FORMAT_R32_SFLOAT:
756                 case VK_FORMAT_R32G32_SFLOAT:
757                 case VK_FORMAT_R32G32B32_SFLOAT:
758                 case VK_FORMAT_R32G32B32A32_SFLOAT:
759                 case VK_FORMAT_R64_SFLOAT:
760                 case VK_FORMAT_R64G64_SFLOAT:
761                 case VK_FORMAT_R64G64B64_SFLOAT:
762                 case VK_FORMAT_R64G64B64A64_SFLOAT:
763                         return Vec4(0.00001f);
764
765                 default:
766                         break;
767         }
768
769         if (isVertexFormatSnorm(format))
770         {
771                 return Vec4(1.5f * getRepresentableDifferenceSnorm(format));
772         }
773         else if (isVertexFormatUnorm(format))
774         {
775                 return Vec4(1.5f * getRepresentableDifferenceUnorm(format));
776         }
777
778         return Vec4(0.001f);
779 }
780
781 VertexInputInstance::VertexInputInstance (Context&                                                                                              context,
782                                                                                   const AttributeDescriptionList&                                               attributeDescriptions,
783                                                                                   const std::vector<VkVertexInputBindingDescription>&   bindingDescriptions,
784                                                                                   const std::vector<VkDeviceSize>&                                              bindingOffsets)
785         : vkt::TestInstance                     (context)
786         , m_renderSize                          (16, 16)
787         , m_colorFormat                         (VK_FORMAT_R8G8B8A8_UNORM)
788 {
789         DE_ASSERT(bindingDescriptions.size() == bindingOffsets.size());
790
791         const DeviceInterface&          vk                                              = context.getDeviceInterface();
792         const VkDevice                          vkDevice                                = context.getDevice();
793         const deUint32                          queueFamilyIndex                = context.getUniversalQueueFamilyIndex();
794         SimpleAllocator                         memAlloc                                (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
795         const VkComponentMapping        componentMappingRGBA    = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
796
797         // Check upfront for unsupported features
798         for (size_t attributeNdx = 0; attributeNdx < attributeDescriptions.size(); attributeNdx++)
799         {
800                 const VkVertexInputAttributeDescription& attributeDescription = attributeDescriptions[attributeNdx].vkDescription;
801                 if (!isSupportedVertexFormat(context, attributeDescription.format))
802                 {
803                         throw tcu::NotSupportedError(std::string("Unsupported format for vertex input: ") + getFormatName(attributeDescription.format));
804                 }
805         }
806
807         // Create color image
808         {
809                 const VkImageCreateInfo colorImageParams =
810                 {
811                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                            // VkStructureType                      sType;
812                         DE_NULL,                                                                                                                                        // const void*                          pNext;
813                         0u,                                                                                                                                                     // VkImageCreateFlags           flags;
814                         VK_IMAGE_TYPE_2D,                                                                                                                       // VkImageType                          imageType;
815                         m_colorFormat,                                                                                                                          // VkFormat                                     format;
816                         { m_renderSize.x(), m_renderSize.y(), 1u },                                                                     // VkExtent3D                           extent;
817                         1u,                                                                                                                                                     // deUint32                                     mipLevels;
818                         1u,                                                                                                                                                     // deUint32                                     arrayLayers;
819                         VK_SAMPLE_COUNT_1_BIT,                                                                                                          // VkSampleCountFlagBits        samples;
820                         VK_IMAGE_TILING_OPTIMAL,                                                                                                        // VkImageTiling                        tiling;
821                         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,          // VkImageUsageFlags            usage;
822                         VK_SHARING_MODE_EXCLUSIVE,                                                                                                      // VkSharingMode                        sharingMode;
823                         1u,                                                                                                                                                     // deUint32                                     queueFamilyIndexCount;
824                         &queueFamilyIndex,                                                                                                                      // const deUint32*                      pQueueFamilyIndices;
825                         VK_IMAGE_LAYOUT_UNDEFINED,                                                                                                      // VkImageLayout                        initialLayout;
826                 };
827
828                 m_colorImage                    = createImage(vk, vkDevice, &colorImageParams);
829
830                 // Allocate and bind color image memory
831                 m_colorImageAlloc               = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
832                 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
833         }
834
835         // Create color attachment view
836         {
837                 const VkImageViewCreateInfo colorAttachmentViewParams =
838                 {
839                         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,               // VkStructureType                      sType;
840                         DE_NULL,                                                                                // const void*                          pNext;
841                         0u,                                                                                             // VkImageViewCreateFlags       flags;
842                         *m_colorImage,                                                                  // VkImage                                      image;
843                         VK_IMAGE_VIEW_TYPE_2D,                                                  // VkImageViewType                      viewType;
844                         m_colorFormat,                                                                  // VkFormat                                     format;
845                         componentMappingRGBA,                                                   // VkComponentMapping           components;
846                         { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },  // VkImageSubresourceRange      subresourceRange;
847                 };
848
849                 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
850         }
851
852         // Create render pass
853         {
854                 const VkAttachmentDescription colorAttachmentDescription =
855                 {
856                         0u,                                                                                                     // VkAttachmentDescriptionFlags         flags;
857                         m_colorFormat,                                                                          // VkFormat                                                     format;
858                         VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
859                         VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
860                         VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
861                         VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
862                         VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
863                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        initialLayout;
864                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout                                        finalLayout;
865                 };
866
867                 const VkAttachmentReference colorAttachmentReference =
868                 {
869                         0u,                                                                                                     // deUint32                     attachment;
870                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
871                 };
872
873                 const VkSubpassDescription subpassDescription =
874                 {
875                         0u,                                                                                                     // VkSubpassDescriptionFlags    flags;
876                         VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                  pipelineBindPoint;
877                         0u,                                                                                                     // deUint32                                             inputAttachmentCount;
878                         DE_NULL,                                                                                        // const VkAttachmentReference* pInputAttachments;
879                         1u,                                                                                                     // deUint32                                             colorAttachmentCount;
880                         &colorAttachmentReference,                                                      // const VkAttachmentReference* pColorAttachments;
881                         DE_NULL,                                                                                        // const VkAttachmentReference* pResolveAttachments;
882                         DE_NULL,                                                                                        // const VkAttachmentReference* pDepthStencilAttachment;
883                         0u,                                                                                                     // deUint32                                             preserveAttachmentCount;
884                         DE_NULL                                                                                         // const VkAttachmentReference* pPreserveAttachments;
885                 };
886
887                 const VkRenderPassCreateInfo renderPassParams =
888                 {
889                         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
890                         DE_NULL,                                                                                        // const void*                                          pNext;
891                         0u,                                                                                                     // VkRenderPassCreateFlags                      flags;
892                         1u,                                                                                                     // deUint32                                                     attachmentCount;
893                         &colorAttachmentDescription,                                            // const VkAttachmentDescription*       pAttachments;
894                         1u,                                                                                                     // deUint32                                                     subpassCount;
895                         &subpassDescription,                                                            // const VkSubpassDescription*          pSubpasses;
896                         0u,                                                                                                     // deUint32                                                     dependencyCount;
897                         DE_NULL                                                                                         // const VkSubpassDependency*           pDependencies;
898                 };
899
900                 m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
901         }
902
903         // Create framebuffer
904         {
905                 const VkFramebufferCreateInfo framebufferParams =
906                 {
907                         VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,                      // VkStructureType                      sType;
908                         DE_NULL,                                                                                        // const void*                          pNext;
909                         0u,                                                                                                     // VkFramebufferCreateFlags     flags;
910                         *m_renderPass,                                                                          // VkRenderPass                         renderPass;
911                         1u,                                                                                                     // deUint32                                     attachmentCount;
912                         &m_colorAttachmentView.get(),                                           // const VkImageView*           pAttachments;
913                         (deUint32)m_renderSize.x(),                                                     // deUint32                                     width;
914                         (deUint32)m_renderSize.y(),                                                     // deUint32                                     height;
915                         1u                                                                                                      // deUint32                                     layers;
916                 };
917
918                 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
919         }
920
921         // Create pipeline layout
922         {
923                 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
924                 {
925                         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                                      sType;
926                         DE_NULL,                                                                                        // const void*                                          pNext;
927                         0u,                                                                                                     // VkPipelineLayoutCreateFlags          flags;
928                         0u,                                                                                                     // deUint32                                                     setLayoutCount;
929                         DE_NULL,                                                                                        // const VkDescriptorSetLayout*         pSetLayouts;
930                         0u,                                                                                                     // deUint32                                                     pushConstantRangeCount;
931                         DE_NULL                                                                                         // const VkPushConstantRange*           pPushConstantRanges;
932                 };
933
934                 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
935         }
936
937         m_vertexShaderModule    = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("attribute_test_vert"), 0);
938         m_fragmentShaderModule  = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("attribute_test_frag"), 0);
939
940         // Create specialization constant
941         deUint32 specializationData = static_cast<deUint32>(attributeDescriptions.size());
942
943         const VkSpecializationMapEntry specializationMapEntry =
944         {
945                 0,                                                                                                              // uint32_t                                                     constantID
946                 0,                                                                                                              // uint32_t                                                     offset
947                 sizeof(specializationData),                                                             // uint32_t                                                     size
948         };
949
950         const VkSpecializationInfo specializationInfo =
951         {
952                 1,                                                                                                              // uint32_t                                                     mapEntryCount
953                 &specializationMapEntry,                                                                // const void*                                          pMapEntries
954                 sizeof(specializationData),                                                             // size_t                                                       dataSize
955                 &specializationData                                                                             // const void*                                          pData
956         };
957
958         // Create pipeline
959         {
960                 const VkPipelineShaderStageCreateInfo shaderStageParams[2] =
961                 {
962                         {
963                                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,            // VkStructureType                                              sType;
964                                 DE_NULL,                                                                                                        // const void*                                                  pNext;
965                                 0u,                                                                                                                     // VkPipelineShaderStageCreateFlags             flags;
966                                 VK_SHADER_STAGE_VERTEX_BIT,                                                                     // VkShaderStageFlagBits                                stage;
967                                 *m_vertexShaderModule,                                                                          // VkShaderModule                                               module;
968                                 "main",                                                                                                         // const char*                                                  pName;
969                                 &specializationInfo                                                                                     // const VkSpecializationInfo*                  pSpecializationInfo;
970                         },
971                         {
972                                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,            // VkStructureType                                              sType;
973                                 DE_NULL,                                                                                                        // const void*                                                  pNext;
974                                 0u,                                                                                                                     // VkPipelineShaderStageCreateFlags             flags;
975                                 VK_SHADER_STAGE_FRAGMENT_BIT,                                                           // VkShaderStageFlagBits                                stage;
976                                 *m_fragmentShaderModule,                                                                        // VkShaderModule                                               module;
977                                 "main",                                                                                                         // const char*                                                  pName;
978                                 DE_NULL                                                                                                         // const VkSpecializationInfo*                  pSpecializationInfo;
979                         }
980                 };
981
982                 // Create vertex attribute array and check if their VK formats are supported
983                 std::vector<VkVertexInputAttributeDescription> vkAttributeDescriptions;
984                 for (size_t attributeNdx = 0; attributeNdx < attributeDescriptions.size(); attributeNdx++)
985                 {
986                         const VkVertexInputAttributeDescription& attributeDescription = attributeDescriptions[attributeNdx].vkDescription;
987                         vkAttributeDescriptions.push_back(attributeDescription);
988                 }
989
990                 const VkPipelineVertexInputStateCreateInfo      vertexInputStateParams  =
991                 {
992                         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                                                      sType;
993                         DE_NULL,                                                                                                                // const void*                                                          pNext;
994                         0u,                                                                                                                             // VkPipelineVertexInputStateCreateFlags        flags;
995                         (deUint32)bindingDescriptions.size(),                                                   // deUint32                                                                     vertexBindingDescriptionCount;
996                         bindingDescriptions.data(),                                                                             // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
997                         (deUint32)vkAttributeDescriptions.size(),                                               // deUint32                                                                     vertexAttributeDescriptionCount;
998                         vkAttributeDescriptions.data()                                                                  // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
999                 };
1000
1001                 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
1002                 {
1003                         VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                                                      sType;
1004                         DE_NULL,                                                                                                                // const void*                                                          pNext;
1005                         0u,                                                                                                                             // VkPipelineInputAssemblyStateCreateFlags      flags;
1006                         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,                                                   // VkPrimitiveTopology                                          topology;
1007                         false                                                                                                                   // VkBool32                                                                     primitiveRestartEnable;
1008                 };
1009
1010                 const VkViewport viewport =
1011                 {
1012                         0.0f,                                           // float        x;
1013                         0.0f,                                           // float        y;
1014                         (float)m_renderSize.x(),        // float        width;
1015                         (float)m_renderSize.y(),        // float        height;
1016                         0.0f,                                           // float        minDepth;
1017                         1.0f                                            // float        maxDepth;
1018                 };
1019
1020                 const VkRect2D scissor = { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } };
1021
1022                 const VkPipelineViewportStateCreateInfo viewportStateParams =
1023                 {
1024                         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,                  // VkStructureType                                              sType;
1025                         DE_NULL,                                                                                                                // const void*                                                  pNext;
1026                         0u,                                                                                                                             // VkPipelineViewportStateCreateFlags   flags;
1027                         1u,                                                                                                                             // deUint32                                                             viewportCount;
1028                         &viewport,                                                                                                              // const VkViewport*                                    pViewports;
1029                         1u,                                                                                                                             // deUint32                                                             scissorCount;
1030                         &scissor                                                                                                                // const VkRect2D*                                              pScissors;
1031                 };
1032
1033                 const VkPipelineRasterizationStateCreateInfo rasterStateParams =
1034                 {
1035                         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
1036                         DE_NULL,                                                                                                                // const void*                                                          pNext;
1037                         0u,                                                                                                                             // VkPipelineRasterizationStateCreateFlags      flags;
1038                         false,                                                                                                                  // VkBool32                                                                     depthClampEnable;
1039                         false,                                                                                                                  // VkBool32                                                                     rasterizerDiscardEnable;
1040                         VK_POLYGON_MODE_FILL,                                                                                   // VkPolygonMode                                                        polygonMode;
1041                         VK_CULL_MODE_NONE,                                                                                              // VkCullModeFlags                                                      cullMode;
1042                         VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                // VkFrontFace                                                          frontFace;
1043                         VK_FALSE,                                                                                                               // VkBool32                                                                     depthBiasEnable;
1044                         0.0f,                                                                                                                   // float                                                                        depthBiasConstantFactor;
1045                         0.0f,                                                                                                                   // float                                                                        depthBiasClamp;
1046                         0.0f,                                                                                                                   // float                                                                        depthBiasSlopeFactor;
1047                         1.0f,                                                                                                                   // float                                                                        lineWidth;
1048                 };
1049
1050                 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
1051                 {
1052                         false,                                                                                                                                          // VkBool32                                     blendEnable;
1053                         VK_BLEND_FACTOR_ONE,                                                                                                            // VkBlendFactor                        srcColorBlendFactor;
1054                         VK_BLEND_FACTOR_ZERO,                                                                                                           // VkBlendFactor                        dstColorBlendFactor;
1055                         VK_BLEND_OP_ADD,                                                                                                                        // VkBlendOp                            colorBlendOp;
1056                         VK_BLEND_FACTOR_ONE,                                                                                                            // VkBlendFactor                        srcAlphaBlendFactor;
1057                         VK_BLEND_FACTOR_ZERO,                                                                                                           // VkBlendFactor                        dstAlphaBlendFactor;
1058                         VK_BLEND_OP_ADD,                                                                                                                        // VkBlendOp                            alphaBlendOp;
1059                         VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |                                           // VkColorComponentFlags        colorWriteMask;
1060                                 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
1061                 };
1062
1063                 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
1064                 {
1065                         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
1066                         DE_NULL,                                                                                                        // const void*                                                                  pNext;
1067                         0u,                                                                                                                     // VkPipelineColorBlendStateCreateFlags                 flags;
1068                         false,                                                                                                          // VkBool32                                                                             logicOpEnable;
1069                         VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
1070                         1u,                                                                                                                     // deUint32                                                                             attachmentCount;
1071                         &colorBlendAttachmentState,                                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments;
1072                         { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // float                                                                                blendConstants[4];
1073                 };
1074
1075                 const VkPipelineMultisampleStateCreateInfo      multisampleStateParams  =
1076                 {
1077                         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
1078                         DE_NULL,                                                                                                        // const void*                                                          pNext;
1079                         0u,                                                                                                                     // VkPipelineMultisampleStateCreateFlags        flags;
1080                         VK_SAMPLE_COUNT_1_BIT,                                                                          // VkSampleCountFlagBits                                        rasterizationSamples;
1081                         false,                                                                                                          // VkBool32                                                                     sampleShadingEnable;
1082                         0.0f,                                                                                                           // float                                                                        minSampleShading;
1083                         DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
1084                         false,                                                                                                          // VkBool32                                                                     alphaToCoverageEnable;
1085                         false                                                                                                           // VkBool32                                                                     alphaToOneEnable;
1086                 };
1087
1088                 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
1089                 {
1090                         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
1091                         DE_NULL,                                                                                                        // const void*                                                          pNext;
1092                         0u,                                                                                                                     // VkPipelineDepthStencilStateCreateFlags       flags;
1093                         false,                                                                                                          // VkBool32                                                                     depthTestEnable;
1094                         false,                                                                                                          // VkBool32                                                                     depthWriteEnable;
1095                         VK_COMPARE_OP_LESS,                                                                                     // VkCompareOp                                                          depthCompareOp;
1096                         false,                                                                                                          // VkBool32                                                                     depthBoundsTestEnable;
1097                         false,                                                                                                          // VkBool32                                                                     stencilTestEnable;
1098                         // VkStencilOpState     front;
1099                         {
1100                                 VK_STENCIL_OP_KEEP,             // VkStencilOp  failOp;
1101                                 VK_STENCIL_OP_KEEP,             // VkStencilOp  passOp;
1102                                 VK_STENCIL_OP_KEEP,             // VkStencilOp  depthFailOp;
1103                                 VK_COMPARE_OP_NEVER,    // VkCompareOp  compareOp;
1104                                 0u,                                             // deUint32             compareMask;
1105                                 0u,                                             // deUint32             writeMask;
1106                                 0u,                                             // deUint32             reference;
1107                         },
1108                         // VkStencilOpState     back;
1109                         {
1110                                 VK_STENCIL_OP_KEEP,             // VkStencilOp  failOp;
1111                                 VK_STENCIL_OP_KEEP,             // VkStencilOp  passOp;
1112                                 VK_STENCIL_OP_KEEP,             // VkStencilOp  depthFailOp;
1113                                 VK_COMPARE_OP_NEVER,    // VkCompareOp  compareOp;
1114                                 0u,                                             // deUint32             compareMask;
1115                                 0u,                                             // deUint32             writeMask;
1116                                 0u,                                             // deUint32             reference;
1117                         },
1118                         0.0f,                                                                                                           // float                        minDepthBounds;
1119                         1.0f,                                                                                                           // float                        maxDepthBounds;
1120                 };
1121
1122                 const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
1123                 {
1124                         VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,        // VkStructureType                                                                      sType;
1125                         DE_NULL,                                                                                        // const void*                                                                          pNext;
1126                         0u,                                                                                                     // VkPipelineCreateFlags                                                        flags;
1127                         2u,                                                                                                     // deUint32                                                                                     stageCount;
1128                         shaderStageParams,                                                                      // const VkPipelineShaderStageCreateInfo*                       pStages;
1129                         &vertexInputStateParams,                                                        // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
1130                         &inputAssemblyStateParams,                                                      // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
1131                         DE_NULL,                                                                                        // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
1132                         &viewportStateParams,                                                           // const VkPipelineViewportStateCreateInfo*                     pViewportState;
1133                         &rasterStateParams,                                                                     // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
1134                         &multisampleStateParams,                                                        // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
1135                         &depthStencilStateParams,                                                       // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
1136                         &colorBlendStateParams,                                                         // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
1137                         (const VkPipelineDynamicStateCreateInfo*)DE_NULL,       // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
1138                         *m_pipelineLayout,                                                                      // VkPipelineLayout                                                                     layout;
1139                         *m_renderPass,                                                                          // VkRenderPass                                                                         renderPass;
1140                         0u,                                                                                                     // deUint32                                                                                     subpass;
1141                         0u,                                                                                                     // VkPipeline                                                                           basePipelineHandle;
1142                         0u                                                                                                      // deInt32                                                                                      basePipelineIndex;
1143                 };
1144
1145                 m_graphicsPipeline      = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
1146         }
1147
1148         // Create vertex buffer
1149         {
1150                 const VkBufferCreateInfo vertexBufferParams =
1151                 {
1152                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
1153                         DE_NULL,                                                                        // const void*                  pNext;
1154                         0u,                                                                                     // VkBufferCreateFlags  flags;
1155                         4096u,                                                                          // VkDeviceSize                 size;
1156                         VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                      // VkBufferUsageFlags   usage;
1157                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
1158                         1u,                                                                                     // deUint32                             queueFamilyIndexCount;
1159                         &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
1160                 };
1161
1162                 // Upload data for each vertex input binding
1163                 for (deUint32 bindingNdx = 0; bindingNdx < bindingDescriptions.size(); bindingNdx++)
1164                 {
1165                         Move<VkBuffer>                  vertexBuffer            = createBuffer(vk, vkDevice, &vertexBufferParams);
1166                         de::MovePtr<Allocation> vertexBufferAlloc       = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
1167
1168                         VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset()));
1169
1170                         writeVertexInputData((deUint8*)vertexBufferAlloc->getHostPtr(), bindingDescriptions[bindingNdx], bindingOffsets[bindingNdx], attributeDescriptions);
1171                         flushMappedMemoryRange(vk, vkDevice, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferParams.size);
1172
1173                         m_vertexBuffers.push_back(vertexBuffer.disown());
1174                         m_vertexBufferAllocs.push_back(vertexBufferAlloc.release());
1175                 }
1176         }
1177
1178         // Create command pool
1179         m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1180
1181         // Create command buffer
1182         {
1183                 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
1184                 {
1185                         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                                      sType;
1186                         DE_NULL,                                                                                // const void*                                          pNext;
1187                         0u,                                                                                             // VkCommandBufferUsageFlags            flags;
1188                         (const VkCommandBufferInheritanceInfo*)DE_NULL,
1189                 };
1190
1191                 const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
1192
1193                 const VkRenderPassBeginInfo renderPassBeginInfo =
1194                 {
1195                         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                               // VkStructureType              sType;
1196                         DE_NULL,                                                                                                // const void*                  pNext;
1197                         *m_renderPass,                                                                                  // VkRenderPass                 renderPass;
1198                         *m_framebuffer,                                                                                 // VkFramebuffer                framebuffer;
1199                         { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } },   // VkRect2D                             renderArea;
1200                         1u,                                                                                                             // deUint32                             clearValueCount;
1201                         &attachmentClearValue                                                                   // const VkClearValue*  pClearValues;
1202                 };
1203
1204                 const VkImageMemoryBarrier attachmentLayoutBarrier =
1205                 {
1206                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                 // VkStructureType                      sType;
1207                         DE_NULL,                                                                                // const void*                          pNext;
1208                         0u,                                                                                             // VkAccessFlags                        srcAccessMask;
1209                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                   // VkAccessFlags                        dstAccessMask;
1210                         VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                        oldLayout;
1211                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,               // VkImageLayout                        newLayout;
1212                         VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     srcQueueFamilyIndex;
1213                         VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     dstQueueFamilyIndex;
1214                         *m_colorImage,                                                                  // VkImage                                      image;
1215                         { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },  // VkImageSubresourceRange      subresourceRange;
1216                 };
1217
1218                 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1219
1220                 VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1221
1222                 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
1223                         0u, DE_NULL, 0u, DE_NULL, 1u, &attachmentLayoutBarrier);
1224
1225                 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1226
1227                 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
1228
1229                 std::vector<VkBuffer> vertexBuffers;
1230                 for (size_t bufferNdx = 0; bufferNdx < m_vertexBuffers.size(); bufferNdx++)
1231                         vertexBuffers.push_back(m_vertexBuffers[bufferNdx]);
1232
1233                 if (vertexBuffers.size() <= 1)
1234                 {
1235                         // One vertex buffer
1236                         vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, (deUint32)vertexBuffers.size(), vertexBuffers.data(), bindingOffsets.data());
1237                 }
1238                 else
1239                 {
1240                         // Smoke-test vkCmdBindVertexBuffers(..., startBinding, ... )
1241
1242                         const deUint32 firstHalfLength = (deUint32)vertexBuffers.size() / 2;
1243                         const deUint32 secondHalfLength = firstHalfLength + (deUint32)(vertexBuffers.size() % 2);
1244
1245                         // Bind first half of vertex buffers
1246                         vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, firstHalfLength, vertexBuffers.data(), bindingOffsets.data());
1247
1248                         // Bind second half of vertex buffers
1249                         vk.cmdBindVertexBuffers(*m_cmdBuffer, firstHalfLength, secondHalfLength,
1250                                                                         vertexBuffers.data() + firstHalfLength,
1251                                                                         bindingOffsets.data() + firstHalfLength);
1252                 }
1253
1254                 vk.cmdDraw(*m_cmdBuffer, 4, 2, 0, 0);
1255
1256                 vk.cmdEndRenderPass(*m_cmdBuffer);
1257                 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1258         }
1259
1260         // Create fence
1261         m_fence = createFence(vk, vkDevice);
1262 }
1263
1264 VertexInputInstance::~VertexInputInstance (void)
1265 {
1266         const DeviceInterface&          vk                      = m_context.getDeviceInterface();
1267         const VkDevice                          vkDevice        = m_context.getDevice();
1268
1269         for (size_t bufferNdx = 0; bufferNdx < m_vertexBuffers.size(); bufferNdx++)
1270                 vk.destroyBuffer(vkDevice, m_vertexBuffers[bufferNdx], DE_NULL);
1271
1272         for (size_t allocNdx = 0; allocNdx < m_vertexBufferAllocs.size(); allocNdx++)
1273                 delete m_vertexBufferAllocs[allocNdx];
1274 }
1275
1276 void VertexInputInstance::writeVertexInputData(deUint8* destPtr, const VkVertexInputBindingDescription& bindingDescription, const VkDeviceSize bindingOffset, const AttributeDescriptionList& attributes)
1277 {
1278         const deUint32 vertexCount = (bindingDescription.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) ? (4 * 2) : 2;
1279
1280         deUint8* destOffsetPtr = ((deUint8 *)destPtr) + bindingOffset;
1281         for (deUint32 vertexNdx = 0; vertexNdx < vertexCount; vertexNdx++)
1282         {
1283                 for (size_t attributeNdx = 0; attributeNdx < attributes.size(); attributeNdx++)
1284                 {
1285                         const VertexInputAttributeDescription& attribDesc = attributes[attributeNdx];
1286
1287                         // Only write vertex input data to bindings referenced by attribute descriptions
1288                         if (attribDesc.vkDescription.binding == bindingDescription.binding)
1289                         {
1290                                 writeVertexInputValue(destOffsetPtr + attribDesc.vkDescription.offset, attribDesc, vertexNdx);
1291                         }
1292                 }
1293                 destOffsetPtr += bindingDescription.stride;
1294         }
1295 }
1296
1297 void writeVertexInputValueSint (deUint8* destPtr, VkFormat format, int componentNdx, deInt32 value)
1298 {
1299         const deUint32  componentSize   = getVertexFormatComponentSize(format);
1300         deUint8*                destFormatPtr   = ((deUint8*)destPtr) + componentSize * componentNdx;
1301
1302         switch (componentSize)
1303         {
1304                 case 1:
1305                         *((deInt8*)destFormatPtr) = (deInt8)value;
1306                         break;
1307
1308                 case 2:
1309                         *((deInt16*)destFormatPtr) = (deInt16)value;
1310                         break;
1311
1312                 case 4:
1313                         *((deInt32*)destFormatPtr) = (deInt32)value;
1314                         break;
1315
1316                 default:
1317                         DE_ASSERT(false);
1318         }
1319 }
1320
1321 void writeVertexInputValueUint (deUint8* destPtr, VkFormat format, int componentNdx, deUint32 value)
1322 {
1323         const deUint32  componentSize   = getVertexFormatComponentSize(format);
1324         deUint8*                destFormatPtr   = ((deUint8*)destPtr) + componentSize * componentNdx;
1325
1326         switch (componentSize)
1327         {
1328                 case 1:
1329                         *((deUint8 *)destFormatPtr) = (deUint8)value;
1330                         break;
1331
1332                 case 2:
1333                         *((deUint16 *)destFormatPtr) = (deUint16)value;
1334                         break;
1335
1336                 case 4:
1337                         *((deUint32 *)destFormatPtr) = (deUint32)value;
1338                         break;
1339
1340                 default:
1341                         DE_ASSERT(false);
1342         }
1343 }
1344
1345 void writeVertexInputValueSfloat (deUint8* destPtr, VkFormat format, int componentNdx, float value)
1346 {
1347         const deUint32  componentSize   = getVertexFormatComponentSize(format);
1348         deUint8*                destFormatPtr   = ((deUint8*)destPtr) + componentSize * componentNdx;
1349
1350         switch (componentSize)
1351         {
1352                 case 2:
1353                 {
1354                         deFloat16 f16 = deFloat32To16(value);
1355                         deMemcpy(destFormatPtr, &f16, sizeof(f16));
1356                         break;
1357                 }
1358
1359                 case 4:
1360                         deMemcpy(destFormatPtr, &value, sizeof(value));
1361                         break;
1362
1363                 default:
1364                         DE_ASSERT(false);
1365         }
1366 }
1367
1368 void VertexInputInstance::writeVertexInputValue (deUint8* destPtr, const VertexInputAttributeDescription& attribute, int indexId)
1369 {
1370         const int               vertexInputCount        = VertexInputTest::s_glslTypeDescriptions[attribute.glslType].vertexInputCount;
1371         const int               componentCount          = VertexInputTest::s_glslTypeDescriptions[attribute.glslType].vertexInputComponentCount;
1372         const deUint32  totalComponentCount     = componentCount * vertexInputCount;
1373         const deUint32  vertexInputIndex        = indexId * totalComponentCount + attribute.vertexInputIndex * componentCount;
1374         const bool              hasBGROrder                     = isVertexFormatComponentOrderBGR(attribute.vkDescription.format);
1375         int                             swizzledNdx;
1376
1377         for (int componentNdx = 0; componentNdx < componentCount; componentNdx++)
1378         {
1379                 if (hasBGROrder)
1380                 {
1381                         if (componentNdx == 0)
1382                                 swizzledNdx = 2;
1383                         else if (componentNdx == 2)
1384                                 swizzledNdx = 0;
1385                         else
1386                                 swizzledNdx = componentNdx;
1387                 }
1388                 else
1389                         swizzledNdx = componentNdx;
1390
1391                 switch (attribute.glslType)
1392                 {
1393                         case VertexInputTest::GLSL_TYPE_INT:
1394                         case VertexInputTest::GLSL_TYPE_IVEC2:
1395                         case VertexInputTest::GLSL_TYPE_IVEC3:
1396                         case VertexInputTest::GLSL_TYPE_IVEC4:
1397                                 writeVertexInputValueSint(destPtr, attribute.vkDescription.format, componentNdx, -(deInt32)(vertexInputIndex + swizzledNdx));
1398                                 break;
1399
1400                         case VertexInputTest::GLSL_TYPE_UINT:
1401                         case VertexInputTest::GLSL_TYPE_UVEC2:
1402                         case VertexInputTest::GLSL_TYPE_UVEC3:
1403                         case VertexInputTest::GLSL_TYPE_UVEC4:
1404                                 writeVertexInputValueUint(destPtr, attribute.vkDescription.format, componentNdx, vertexInputIndex + swizzledNdx);
1405                                 break;
1406
1407                         case VertexInputTest::GLSL_TYPE_FLOAT:
1408                         case VertexInputTest::GLSL_TYPE_VEC2:
1409                         case VertexInputTest::GLSL_TYPE_VEC3:
1410                         case VertexInputTest::GLSL_TYPE_VEC4:
1411                         case VertexInputTest::GLSL_TYPE_MAT2:
1412                         case VertexInputTest::GLSL_TYPE_MAT3:
1413                         case VertexInputTest::GLSL_TYPE_MAT4:
1414                                 if (isVertexFormatSfloat(attribute.vkDescription.format))
1415                                 {
1416                                         writeVertexInputValueSfloat(destPtr, attribute.vkDescription.format, componentNdx, -(0.01f * (float)(vertexInputIndex + swizzledNdx)));
1417                                 }
1418                                 else if (isVertexFormatSscaled(attribute.vkDescription.format))
1419                                 {
1420                                         writeVertexInputValueSint(destPtr, attribute.vkDescription.format, componentNdx, -(deInt32)(vertexInputIndex + swizzledNdx));
1421                                 }
1422                                 else if (isVertexFormatUscaled(attribute.vkDescription.format) || isVertexFormatUnorm(attribute.vkDescription.format) || isVertexFormatSRGB(attribute.vkDescription.format))
1423                                 {
1424                                         writeVertexInputValueUint(destPtr, attribute.vkDescription.format, componentNdx, vertexInputIndex + swizzledNdx);
1425                                 }
1426                                 else if (isVertexFormatSnorm(attribute.vkDescription.format))
1427                                 {
1428                                         const deInt32 minIntValue = -((1 << (getVertexFormatComponentSize(attribute.vkDescription.format) * 8 - 1))) + 1;
1429                                         writeVertexInputValueSint(destPtr, attribute.vkDescription.format, componentNdx, minIntValue + (vertexInputIndex + swizzledNdx));
1430                                 }
1431                                 else
1432                                         DE_ASSERT(false);
1433                                 break;
1434
1435                         case VertexInputTest::GLSL_TYPE_DOUBLE:
1436                         case VertexInputTest::GLSL_TYPE_DVEC2:
1437                         case VertexInputTest::GLSL_TYPE_DVEC3:
1438                         case VertexInputTest::GLSL_TYPE_DVEC4:
1439                         case VertexInputTest::GLSL_TYPE_DMAT2:
1440                         case VertexInputTest::GLSL_TYPE_DMAT3:
1441                         case VertexInputTest::GLSL_TYPE_DMAT4:
1442                                 *(reinterpret_cast<double *>(destPtr) + componentNdx) = -0.01 * (vertexInputIndex + swizzledNdx);
1443
1444                                 break;
1445
1446                         default:
1447                                 DE_ASSERT(false);
1448                 }
1449         }
1450 }
1451
1452 tcu::TestStatus VertexInputInstance::iterate (void)
1453 {
1454         const DeviceInterface&          vk                      = m_context.getDeviceInterface();
1455         const VkDevice                          vkDevice        = m_context.getDevice();
1456         const VkQueue                           queue           = m_context.getUniversalQueue();
1457         const VkSubmitInfo                      submitInfo      =
1458         {
1459                 VK_STRUCTURE_TYPE_SUBMIT_INFO,  // VkStructureType                      sType;
1460                 DE_NULL,                                                // const void*                          pNext;
1461                 0u,                                                             // deUint32                                     waitSemaphoreCount;
1462                 DE_NULL,                                                // const VkSemaphore*           pWaitSemaphores;
1463                 (const VkPipelineStageFlags*)DE_NULL,
1464                 1u,                                                             // deUint32                                     commandBufferCount;
1465                 &m_cmdBuffer.get(),                             // const VkCommandBuffer*       pCommandBuffers;
1466                 0u,                                                             // deUint32                                     signalSemaphoreCount;
1467                 DE_NULL                                                 // const VkSemaphore*           pSignalSemaphores;
1468         };
1469
1470         VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
1471         VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
1472         VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
1473
1474         return verifyImage();
1475 }
1476
1477 bool VertexInputTest::isCompatibleType (VkFormat format, GlslType glslType)
1478 {
1479         const GlslTypeDescription glslTypeDesc = s_glslTypeDescriptions[glslType];
1480
1481         if ((deUint32)s_glslTypeDescriptions[glslType].vertexInputComponentCount == getVertexFormatComponentCount(format))
1482         {
1483                 switch (glslTypeDesc.basicType)
1484                 {
1485                         case GLSL_BASIC_TYPE_INT:
1486                                 return isVertexFormatSint(format);
1487
1488                         case GLSL_BASIC_TYPE_UINT:
1489                                 return isVertexFormatUint(format);
1490
1491                         case GLSL_BASIC_TYPE_FLOAT:
1492                                 return getVertexFormatComponentSize(format) <= 4 && (isVertexFormatSfloat(format) || isVertexFormatSnorm(format) || isVertexFormatUnorm(format) || isVertexFormatSscaled(format) || isVertexFormatUscaled(format) || isVertexFormatSRGB(format));
1493
1494                         case GLSL_BASIC_TYPE_DOUBLE:
1495                                 return isVertexFormatSfloat(format) && getVertexFormatComponentSize(format) == 8;
1496
1497                         default:
1498                                 DE_ASSERT(false);
1499                                 return false;
1500                 }
1501         }
1502         else
1503                 return false;
1504 }
1505
1506 tcu::TestStatus VertexInputInstance::verifyImage (void)
1507 {
1508         bool                                                    compareOk                       = false;
1509         const tcu::TextureFormat                tcuColorFormat          = mapVkFormat(m_colorFormat);
1510         tcu::TextureLevel                               reference                       (tcuColorFormat, m_renderSize.x(), m_renderSize.y());
1511         const tcu::PixelBufferAccess    refRedSubregion         (tcu::getSubregion(reference.getAccess(),
1512                                                                                                                                                    deRoundFloatToInt32((float)m_renderSize.x() * 0.0f),
1513                                                                                                                                                    deRoundFloatToInt32((float)m_renderSize.y() * 0.0f),
1514                                                                                                                                                    deRoundFloatToInt32((float)m_renderSize.x() * 0.5f),
1515                                                                                                                                                    deRoundFloatToInt32((float)m_renderSize.y() * 1.0f)));
1516         const tcu::PixelBufferAccess    refBlueSubregion        (tcu::getSubregion(reference.getAccess(),
1517                                                                                                                                                    deRoundFloatToInt32((float)m_renderSize.x() * 0.5f),
1518                                                                                                                                                    deRoundFloatToInt32((float)m_renderSize.y() * 0.0f),
1519                                                                                                                                                    deRoundFloatToInt32((float)m_renderSize.x() * 0.5f),
1520                                                                                                                                                    deRoundFloatToInt32((float)m_renderSize.y() * 1.0f)));
1521
1522         // Create reference image
1523         tcu::clear(reference.getAccess(), defaultClearColor(tcuColorFormat));
1524         tcu::clear(refRedSubregion, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1525         tcu::clear(refBlueSubregion, tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
1526
1527         // Compare result with reference image
1528         {
1529                 const DeviceInterface&                  vk                                      = m_context.getDeviceInterface();
1530                 const VkDevice                                  vkDevice                        = m_context.getDevice();
1531                 const VkQueue                                   queue                           = m_context.getUniversalQueue();
1532                 const deUint32                                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
1533                 SimpleAllocator                                 allocator                       (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1534                 de::MovePtr<tcu::TextureLevel>  result                          = readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize);
1535
1536                 compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
1537                                                                                                                           "IntImageCompare",
1538                                                                                                                           "Image comparison",
1539                                                                                                                           reference.getAccess(),
1540                                                                                                                           result->getAccess(),
1541                                                                                                                           tcu::UVec4(2, 2, 2, 2),
1542                                                                                                                           tcu::IVec3(1, 1, 0),
1543                                                                                                                           true,
1544                                                                                                                           tcu::COMPARE_LOG_RESULT);
1545         }
1546
1547         if (compareOk)
1548                 return tcu::TestStatus::pass("Result image matches reference");
1549         else
1550                 return tcu::TestStatus::fail("Image mismatch");
1551 }
1552
1553 std::string getAttributeInfoCaseName (const VertexInputTest::AttributeInfo& attributeInfo)
1554 {
1555         std::ostringstream      caseName;
1556         const std::string       formatName      = getFormatName(attributeInfo.vkType);
1557
1558         caseName << "as_" << de::toLower(formatName.substr(10)) << "_rate_";
1559
1560         if (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX)
1561                 caseName <<  "vertex";
1562         else
1563                 caseName <<  "instance";
1564
1565         return caseName.str();
1566 }
1567
1568 std::string getAttributeInfoDescription (const VertexInputTest::AttributeInfo& attributeInfo)
1569 {
1570         std::ostringstream caseDesc;
1571
1572         caseDesc << std::string(VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].name) << " from type " << getFormatName(attributeInfo.vkType) <<  " with ";
1573
1574         if (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX)
1575                 caseDesc <<  "vertex input rate ";
1576         else
1577                 caseDesc <<  "instance input rate ";
1578
1579         return caseDesc.str();
1580 }
1581
1582 std::string getAttributeInfosDescription (const std::vector<VertexInputTest::AttributeInfo>& attributeInfos)
1583 {
1584         std::ostringstream caseDesc;
1585
1586         caseDesc << "Uses vertex attributes:\n";
1587
1588         for (size_t attributeNdx = 0; attributeNdx < attributeInfos.size(); attributeNdx++)
1589                 caseDesc << "\t- " << getAttributeInfoDescription (attributeInfos[attributeNdx]) << "\n";
1590
1591         return caseDesc.str();
1592 }
1593
1594 struct CompatibleFormats
1595 {
1596         VertexInputTest::GlslType       glslType;
1597         std::vector<VkFormat>           compatibleVkFormats;
1598 };
1599
1600 void createSingleAttributeCases (tcu::TestCaseGroup* singleAttributeTests, VertexInputTest::GlslType glslType)
1601 {
1602         const VkFormat vertexFormats[] =
1603         {
1604                 // Required, unpacked
1605                 VK_FORMAT_R8_UNORM,
1606                 VK_FORMAT_R8_SNORM,
1607                 VK_FORMAT_R8_UINT,
1608                 VK_FORMAT_R8_SINT,
1609                 VK_FORMAT_R8G8_UNORM,
1610                 VK_FORMAT_R8G8_SNORM,
1611                 VK_FORMAT_R8G8_UINT,
1612                 VK_FORMAT_R8G8_SINT,
1613                 VK_FORMAT_R8G8B8A8_UNORM,
1614                 VK_FORMAT_R8G8B8A8_SNORM,
1615                 VK_FORMAT_R8G8B8A8_UINT,
1616                 VK_FORMAT_R8G8B8A8_SINT,
1617                 VK_FORMAT_B8G8R8A8_UNORM,
1618                 VK_FORMAT_R16_UNORM,
1619                 VK_FORMAT_R16_SNORM,
1620                 VK_FORMAT_R16_UINT,
1621                 VK_FORMAT_R16_SINT,
1622                 VK_FORMAT_R16_SFLOAT,
1623                 VK_FORMAT_R16G16_UNORM,
1624                 VK_FORMAT_R16G16_SNORM,
1625                 VK_FORMAT_R16G16_UINT,
1626                 VK_FORMAT_R16G16_SINT,
1627                 VK_FORMAT_R16G16_SFLOAT,
1628                 VK_FORMAT_R16G16B16A16_UNORM,
1629                 VK_FORMAT_R16G16B16A16_SNORM,
1630                 VK_FORMAT_R16G16B16A16_UINT,
1631                 VK_FORMAT_R16G16B16A16_SINT,
1632                 VK_FORMAT_R16G16B16A16_SFLOAT,
1633                 VK_FORMAT_R32_UINT,
1634                 VK_FORMAT_R32_SINT,
1635                 VK_FORMAT_R32_SFLOAT,
1636                 VK_FORMAT_R32G32_UINT,
1637                 VK_FORMAT_R32G32_SINT,
1638                 VK_FORMAT_R32G32_SFLOAT,
1639                 VK_FORMAT_R32G32B32_UINT,
1640                 VK_FORMAT_R32G32B32_SINT,
1641                 VK_FORMAT_R32G32B32_SFLOAT,
1642                 VK_FORMAT_R32G32B32A32_UINT,
1643                 VK_FORMAT_R32G32B32A32_SINT,
1644                 VK_FORMAT_R32G32B32A32_SFLOAT,
1645
1646                 // Scaled formats
1647                 VK_FORMAT_R8G8_USCALED,
1648                 VK_FORMAT_R8G8_SSCALED,
1649                 VK_FORMAT_R16_USCALED,
1650                 VK_FORMAT_R16_SSCALED,
1651                 VK_FORMAT_R8G8B8_USCALED,
1652                 VK_FORMAT_R8G8B8_SSCALED,
1653                 VK_FORMAT_B8G8R8_USCALED,
1654                 VK_FORMAT_B8G8R8_SSCALED,
1655                 VK_FORMAT_R8G8B8A8_USCALED,
1656                 VK_FORMAT_R8G8B8A8_SSCALED,
1657                 VK_FORMAT_B8G8R8A8_USCALED,
1658                 VK_FORMAT_B8G8R8A8_SSCALED,
1659                 VK_FORMAT_R16G16_USCALED,
1660                 VK_FORMAT_R16G16_SSCALED,
1661                 VK_FORMAT_R16G16B16_USCALED,
1662                 VK_FORMAT_R16G16B16_SSCALED,
1663                 VK_FORMAT_R16G16B16A16_USCALED,
1664                 VK_FORMAT_R16G16B16A16_SSCALED,
1665
1666                 // SRGB formats
1667                 VK_FORMAT_R8_SRGB,
1668                 VK_FORMAT_R8G8_SRGB,
1669                 VK_FORMAT_R8G8B8_SRGB,
1670                 VK_FORMAT_B8G8R8_SRGB,
1671                 VK_FORMAT_R8G8B8A8_SRGB,
1672                 VK_FORMAT_B8G8R8A8_SRGB,
1673
1674                 // Double formats
1675                 VK_FORMAT_R64_SFLOAT,
1676                 VK_FORMAT_R64G64_SFLOAT,
1677                 VK_FORMAT_R64G64B64_SFLOAT,
1678                 VK_FORMAT_R64G64B64A64_SFLOAT,
1679         };
1680
1681         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); formatNdx++)
1682         {
1683                 if (VertexInputTest::isCompatibleType(vertexFormats[formatNdx], glslType))
1684                 {
1685                         // Create test case for RATE_VERTEX
1686                         VertexInputTest::AttributeInfo attributeInfo;
1687                         attributeInfo.vkType = vertexFormats[formatNdx];
1688                         attributeInfo.glslType = glslType;
1689                         attributeInfo.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
1690
1691                         singleAttributeTests->addChild(new VertexInputTest(singleAttributeTests->getTestContext(),
1692                                                                                                                            getAttributeInfoCaseName(attributeInfo),
1693                                                                                                                            getAttributeInfoDescription(attributeInfo),
1694                                                                                                                            std::vector<VertexInputTest::AttributeInfo>(1, attributeInfo),
1695                                                                                                                            VertexInputTest::BINDING_MAPPING_ONE_TO_ONE,
1696                                                                                                                            VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED));
1697
1698                         // Create test case for RATE_INSTANCE
1699                         attributeInfo.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
1700
1701                         singleAttributeTests->addChild(new VertexInputTest(singleAttributeTests->getTestContext(),
1702                                                                                                                            getAttributeInfoCaseName(attributeInfo),
1703                                                                                                                            getAttributeInfoDescription(attributeInfo),
1704                                                                                                                            std::vector<VertexInputTest::AttributeInfo>(1, attributeInfo),
1705                                                                                                                            VertexInputTest::BINDING_MAPPING_ONE_TO_ONE,
1706                                                                                                                            VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED));
1707                 }
1708         }
1709 }
1710
1711 void createSingleAttributeTests (tcu::TestCaseGroup* singleAttributeTests)
1712 {
1713         for (int glslTypeNdx = 0; glslTypeNdx < VertexInputTest::GLSL_TYPE_COUNT; glslTypeNdx++)
1714         {
1715                 VertexInputTest::GlslType glslType = (VertexInputTest::GlslType)glslTypeNdx;
1716                 addTestGroup(singleAttributeTests, VertexInputTest::s_glslTypeDescriptions[glslType].name, "", createSingleAttributeCases, glslType);
1717         }
1718 }
1719
1720 // Create all unique GlslType combinations recursively
1721 void createMultipleAttributeCases (deUint32 depth, deUint32 firstNdx, CompatibleFormats* compatibleFormats, de::Random& randomFunc, tcu::TestCaseGroup& testGroup, VertexInputTest::BindingMapping bindingMapping, VertexInputTest::AttributeLayout attributeLayout, const std::vector<VertexInputTest::AttributeInfo>& attributeInfos = std::vector<VertexInputTest::AttributeInfo>(0))
1722 {
1723         tcu::TestContext& testCtx = testGroup.getTestContext();
1724
1725         // Exclude double values, which are not included in vertexFormats
1726         for (deUint32 currentNdx = firstNdx; currentNdx < VertexInputTest::GLSL_TYPE_DOUBLE - depth; currentNdx++)
1727         {
1728                 std::vector <VertexInputTest::AttributeInfo> newAttributeInfos = attributeInfos;
1729
1730                 {
1731                         VertexInputTest::AttributeInfo attributeInfo;
1732                         attributeInfo.glslType  = (VertexInputTest::GlslType)currentNdx;
1733                         attributeInfo.inputRate = (depth % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
1734                         attributeInfo.vkType    = VK_FORMAT_LAST;
1735
1736                         newAttributeInfos.push_back(attributeInfo);
1737                 }
1738
1739                 // Add test case
1740                 if (depth == 0)
1741                 {
1742                         // Select a random compatible format for each attribute
1743                         for (size_t i = 0; i < newAttributeInfos.size(); i++)
1744                         {
1745                                 const std::vector<VkFormat>& formats = compatibleFormats[newAttributeInfos[i].glslType].compatibleVkFormats;
1746                                 newAttributeInfos[i].vkType = formats[randomFunc.getUint32() % formats.size()];
1747                         }
1748
1749                         const std::string caseName = VertexInputTest::s_glslTypeDescriptions[currentNdx].name;
1750                         const std::string caseDesc = getAttributeInfosDescription(newAttributeInfos);
1751
1752                         testGroup.addChild(new VertexInputTest(testCtx, caseName, caseDesc, newAttributeInfos, bindingMapping, attributeLayout));
1753                 }
1754                 // Add test group
1755                 else
1756                 {
1757                         const std::string                               name                    = VertexInputTest::s_glslTypeDescriptions[currentNdx].name;
1758                         de::MovePtr<tcu::TestCaseGroup> newTestGroup    (new tcu::TestCaseGroup(testCtx, name.c_str(), ""));
1759
1760                         createMultipleAttributeCases(depth - 1u, currentNdx + 1u, compatibleFormats, randomFunc, *newTestGroup, bindingMapping, attributeLayout, newAttributeInfos);
1761                         testGroup.addChild(newTestGroup.release());
1762                 }
1763         }
1764 }
1765
1766 void createMultipleAttributeTests (tcu::TestCaseGroup* multipleAttributeTests)
1767 {
1768         // Required vertex formats, unpacked
1769         const VkFormat vertexFormats[] =
1770         {
1771                 VK_FORMAT_R8_UNORM,
1772                 VK_FORMAT_R8_SNORM,
1773                 VK_FORMAT_R8_UINT,
1774                 VK_FORMAT_R8_SINT,
1775                 VK_FORMAT_R8G8_UNORM,
1776                 VK_FORMAT_R8G8_SNORM,
1777                 VK_FORMAT_R8G8_UINT,
1778                 VK_FORMAT_R8G8_SINT,
1779                 VK_FORMAT_R8G8B8A8_UNORM,
1780                 VK_FORMAT_R8G8B8A8_SNORM,
1781                 VK_FORMAT_R8G8B8A8_UINT,
1782                 VK_FORMAT_R8G8B8A8_SINT,
1783                 VK_FORMAT_B8G8R8A8_UNORM,
1784                 VK_FORMAT_R16_UNORM,
1785                 VK_FORMAT_R16_SNORM,
1786                 VK_FORMAT_R16_UINT,
1787                 VK_FORMAT_R16_SINT,
1788                 VK_FORMAT_R16_SFLOAT,
1789                 VK_FORMAT_R16G16_UNORM,
1790                 VK_FORMAT_R16G16_SNORM,
1791                 VK_FORMAT_R16G16_UINT,
1792                 VK_FORMAT_R16G16_SINT,
1793                 VK_FORMAT_R16G16_SFLOAT,
1794                 VK_FORMAT_R16G16B16A16_UNORM,
1795                 VK_FORMAT_R16G16B16A16_SNORM,
1796                 VK_FORMAT_R16G16B16A16_UINT,
1797                 VK_FORMAT_R16G16B16A16_SINT,
1798                 VK_FORMAT_R16G16B16A16_SFLOAT,
1799                 VK_FORMAT_R32_UINT,
1800                 VK_FORMAT_R32_SINT,
1801                 VK_FORMAT_R32_SFLOAT,
1802                 VK_FORMAT_R32G32_UINT,
1803                 VK_FORMAT_R32G32_SINT,
1804                 VK_FORMAT_R32G32_SFLOAT,
1805                 VK_FORMAT_R32G32B32_UINT,
1806                 VK_FORMAT_R32G32B32_SINT,
1807                 VK_FORMAT_R32G32B32_SFLOAT,
1808                 VK_FORMAT_R32G32B32A32_UINT,
1809                 VK_FORMAT_R32G32B32A32_SINT,
1810                 VK_FORMAT_R32G32B32A32_SFLOAT
1811         };
1812
1813         // Find compatible VK formats for each GLSL vertex type
1814         CompatibleFormats compatibleFormats[VertexInputTest::GLSL_TYPE_COUNT];
1815         {
1816                 for (int glslTypeNdx = 0; glslTypeNdx < VertexInputTest::GLSL_TYPE_COUNT; glslTypeNdx++)
1817                 {
1818                         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); formatNdx++)
1819                         {
1820                                 if (VertexInputTest::isCompatibleType(vertexFormats[formatNdx], (VertexInputTest::GlslType)glslTypeNdx))
1821                                         compatibleFormats[glslTypeNdx].compatibleVkFormats.push_back(vertexFormats[formatNdx]);
1822                         }
1823                 }
1824         }
1825
1826         de::Random                      randomFunc(102030);
1827         tcu::TestContext&                               testCtx = multipleAttributeTests->getTestContext();
1828         de::MovePtr<tcu::TestCaseGroup> oneToOneAttributeTests(new tcu::TestCaseGroup(testCtx, "attributes", ""));
1829         de::MovePtr<tcu::TestCaseGroup> oneToManyAttributeTests(new tcu::TestCaseGroup(testCtx, "attributes", ""));
1830         de::MovePtr<tcu::TestCaseGroup> oneToManySequentialAttributeTests(new tcu::TestCaseGroup(testCtx, "attributes_sequential", ""));
1831
1832         createMultipleAttributeCases(2u, 0u, compatibleFormats, randomFunc, *oneToOneAttributeTests,                    VertexInputTest::BINDING_MAPPING_ONE_TO_ONE,    VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED);
1833         createMultipleAttributeCases(2u, 0u, compatibleFormats, randomFunc, *oneToManyAttributeTests,                   VertexInputTest::BINDING_MAPPING_ONE_TO_MANY,   VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED);
1834         createMultipleAttributeCases(2u, 0u, compatibleFormats, randomFunc, *oneToManySequentialAttributeTests, VertexInputTest::BINDING_MAPPING_ONE_TO_MANY,   VertexInputTest::ATTRIBUTE_LAYOUT_SEQUENTIAL);
1835
1836         de::MovePtr<tcu::TestCaseGroup> bindingOneToOneTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_one", "Each attribute uses a unique binding"));
1837         bindingOneToOneTests->addChild(oneToOneAttributeTests.release());
1838         multipleAttributeTests->addChild(bindingOneToOneTests.release());
1839
1840         de::MovePtr<tcu::TestCaseGroup> bindingOneToManyTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_many", "Attributes share the same binding"));
1841         bindingOneToManyTests->addChild(oneToManyAttributeTests.release());
1842         bindingOneToManyTests->addChild(oneToManySequentialAttributeTests.release());
1843         multipleAttributeTests->addChild(bindingOneToManyTests.release());
1844 }
1845
1846 void createMaxAttributeTests (tcu::TestCaseGroup* maxAttributeTests)
1847 {
1848         // Required vertex formats, unpacked
1849         const VkFormat                                  vertexFormats[]         =
1850         {
1851                 VK_FORMAT_R8_UNORM,
1852                 VK_FORMAT_R8_SNORM,
1853                 VK_FORMAT_R8_UINT,
1854                 VK_FORMAT_R8_SINT,
1855                 VK_FORMAT_R8G8_UNORM,
1856                 VK_FORMAT_R8G8_SNORM,
1857                 VK_FORMAT_R8G8_UINT,
1858                 VK_FORMAT_R8G8_SINT,
1859                 VK_FORMAT_R8G8B8A8_UNORM,
1860                 VK_FORMAT_R8G8B8A8_SNORM,
1861                 VK_FORMAT_R8G8B8A8_UINT,
1862                 VK_FORMAT_R8G8B8A8_SINT,
1863                 VK_FORMAT_B8G8R8A8_UNORM,
1864                 VK_FORMAT_R16_UNORM,
1865                 VK_FORMAT_R16_SNORM,
1866                 VK_FORMAT_R16_UINT,
1867                 VK_FORMAT_R16_SINT,
1868                 VK_FORMAT_R16_SFLOAT,
1869                 VK_FORMAT_R16G16_UNORM,
1870                 VK_FORMAT_R16G16_SNORM,
1871                 VK_FORMAT_R16G16_UINT,
1872                 VK_FORMAT_R16G16_SINT,
1873                 VK_FORMAT_R16G16_SFLOAT,
1874                 VK_FORMAT_R16G16B16A16_UNORM,
1875                 VK_FORMAT_R16G16B16A16_SNORM,
1876                 VK_FORMAT_R16G16B16A16_UINT,
1877                 VK_FORMAT_R16G16B16A16_SINT,
1878                 VK_FORMAT_R16G16B16A16_SFLOAT,
1879                 VK_FORMAT_R32_UINT,
1880                 VK_FORMAT_R32_SINT,
1881                 VK_FORMAT_R32_SFLOAT,
1882                 VK_FORMAT_R32G32_UINT,
1883                 VK_FORMAT_R32G32_SINT,
1884                 VK_FORMAT_R32G32_SFLOAT,
1885                 VK_FORMAT_R32G32B32_UINT,
1886                 VK_FORMAT_R32G32B32_SINT,
1887                 VK_FORMAT_R32G32B32_SFLOAT,
1888                 VK_FORMAT_R32G32B32A32_UINT,
1889                 VK_FORMAT_R32G32B32A32_SINT,
1890                 VK_FORMAT_R32G32B32A32_SFLOAT
1891         };
1892
1893         // VkPhysicalDeviceLimits::maxVertexInputAttributes is used when attributeCount is 0
1894         const deUint32                                  attributeCount[]        = { 16, 32, 64, 128, 0 };
1895         tcu::TestContext&                               testCtx                         (maxAttributeTests->getTestContext());
1896         de::Random                                              randomFunc                      (132030);
1897
1898         // Find compatible VK formats for each GLSL vertex type
1899         CompatibleFormats compatibleFormats[VertexInputTest::GLSL_TYPE_COUNT];
1900         {
1901                 for (int glslTypeNdx = 0; glslTypeNdx < VertexInputTest::GLSL_TYPE_COUNT; glslTypeNdx++)
1902                 {
1903                         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); formatNdx++)
1904                         {
1905                                 if (VertexInputTest::isCompatibleType(vertexFormats[formatNdx], (VertexInputTest::GlslType)glslTypeNdx))
1906                                         compatibleFormats[glslTypeNdx].compatibleVkFormats.push_back(vertexFormats[formatNdx]);
1907                         }
1908                 }
1909         }
1910
1911         for (deUint32 attributeCountNdx = 0; attributeCountNdx < DE_LENGTH_OF_ARRAY(attributeCount); attributeCountNdx++)
1912         {
1913                 const std::string                                                       groupName = (attributeCount[attributeCountNdx] == 0 ? "query_max" : de::toString(attributeCount[attributeCountNdx])) + "_attributes";
1914                 const std::string                                                       groupDesc = de::toString(attributeCount[attributeCountNdx]) + " vertex input attributes";
1915
1916                 de::MovePtr<tcu::TestCaseGroup>                         numAttributeTests(new tcu::TestCaseGroup(testCtx, groupName.c_str(), groupDesc.c_str()));
1917                 de::MovePtr<tcu::TestCaseGroup>                         bindingOneToOneTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_one", "Each attribute uses a unique binding"));
1918                 de::MovePtr<tcu::TestCaseGroup>                         bindingOneToManyTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_many", "Attributes share the same binding"));
1919
1920                 std::vector<VertexInputTest::AttributeInfo>     attributeInfos(attributeCount[attributeCountNdx]);
1921
1922                 for (deUint32 attributeNdx = 0; attributeNdx < attributeCount[attributeCountNdx]; attributeNdx++)
1923                 {
1924                         // Use random glslTypes, each consuming one attribute location
1925                         const VertexInputTest::GlslType glslType        = (VertexInputTest::GlslType)(randomFunc.getUint32() % VertexInputTest::GLSL_TYPE_MAT2);
1926                         const std::vector<VkFormat>&    formats         = compatibleFormats[glslType].compatibleVkFormats;
1927                         const VkFormat                                  format          = formats[randomFunc.getUint32() % formats.size()];
1928
1929                         attributeInfos[attributeNdx].glslType           = glslType;
1930                         attributeInfos[attributeNdx].inputRate          = ((attributeCountNdx + attributeNdx) % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
1931                         attributeInfos[attributeNdx].vkType                     = format;
1932                 }
1933
1934                 bindingOneToOneTests->addChild(new VertexInputTest(testCtx, "interleaved", "Interleaved attribute layout", attributeInfos, VertexInputTest::BINDING_MAPPING_ONE_TO_ONE, VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED));
1935                 bindingOneToManyTests->addChild(new VertexInputTest(testCtx, "interleaved", "Interleaved attribute layout", attributeInfos, VertexInputTest::BINDING_MAPPING_ONE_TO_MANY, VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED));
1936                 bindingOneToManyTests->addChild(new VertexInputTest(testCtx, "sequential", "Sequential attribute layout", attributeInfos, VertexInputTest::BINDING_MAPPING_ONE_TO_MANY, VertexInputTest::ATTRIBUTE_LAYOUT_SEQUENTIAL));
1937
1938                 numAttributeTests->addChild(bindingOneToOneTests.release());
1939                 numAttributeTests->addChild(bindingOneToManyTests.release());
1940                 maxAttributeTests->addChild(numAttributeTests.release());
1941         }
1942 }
1943
1944 } // anonymous
1945
1946 void createVertexInputTests (tcu::TestCaseGroup* vertexInputTests)
1947 {
1948         addTestGroup(vertexInputTests, "single_attribute", "Uses one attribute", createSingleAttributeTests);
1949         addTestGroup(vertexInputTests, "multiple_attributes", "Uses more than one attribute", createMultipleAttributeTests);
1950         addTestGroup(vertexInputTests, "max_attributes", "Implementations can use as many vertex input attributes as they advertise", createMaxAttributeTests);
1951 }
1952
1953 } // pipeline
1954 } // vkt