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