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