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