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