Merge pull request #276 from Ella-0/master
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / pipeline / vktPipelineSpecConstantTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Pipeline specialization constants tests
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktPipelineSpecConstantTests.hpp"
25 #include "vktTestCase.hpp"
26 #include "vktPipelineSpecConstantUtil.hpp"
27 #include "vktPipelineMakeUtil.hpp"
28
29 #include "tcuTestLog.hpp"
30 #include "tcuTexture.hpp"
31 #include "tcuFormatUtil.hpp"
32 #include "tcuFloat.hpp"
33
34 #include "gluShaderUtil.hpp"
35
36 #include "vkBuilderUtil.hpp"
37 #include "vkPrograms.hpp"
38 #include "vkRefUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkImageUtil.hpp"
41 #include "vkBarrierUtil.hpp"
42 #include "vkCmdUtil.hpp"
43 #include "vkObjUtil.hpp"
44
45 #include "deUniquePtr.hpp"
46 #include "deStringUtil.hpp"
47
48 #include <limits>
49
50 namespace vkt
51 {
52 namespace pipeline
53 {
54
55 using namespace vk;
56
57 namespace
58 {
59
60 static const char* const s_perVertexBlock =     "gl_PerVertex {\n"
61                                                                                         "    vec4 gl_Position;\n"
62                                                                                         "}";
63
64 //! Raw memory storage for values used in test cases.
65 //! We use it to simplify test case definitions where different types are expected in the result.
66 class GenericValue
67 {
68 public:
69         GenericValue (void) { clear(); }
70
71         //! Copy up to 'size' bytes of 'data'.
72         GenericValue (const void* data, const deUint32 size)
73         {
74                 DE_ASSERT(size <= sizeof(m_data));
75                 clear();
76                 deMemcpy(&m_data, data, size);
77         }
78
79 private:
80         deUint64 m_data;
81
82         void clear (void) { m_data = 0; }
83 };
84
85 inline GenericValue makeValueBool32      (const bool a)                 { return GenericValue(&a, sizeof(a)); }
86 inline GenericValue makeValueInt8    (const deInt8 a)           { return GenericValue(&a, sizeof(a)); }
87 inline GenericValue makeValueUint8   (const deUint8 a)          { return GenericValue(&a, sizeof(a)); }
88 inline GenericValue makeValueInt16   (const deInt16 a)          { return GenericValue(&a, sizeof(a)); }
89 inline GenericValue makeValueUint16  (const deUint16 a)         { return GenericValue(&a, sizeof(a)); }
90 inline GenericValue makeValueInt32       (const deInt32 a)              { return GenericValue(&a, sizeof(a)); }
91 inline GenericValue makeValueUint32      (const deUint32 a)             { return GenericValue(&a, sizeof(a)); }
92 inline GenericValue makeValueInt64   (const deInt64 a)          { return GenericValue(&a, sizeof(a)); }
93 inline GenericValue makeValueUint64  (const deUint64 a)         { return GenericValue(&a, sizeof(a)); }
94 inline GenericValue makeValueFloat16 (const tcu::Float16 a)     { return GenericValue(&a, sizeof(a)); }
95 inline GenericValue makeValueFloat32 (const float a)            { return GenericValue(&a, sizeof(a)); }
96 inline GenericValue makeValueFloat64 (const double a)           { return GenericValue(&a, sizeof(a)); }
97
98 struct SpecConstant
99 {
100         deUint32                        specID;                         //!< specialization constant ID
101         std::string                     declarationCode;        //!< syntax to declare the constant, use ${ID} as an ID placeholder
102         deUint32                        size;                           //!< data size on the host, 0 = no specialized value
103         GenericValue            specValue;                      //!< specialized value passed by the API
104         bool                            forceUse;                       //!< always include a VkSpecializationMapEntry for this spec constant
105
106         SpecConstant (const deUint32 specID_, const std::string declarationCode_)
107                 : specID                        (specID_)
108                 , declarationCode       (declarationCode_)
109                 , size                          (0)
110                 , specValue                     ()
111                 , forceUse                      (false)
112         {
113         }
114
115         SpecConstant (const deUint32 specID_, const std::string declarationCode_, const deUint32 size_, const GenericValue specValue_, bool forceUse_ = false)
116                 : specID                        (specID_)
117                 , declarationCode       (declarationCode_)
118                 , size                          (size_)
119                 , specValue                     (specValue_)
120                 , forceUse                      (forceUse_)
121         {
122         }
123 };
124
125 //! Useful when referring to a value in a buffer (i.e. check expected values in SSBO).
126 struct OffsetValue
127 {
128         deUint32                size;           //!< data size in the buffer (up to sizeof(value))
129         deUint32                offset;         //!< offset into the buffer
130         GenericValue    value;          //!< value expected to be there
131
132         OffsetValue (const deUint32 size_, const deUint32 offset_, const GenericValue value_)
133                 : size          (size_)
134                 , offset        (offset_)
135                 , value         (value_)
136         {}
137 };
138
139 //! Get the integer value of 'size' bytes at 'memory' location.
140 deUint64 memoryAsInteger (const void* memory, const deUint32 size)
141 {
142         DE_ASSERT(size <= sizeof(deUint64));
143         deUint64 value = 0;
144         deMemcpy(&value, memory, size);
145         return value;
146 }
147
148 inline std::string memoryAsHexString (const void* memory, const deUint32 size)
149 {
150         const deUint8* memoryBytePtr = static_cast<const deUint8*>(memory);
151         return de::toString(tcu::formatArray(tcu::Format::HexIterator<deUint8>(memoryBytePtr), tcu::Format::HexIterator<deUint8>(memoryBytePtr + size)));
152 }
153
154 void logValueMismatch (tcu::TestLog& log, const void* expected, const void* actual, const deUint32 offset, const deUint32 size)
155 {
156         const bool canDisplayValue = (size <= sizeof(deUint64));
157         log << tcu::TestLog::Message
158                 << "Comparison failed for value at offset " << de::toString(offset) << ": expected "
159                 << (canDisplayValue ? de::toString(memoryAsInteger(expected, size)) + " " : "") << memoryAsHexString(expected, size) << " but got "
160                 << (canDisplayValue ? de::toString(memoryAsInteger(actual, size)) + " " : "") << memoryAsHexString(actual, size)
161                 << tcu::TestLog::EndMessage;
162 }
163
164 //! Check if expected values exist in the memory.
165 bool verifyValues (tcu::TestLog& log, const void* memory, const std::vector<OffsetValue>& expectedValues)
166 {
167         bool ok = true;
168         log << tcu::TestLog::Section("compare", "Verify result values");
169
170         for (std::vector<OffsetValue>::const_iterator it = expectedValues.begin(); it < expectedValues.end(); ++it)
171         {
172                 const char* const valuePtr = static_cast<const char*>(memory) + it->offset;
173                 if (deMemCmp(valuePtr, &it->value, it->size) != 0)
174                 {
175                         ok = false;
176                         logValueMismatch(log, &it->value, valuePtr, it->offset, it->size);
177                 }
178         }
179
180         if (ok)
181                 log << tcu::TestLog::Message << "All OK" << tcu::TestLog::EndMessage;
182
183         log << tcu::TestLog::EndSection;
184         return ok;
185 }
186
187 //! Bundles together common test case parameters.
188 struct CaseDefinition
189 {
190         std::string                                     name;                           //!< Test case name
191         std::vector<SpecConstant>       specConstants;          //!< list of specialization constants to declare
192         VkDeviceSize                            ssboSize;                       //!< required ssbo size in bytes
193         std::string                                     ssboCode;                       //!< ssbo member definitions
194         std::string                                     globalCode;                     //!< generic shader code outside the main function (e.g. declarations)
195         std::string                                     mainCode;                       //!< generic shader code to execute in main (e.g. assignments)
196         std::vector<OffsetValue>        expectedValues;         //!< list of values to check inside the ssbo buffer
197         FeatureFlags                            requirements;           //!< features the implementation must support to allow this test to run
198         bool                                            packData;                       //!< whether to tightly pack specialization constant data or not
199 };
200
201 //! Manages Vulkan structures to pass specialization data.
202 class Specialization
203 {
204 public:
205                                                                                         Specialization (const std::vector<SpecConstant>& specConstants, bool packData);
206
207         //! Can return NULL if nothing is specialized
208         const VkSpecializationInfo*                             getSpecializationInfo (void) const { return m_entries.size() > 0 ? &m_specialization : DE_NULL; }
209
210 private:
211         std::vector<deUint8>                                    m_data;
212         std::vector<VkSpecializationMapEntry>   m_entries;
213         VkSpecializationInfo                                    m_specialization;
214 };
215
216 Specialization::Specialization (const std::vector<SpecConstant>& specConstants, bool packData)
217 {
218         const auto kGenericValueSize = static_cast<deUint32>(sizeof(GenericValue));
219
220         // Reserve memory for the worst case in m_data.
221         m_data.resize(specConstants.size() * kGenericValueSize, std::numeric_limits<deUint8>::max());
222         m_entries.reserve(specConstants.size());
223
224         deUint32 offset = 0u;
225         for (const auto& sc : specConstants)
226         {
227                 if (sc.size != 0u || sc.forceUse)
228                 {
229                         if (sc.size > 0u)
230                                 deMemcpy(&m_data[offset], &sc.specValue, sc.size);
231                         m_entries.push_back(makeSpecializationMapEntry(sc.specID, offset, sc.size));
232                         offset += (packData ? sc.size : kGenericValueSize);
233                 }
234         }
235
236         if (m_entries.size() > 0)
237         {
238                 m_specialization.mapEntryCount = static_cast<deUint32>(m_entries.size());
239                 m_specialization.pMapEntries   = m_entries.data();
240                 m_specialization.dataSize          = static_cast<deUintptr>(offset);
241                 m_specialization.pData             = m_data.data();
242         }
243         else
244                 deMemset(&m_specialization, 0, sizeof(m_specialization));
245 }
246
247 class SpecConstantTest : public TestCase
248 {
249 public:
250                                                                 SpecConstantTest        (tcu::TestContext&                              testCtx,
251                                                                                                          const VkShaderStageFlagBits    stage,          //!< which shader stage is tested
252                                                                                                          const CaseDefinition&                  caseDef);
253
254         void                                            initPrograms            (SourceCollections&             programCollection) const;
255         TestInstance*                           createInstance          (Context&                               context) const;
256         virtual void                            checkSupport            (Context&                               context) const;
257
258 private:
259         const VkShaderStageFlagBits     m_stage;
260         const CaseDefinition            m_caseDef;
261 };
262
263 SpecConstantTest::SpecConstantTest (tcu::TestContext&                   testCtx,
264                                                                         const VkShaderStageFlagBits     stage,
265                                                                         const CaseDefinition&           caseDef)
266         : TestCase      (testCtx, caseDef.name, "")
267         , m_stage       (stage)
268         , m_caseDef     (caseDef)
269 {
270 }
271
272 //! Build a string that declares all specialization constants, replacing ${ID} with proper ID numbers.
273 std::string generateSpecConstantCode (const std::vector<SpecConstant>& specConstants)
274 {
275         std::ostringstream code;
276         for (std::vector<SpecConstant>::const_iterator it = specConstants.begin(); it != specConstants.end(); ++it)
277         {
278                 std::string decl = it->declarationCode;
279                 const std::string::size_type pos = decl.find("${ID}");
280                 if (pos != std::string::npos)
281                         decl.replace(pos, 5, de::toString(it->specID));
282                 code << decl << "\n";
283         }
284         code << "\n";
285         return code.str();
286 }
287
288 std::string generateSSBOCode (const std::string& memberDeclarations)
289 {
290         std::ostringstream code;
291         code << "layout (set = 0, binding = 0, std430) writeonly buffer Output {\n"
292                  << memberDeclarations
293                  << "} sb_out;\n"
294                  << "\n";
295         return code.str();
296 }
297
298 void SpecConstantTest::initPrograms (SourceCollections& programCollection) const
299 {
300         // Always add vertex and fragment to graphics stages
301         VkShaderStageFlags requiredStages = m_stage;
302
303         if (requiredStages & VK_SHADER_STAGE_ALL_GRAPHICS)
304                 requiredStages |= VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
305
306         if (requiredStages & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
307                 requiredStages |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
308
309         // Either graphics or compute must be defined, but not both
310         DE_ASSERT(((requiredStages & VK_SHADER_STAGE_ALL_GRAPHICS) != 0) != ((requiredStages & VK_SHADER_STAGE_COMPUTE_BIT) != 0));
311
312         // Extensions needed for some tests.
313         std::ostringstream extStream;
314         if (m_caseDef.requirements & FEATURE_SHADER_INT_64)
315                 extStream << "#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require\n";
316         if (m_caseDef.requirements & FEATURE_SHADER_INT_16)
317                 extStream << "#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require\n";
318         if (m_caseDef.requirements & FEATURE_SHADER_INT_8)
319                 extStream << "#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require\n";
320         if (m_caseDef.requirements & FEATURE_SHADER_FLOAT_16)
321                 extStream << "#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require\n";
322         const std::string extensions = extStream.str();
323
324         // This makes glslang avoid the UniformAndStorage* capabilities.
325         const vk::ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, SPIRV_VERSION_1_3, 0u);
326
327         if (requiredStages & VK_SHADER_STAGE_VERTEX_BIT)
328         {
329                 const bool useSpecConst = (m_stage == VK_SHADER_STAGE_VERTEX_BIT);
330                 std::ostringstream src;
331                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
332                         << extensions
333                         << "layout(location = 0) in highp vec4 position;\n"
334                         << "\n"
335                         << "out " << s_perVertexBlock << ";\n"
336                         << "\n"
337                         << (useSpecConst ? generateSpecConstantCode(m_caseDef.specConstants) : "")
338                         << (useSpecConst ? generateSSBOCode(m_caseDef.ssboCode) : "")
339                         << (useSpecConst ? m_caseDef.globalCode + "\n" : "")
340                         << "void main (void)\n"
341                         << "{\n"
342                         << (useSpecConst ? m_caseDef.mainCode + "\n" : "")
343                         << "    gl_Position = position;\n"
344                         << "}\n";
345
346                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()) << buildOptions;
347         }
348
349         if (requiredStages & VK_SHADER_STAGE_FRAGMENT_BIT)
350         {
351                 const bool useSpecConst = (m_stage == VK_SHADER_STAGE_FRAGMENT_BIT);
352                 std::ostringstream src;
353                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
354                         << extensions
355                         << "layout(location = 0) out highp vec4 fragColor;\n"
356                         << "\n"
357                         << (useSpecConst ? generateSpecConstantCode(m_caseDef.specConstants) : "")
358                         << (useSpecConst ? generateSSBOCode(m_caseDef.ssboCode) : "")
359                         << (useSpecConst ? m_caseDef.globalCode + "\n" : "")
360                         << "void main (void)\n"
361                         << "{\n"
362                         << (useSpecConst ? m_caseDef.mainCode + "\n" : "")
363                         << "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
364                         << "}\n";
365
366                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()) << buildOptions;
367         }
368
369         if (requiredStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
370         {
371                 const bool useSpecConst = (m_stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
372                 std::ostringstream src;
373                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
374                         << extensions
375                         << "layout(vertices = 3) out;\n"
376                         << "\n"
377                         << "in " << s_perVertexBlock << " gl_in[gl_MaxPatchVertices];\n"
378                         << "\n"
379                         << "out " << s_perVertexBlock << " gl_out[];\n"
380                         << "\n"
381                         << (useSpecConst ? generateSpecConstantCode(m_caseDef.specConstants) : "")
382                         << (useSpecConst ? generateSSBOCode(m_caseDef.ssboCode) : "")
383                         << (useSpecConst ? m_caseDef.globalCode + "\n" : "")
384                         << "void main (void)\n"
385                         << "{\n"
386                         << (useSpecConst ? m_caseDef.mainCode + "\n" : "")
387                         << "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
388                         << "    if (gl_InvocationID == 0)\n"
389                         << "    {\n"
390                         << "        gl_TessLevelInner[0] = 3;\n"
391                         << "        gl_TessLevelOuter[0] = 2;\n"
392                         << "        gl_TessLevelOuter[1] = 2;\n"
393                         << "        gl_TessLevelOuter[2] = 2;\n"
394                         << "    }\n"
395                         << "}\n";
396
397                 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str()) << buildOptions;
398         }
399
400         if (requiredStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
401         {
402                 const bool useSpecConst = (m_stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
403                 std::ostringstream src;
404                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
405                         << extensions
406                         << "layout(triangles, equal_spacing, ccw) in;\n"
407                         << "\n"
408                         << "in " << s_perVertexBlock << " gl_in[gl_MaxPatchVertices];\n"
409                         << "\n"
410                         << "out " << s_perVertexBlock << ";\n"
411                         << "\n"
412                         << (useSpecConst ? generateSpecConstantCode(m_caseDef.specConstants) : "")
413                         << (useSpecConst ? generateSSBOCode(m_caseDef.ssboCode) : "")
414                         << (useSpecConst ? m_caseDef.globalCode + "\n" : "")
415                         << "void main (void)\n"
416                         << "{\n"
417                         << (useSpecConst ? m_caseDef.mainCode + "\n" : "")
418                         << "    vec3 p0 = gl_TessCoord.x * gl_in[0].gl_Position.xyz;\n"
419                         << "    vec3 p1 = gl_TessCoord.y * gl_in[1].gl_Position.xyz;\n"
420                         << "    vec3 p2 = gl_TessCoord.z * gl_in[2].gl_Position.xyz;\n"
421                         << "    gl_Position = vec4(p0 + p1 + p2, 1.0);\n"
422                         << "}\n";
423
424                 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str()) << buildOptions;
425         }
426
427         if (requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT)
428         {
429                 const bool useSpecConst = (m_stage == VK_SHADER_STAGE_GEOMETRY_BIT);
430                 std::ostringstream src;
431                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
432                         << extensions
433                         << "layout(triangles) in;\n"
434                         << "layout(triangle_strip, max_vertices = 3) out;\n"
435                         << "\n"
436                         << "in " << s_perVertexBlock << " gl_in[];\n"
437                         << "\n"
438                         << "out " << s_perVertexBlock << ";\n"
439                         << "\n"
440                         << (useSpecConst ? generateSpecConstantCode(m_caseDef.specConstants) : "")
441                         << (useSpecConst ? generateSSBOCode(m_caseDef.ssboCode) : "")
442                         << (useSpecConst ? m_caseDef.globalCode + "\n" : "")
443                         << "void main (void)\n"
444                         << "{\n"
445                         << (useSpecConst ? m_caseDef.mainCode + "\n" : "")
446                         << "    gl_Position = gl_in[0].gl_Position;\n"
447                         << "    EmitVertex();\n"
448                         << "\n"
449                         << "    gl_Position = gl_in[1].gl_Position;\n"
450                         << "    EmitVertex();\n"
451                         << "\n"
452                         << "    gl_Position = gl_in[2].gl_Position;\n"
453                         << "    EmitVertex();\n"
454                         << "\n"
455                         << "    EndPrimitive();\n"
456                         << "}\n";
457
458                 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str()) << buildOptions;
459         }
460
461         if (requiredStages & VK_SHADER_STAGE_COMPUTE_BIT)
462         {
463                 std::ostringstream src;
464                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
465                         << extensions
466                         // Don't define work group size, use the default or specialization constants
467                         << "\n"
468                         << generateSpecConstantCode(m_caseDef.specConstants)
469                         << generateSSBOCode(m_caseDef.ssboCode)
470                         << m_caseDef.globalCode + "\n"
471                         << "void main (void)\n"
472                         << "{\n"
473                         << m_caseDef.mainCode
474                         << "}\n";
475
476                 programCollection.glslSources.add("comp") << glu::ComputeSource(src.str()) << buildOptions;
477         }
478 }
479
480 class ComputeTestInstance : public TestInstance
481 {
482 public:
483                                                                         ComputeTestInstance     (Context&                                                       context,
484                                                                                                                  const VkDeviceSize                                     ssboSize,
485                                                                                                                  const std::vector<SpecConstant>&       specConstants,
486                                                                                                                  const std::vector<OffsetValue>&        expectedValues,
487                                                                                                                  bool                                                           packData);
488
489         tcu::TestStatus                                 iterate                         (void);
490
491 private:
492         const VkDeviceSize                              m_ssboSize;
493         const std::vector<SpecConstant> m_specConstants;
494         const std::vector<OffsetValue>  m_expectedValues;
495         const bool                                              m_packData;
496 };
497
498 ComputeTestInstance::ComputeTestInstance (Context&                                                      context,
499                                                                                   const VkDeviceSize                            ssboSize,
500                                                                                   const std::vector<SpecConstant>&      specConstants,
501                                                                                   const std::vector<OffsetValue>&       expectedValues,
502                                                                                   bool                                                          packData)
503         : TestInstance          (context)
504         , m_ssboSize            (ssboSize)
505         , m_specConstants       (specConstants)
506         , m_expectedValues      (expectedValues)
507         , m_packData            (packData)
508 {
509 }
510
511 tcu::TestStatus ComputeTestInstance::iterate (void)
512 {
513         const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
514         const VkDevice                  device                          = m_context.getDevice();
515         const VkQueue                   queue                           = m_context.getUniversalQueue();
516         const deUint32                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
517         Allocator&                              allocator                       = m_context.getDefaultAllocator();
518
519         // Descriptors
520
521         const Buffer resultBuffer(vk, device, allocator, makeBufferCreateInfo(m_ssboSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible);
522
523         const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
524                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
525                 .build(vk, device));
526
527         const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
528                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
529                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
530
531         const Unique<VkDescriptorSet> descriptorSet        (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
532         const VkDescriptorBufferInfo  descriptorBufferInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, m_ssboSize);
533
534         DescriptorSetUpdateBuilder()
535                 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo)
536                 .update(vk, device);
537
538         // Specialization
539
540         const Specialization        specialization (m_specConstants, m_packData);
541         const VkSpecializationInfo* pSpecInfo      = specialization.getSpecializationInfo();
542
543         // Pipeline
544
545         const Unique<VkShaderModule>   shaderModule  (createShaderModule (vk, device, m_context.getBinaryCollection().get("comp"), 0));
546         const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout (vk, device, *descriptorSetLayout));
547         const Unique<VkPipeline>       pipeline      (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule, pSpecInfo));
548         const Unique<VkCommandPool>    cmdPool       (createCommandPool  (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
549         const Unique<VkCommandBuffer>  cmdBuffer     (makeCommandBuffer  (vk, device, *cmdPool));
550
551         beginCommandBuffer(vk, *cmdBuffer);
552
553         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
554         vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
555
556         vk.cmdDispatch(*cmdBuffer, 1u, 1u, 1u);
557
558         {
559                 const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
560                         VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, m_ssboSize);
561
562                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
563                         0u, DE_NULL, 1u, &shaderWriteBarrier, 0u, DE_NULL);
564         }
565
566         endCommandBuffer(vk, *cmdBuffer);
567         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
568
569         // Verify results
570
571         const Allocation& resultAlloc = resultBuffer.getAllocation();
572         invalidateAlloc(vk, device, resultAlloc);
573
574         if (verifyValues(m_context.getTestContext().getLog(), resultAlloc.getHostPtr(), m_expectedValues))
575                 return tcu::TestStatus::pass("Success");
576         else
577                 return tcu::TestStatus::fail("Values did not match");
578 }
579
580 class GraphicsTestInstance : public TestInstance
581 {
582 public:
583                                                                         GraphicsTestInstance (Context&                                                  context,
584                                                                                                                   const VkDeviceSize                            ssboSize,
585                                                                                                                   const std::vector<SpecConstant>&      specConstants,
586                                                                                                                   const std::vector<OffsetValue>&       expectedValues,
587                                                                                                                   const VkShaderStageFlagBits           stage,
588                                                                                                                   bool                                                          packData);
589
590         tcu::TestStatus                                 iterate                          (void);
591
592 private:
593         const VkDeviceSize                              m_ssboSize;
594         const std::vector<SpecConstant> m_specConstants;
595         const std::vector<OffsetValue>  m_expectedValues;
596         const VkShaderStageFlagBits             m_stage;
597         const bool                                              m_packData;
598 };
599
600 GraphicsTestInstance::GraphicsTestInstance (Context&                                                    context,
601                                                                                         const VkDeviceSize                                      ssboSize,
602                                                                                         const std::vector<SpecConstant>&        specConstants,
603                                                                                         const std::vector<OffsetValue>&         expectedValues,
604                                                                                         const VkShaderStageFlagBits                     stage,
605                                                                                         bool                                                            packData)
606         : TestInstance          (context)
607         , m_ssboSize            (ssboSize)
608         , m_specConstants       (specConstants)
609         , m_expectedValues      (expectedValues)
610         , m_stage                       (stage)
611         , m_packData            (packData)
612 {
613 }
614
615 tcu::TestStatus GraphicsTestInstance::iterate (void)
616 {
617         const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
618         const VkDevice                  device                          = m_context.getDevice();
619         const VkQueue                   queue                           = m_context.getUniversalQueue();
620         const deUint32                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
621         Allocator&                              allocator                       = m_context.getDefaultAllocator();
622
623         // Color attachment
624
625         const tcu::IVec2          renderSize    = tcu::IVec2(32, 32);
626         const VkFormat            imageFormat   = VK_FORMAT_R8G8B8A8_UNORM;
627         const Image               colorImage    (vk, device, allocator, makeImageCreateInfo(renderSize, imageFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT), MemoryRequirement::Any);
628         const Unique<VkImageView> colorImageView(makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, imageFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)));
629
630         // Vertex buffer
631
632         const deUint32     numVertices           = 3;
633         const VkDeviceSize vertexBufferSizeBytes = sizeof(tcu::Vec4) * numVertices;
634         const Buffer       vertexBuffer          (vk, device, allocator, makeBufferCreateInfo(vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible);
635
636         {
637                 const Allocation& alloc = vertexBuffer.getAllocation();
638                 tcu::Vec4* pVertices = reinterpret_cast<tcu::Vec4*>(alloc.getHostPtr());
639
640                 pVertices[0] = tcu::Vec4(-1.0f, -1.0f,  0.0f,  1.0f);
641                 pVertices[1] = tcu::Vec4(-1.0f,  1.0f,  0.0f,  1.0f);
642                 pVertices[2] = tcu::Vec4( 1.0f, -1.0f,  0.0f,  1.0f);
643
644                 flushAlloc(vk, device, alloc);
645                 // No barrier needed, flushed memory is automatically visible
646         }
647
648         // Descriptors
649
650         const Buffer resultBuffer(vk, device, allocator, makeBufferCreateInfo(m_ssboSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible);
651
652         const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
653                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL_GRAPHICS)
654                 .build(vk, device));
655
656         const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
657                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
658                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
659
660         const Unique<VkDescriptorSet> descriptorSet        (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
661         const VkDescriptorBufferInfo  descriptorBufferInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, m_ssboSize);
662
663         DescriptorSetUpdateBuilder()
664                 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo)
665                 .update(vk, device);
666
667         // Specialization
668
669         const Specialization        specialization (m_specConstants, m_packData);
670         const VkSpecializationInfo* pSpecInfo      = specialization.getSpecializationInfo();
671
672         // Pipeline
673
674         const Unique<VkRenderPass>     renderPass    (makeRenderPass    (vk, device, imageFormat));
675         const Unique<VkFramebuffer>    framebuffer   (makeFramebuffer   (vk, device, *renderPass, colorImageView.get(), static_cast<deUint32>(renderSize.x()), static_cast<deUint32>(renderSize.y())));
676         const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
677         const Unique<VkCommandPool>    cmdPool       (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
678         const Unique<VkCommandBuffer>  cmdBuffer     (makeCommandBuffer (vk, device, *cmdPool));
679
680         GraphicsPipelineBuilder pipelineBuilder;
681         pipelineBuilder
682                 .setRenderSize(renderSize)
683                 .setShader(vk, device, VK_SHADER_STAGE_VERTEX_BIT,   m_context.getBinaryCollection().get("vert"), pSpecInfo)
684                 .setShader(vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("frag"), pSpecInfo);
685
686         if ((m_stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) || (m_stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
687                 pipelineBuilder
688                         .setShader(vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,    m_context.getBinaryCollection().get("tesc"), pSpecInfo)
689                         .setShader(vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_context.getBinaryCollection().get("tese"), pSpecInfo);
690
691         if (m_stage == VK_SHADER_STAGE_GEOMETRY_BIT)
692                 pipelineBuilder
693                         .setShader(vk, device, VK_SHADER_STAGE_GEOMETRY_BIT, m_context.getBinaryCollection().get("geom"), pSpecInfo);
694
695         const Unique<VkPipeline> pipeline (pipelineBuilder.build(vk, device, *pipelineLayout, *renderPass));
696
697         // Draw commands
698
699         const VkRect2D          renderArea                      = makeRect2D(renderSize);
700         const tcu::Vec4         clearColor                      (0.0f, 0.0f, 0.0f, 1.0f);
701         const VkDeviceSize      vertexBufferOffset      = 0ull;
702
703         beginCommandBuffer(vk, *cmdBuffer);
704
705         {
706                 const VkImageSubresourceRange imageFullSubresourceRange              = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
707                 const VkImageMemoryBarrier    barrierColorAttachmentSetInitialLayout = makeImageMemoryBarrier(
708                         0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
709                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
710                         *colorImage, imageFullSubresourceRange);
711
712                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
713                         0u, DE_NULL, 0u, DE_NULL, 1u, &barrierColorAttachmentSetInitialLayout);
714         }
715
716         beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor);
717
718         vk.cmdBindPipeline      (*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
719         vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
720         vk.cmdBindVertexBuffers (*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
721
722         vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
723         endRenderPass(vk, *cmdBuffer);
724
725         {
726                 const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
727                         VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, m_ssboSize);
728
729                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
730                         0u, DE_NULL, 1u, &shaderWriteBarrier, 0u, DE_NULL);
731         }
732
733         endCommandBuffer(vk, *cmdBuffer);
734         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
735
736         // Verify results
737
738         const Allocation& resultAlloc = resultBuffer.getAllocation();
739         invalidateAlloc(vk, device, resultAlloc);
740
741         if (verifyValues(m_context.getTestContext().getLog(), resultAlloc.getHostPtr(), m_expectedValues))
742                 return tcu::TestStatus::pass("Success");
743         else
744                 return tcu::TestStatus::fail("Values did not match");
745 }
746
747 FeatureFlags getShaderStageRequirements (const VkShaderStageFlags stageFlags)
748 {
749         FeatureFlags features = (FeatureFlags)0;
750
751         if (((stageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) || ((stageFlags & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0))
752                 features |= FEATURE_TESSELLATION_SHADER;
753
754         if ((stageFlags & VK_SHADER_STAGE_GEOMETRY_BIT) != 0)
755                 features |= FEATURE_GEOMETRY_SHADER;
756
757         // All tests use SSBO writes to read back results.
758         if ((stageFlags & VK_SHADER_STAGE_ALL_GRAPHICS) != 0)
759         {
760                 if ((stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) != 0)
761                         features |= FEATURE_FRAGMENT_STORES_AND_ATOMICS;
762                 else
763                         features |= FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS;
764         }
765
766         return features;
767 }
768
769 void SpecConstantTest::checkSupport (Context& context) const
770 {
771         requireFeatures(context, m_caseDef.requirements | getShaderStageRequirements(m_stage));
772 }
773
774 TestInstance* SpecConstantTest::createInstance (Context& context) const
775 {
776         if (m_stage & VK_SHADER_STAGE_COMPUTE_BIT)
777                 return new ComputeTestInstance(context, m_caseDef.ssboSize, m_caseDef.specConstants, m_caseDef.expectedValues, m_caseDef.packData);
778         else
779                 return new GraphicsTestInstance(context, m_caseDef.ssboSize, m_caseDef.specConstants, m_caseDef.expectedValues, m_stage, m_caseDef.packData);
780 }
781
782 //! Declare specialization constants but use them with default values.
783 tcu::TestCaseGroup* createDefaultValueTests (tcu::TestContext& testCtx, const VkShaderStageFlagBits shaderStage)
784 {
785         de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "default_value", "use default constant value"));
786
787         CaseDefinition defs[] =
788         {
789                 {
790                         "bool",
791                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const bool sc0 = true;"),
792                                            SpecConstant(2u, "layout(constant_id = ${ID}) const bool sc1 = false;")),
793                         8,
794                         "    bool r0;\n"
795                         "    bool r1;\n",
796                         "",
797                         "    sb_out.r0 = sc0;\n"
798                         "    sb_out.r1 = sc1;\n",
799                         makeVector(OffsetValue(4, 0, makeValueBool32(true)),
800                                            OffsetValue(4, 4, makeValueBool32(false))),
801                         (FeatureFlags)0,
802                         false,
803                 },
804                 {
805                         "int8",
806                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int8_t sc0 = int8_t(1);"),
807                                            SpecConstant(2u, "layout(constant_id = ${ID}) const int8_t sc1 = int8_t(-2);")),
808                         2,
809                         "    int8_t r0;\n"
810                         "    int8_t r1;\n",
811                         "",
812                         "    int8_t aux = sc0 + sc1;\n"
813                         "    sb_out.r0 = sc0;\n"
814                         "    sb_out.r1 = sc1;\n",
815                         makeVector(OffsetValue(1, 0, makeValueInt8(1)),
816                                            OffsetValue(1, 1, makeValueInt8(-2))),
817                         FEATURE_SHADER_INT_8,
818                         false,
819                 },
820                 {
821                         "uint8",
822                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint8_t sc0 = int8_t(15);"),
823                                            SpecConstant(2u, "layout(constant_id = ${ID}) const uint8_t sc1 = int8_t(43);")),
824                         2,
825                         "    uint8_t r0;\n"
826                         "    uint8_t r1;\n",
827                         "",
828                         "    uint8_t aux = sc0 + sc1;\n"
829                         "    sb_out.r0 = sc0;\n"
830                         "    sb_out.r1 = sc1;\n",
831                         makeVector(OffsetValue(1, 0, makeValueUint8(15)),
832                                            OffsetValue(1, 1, makeValueUint8(43))),
833                         FEATURE_SHADER_INT_8,
834                         false,
835                 },
836                 {
837                         "int16",
838                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int16_t sc0 = 20000s;", 2, makeValueInt16(32000)),
839                                            SpecConstant(2u, "layout(constant_id = ${ID}) const int16_t sc1 = -20000s;")),
840                         4,
841                         "    int16_t r0;\n"
842                         "    int16_t r1;\n",
843                         "",
844                         "    int16_t aux = sc0 + sc1;\n"
845                         "    sb_out.r0 = sc0;\n"
846                         "    sb_out.r1 = sc1;\n",
847                         makeVector(OffsetValue(2, 0, makeValueInt16(32000)),
848                                            OffsetValue(2, 2, makeValueInt16(-20000))),
849                         FEATURE_SHADER_INT_16,
850                         false,
851                 },
852                 {
853                         "uint16",
854                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint16_t sc0 = 64000us;"),
855                                            SpecConstant(2u, "layout(constant_id = ${ID}) const uint16_t sc1 = 51829us;")),
856                         4,
857                         "    uint16_t r0;\n"
858                         "    uint16_t r1;\n",
859                         "",
860                         "    uint16_t aux = sc0 + sc1;\n"
861                         "    sb_out.r0 = sc0;\n"
862                         "    sb_out.r1 = sc1;\n",
863                         makeVector(OffsetValue(2, 0, makeValueUint16(64000)),
864                                            OffsetValue(2, 2, makeValueUint16(51829))),
865                         FEATURE_SHADER_INT_16,
866                         false,
867                 },
868                 {
869                         "int",
870                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = -3;"),
871                                            SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 17;")),
872                         8,
873                         "    int r0;\n"
874                         "    int r1;\n",
875                         "",
876                         "    sb_out.r0 = sc0;\n"
877                         "    sb_out.r1 = sc1;\n",
878                         makeVector(OffsetValue(4, 0, makeValueInt32(-3)),
879                                            OffsetValue(4, 4, makeValueInt32(17))),
880                         (FeatureFlags)0,
881                         false,
882                 },
883                 {
884                         "uint",
885                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint sc0 = 42u;")),
886                         4,
887                         "    uint r0;\n",
888                         "",
889                         "    sb_out.r0 = sc0;\n",
890                         makeVector(OffsetValue(4, 0, makeValueUint32(42u))),
891                         (FeatureFlags)0,
892                         false,
893                 },
894                 {
895                         "int64",
896                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int64_t sc0 = 9141386509785772560l;"),
897                                            SpecConstant(2u, "layout(constant_id = ${ID}) const int64_t sc1 = -9141386509785772560l;")),
898                         16,
899                         "    int64_t r0;\n"
900                         "    int64_t r1;\n",
901                         "",
902                         "    sb_out.r0 = sc0;\n"
903                         "    sb_out.r1 = sc1;\n",
904                         makeVector(OffsetValue(8, 0, makeValueInt64(9141386509785772560ll)),
905                                            OffsetValue(8, 8, makeValueInt64(-9141386509785772560ll))),
906                         FEATURE_SHADER_INT_64,
907                         false,
908                 },
909                 {
910                         "uint64",
911                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint64_t sc0 = 18364758544493064720ul;"),
912                                            SpecConstant(2u, "layout(constant_id = ${ID}) const uint64_t sc1 = 17298946664678735070ul;")),
913                         16,
914                         "    uint64_t r0;\n"
915                         "    uint64_t r1;\n",
916                         "",
917                         "    sb_out.r0 = sc0;\n"
918                         "    sb_out.r1 = sc1;\n",
919                         makeVector(OffsetValue(8, 0, makeValueUint64(18364758544493064720ull)),
920                                            OffsetValue(8, 8, makeValueUint64(17298946664678735070ull))),
921                         FEATURE_SHADER_INT_64,
922                         false,
923                 },
924                 {
925                         "float16",
926                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const float16_t sc0 = 7.5hf;"),
927                                            SpecConstant(2u, "layout(constant_id = ${ID}) const float16_t sc1 = 1.125hf;")),
928                         4,
929                         "    float16_t r0;\n"
930                         "    float16_t r1;\n",
931                         "",
932                         "    float16_t aux = sc0 + sc1;\n"
933                         "    sb_out.r0 = sc0;\n"
934                         "    sb_out.r1 = sc1;\n",
935                         makeVector(OffsetValue(2, 0, makeValueFloat16(tcu::Float16(7.5))),
936                                            OffsetValue(2, 2, makeValueFloat16(tcu::Float16(1.125)))),
937                         FEATURE_SHADER_FLOAT_16,
938                         false,
939                 },
940                 {
941                         "float",
942                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const float sc0 = 7.5;")),
943                         4,
944                         "    float r0;\n",
945                         "",
946                         "    sb_out.r0 = sc0;\n",
947                         makeVector(OffsetValue(4, 0, makeValueFloat32(7.5f))),
948                         (FeatureFlags)0,
949                         false,
950                 },
951                 {
952                         "double",
953                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const double sc0 = 2.75LF;")),
954                         8,
955                         "    double r0;\n",
956                         "",
957                         "    sb_out.r0 = sc0;\n",
958                         makeVector(OffsetValue(8, 0, makeValueFloat64(2.75))),
959                         FEATURE_SHADER_FLOAT_64,
960                         false,
961                 },
962         };
963
964         for (int i = 0; i < 2; ++i)
965         {
966                 const bool packData = (i > 0);
967                 for (int defNdx = 0; defNdx < DE_LENGTH_OF_ARRAY(defs); ++defNdx)
968                 {
969                         auto& def = defs[defNdx];
970                         def.packData = packData;
971                         if (packData)
972                                 def.name += "_packed";
973                         testGroup->addChild(new SpecConstantTest(testCtx, shaderStage, def));
974                 }
975         }
976
977         return testGroup.release();
978 }
979
980 //! Declare specialization constants and specify their values through API.
981 tcu::TestCaseGroup* createBasicSpecializationTests (tcu::TestContext& testCtx, const VkShaderStageFlagBits shaderStage)
982 {
983         de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "basic", "specialize a constant"));
984
985         CaseDefinition defs[] =
986         {
987                 {
988                         "bool",
989                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const bool sc0 = true;",  4, makeValueBool32(true)),
990                                            SpecConstant(2u, "layout(constant_id = ${ID}) const bool sc1 = false;", 4, makeValueBool32(false)),
991                                            SpecConstant(3u, "layout(constant_id = ${ID}) const bool sc2 = true;",  4, makeValueBool32(false)),
992                                            SpecConstant(4u, "layout(constant_id = ${ID}) const bool sc3 = false;", 4, makeValueBool32(true))),
993                         16,
994                         "    bool r0;\n"
995                         "    bool r1;\n"
996                         "    bool r2;\n"
997                         "    bool r3;\n",
998                         "",
999                         "    sb_out.r0 = sc0;\n"
1000                         "    sb_out.r1 = sc1;\n"
1001                         "    sb_out.r2 = sc2;\n"
1002                         "    sb_out.r3 = sc3;\n",
1003                         makeVector(OffsetValue(4,  0, makeValueBool32(true)),
1004                                            OffsetValue(4,  4, makeValueBool32(false)),
1005                                            OffsetValue(4,  8, makeValueBool32(false)),
1006                                            OffsetValue(4, 12, makeValueBool32(true))),
1007                         (FeatureFlags)0,
1008                         false,
1009                 },
1010                 {
1011                         "int8",
1012                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int8_t sc0 = int8_t(1);", 1, makeValueInt8(127)),
1013                                            SpecConstant(2u, "layout(constant_id = ${ID}) const int8_t sc1 = int8_t(-2);")),
1014                         2,
1015                         "    int8_t r0;\n"
1016                         "    int8_t r1;\n",
1017                         "",
1018                         "    int8_t aux = sc0 + sc1;\n"
1019                         "    sb_out.r0 = sc0;\n"
1020                         "    sb_out.r1 = sc1;\n",
1021                         makeVector(OffsetValue(1, 0, makeValueInt8(127)),
1022                                            OffsetValue(1, 1, makeValueInt8(-2))),
1023                         FEATURE_SHADER_INT_8,
1024                         false,
1025                 },
1026                 {
1027                         "int8_2",
1028                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int8_t sc0 = int8_t(123);", 1, makeValueInt8(65)),
1029                                            SpecConstant(2u, "layout(constant_id = ${ID}) const int8_t sc1 = int8_t(-33);", 1, makeValueInt8(-128))),
1030                         2,
1031                         "    int8_t r0;\n"
1032                         "    int8_t r1;\n",
1033                         "",
1034                         "    int8_t aux = sc0 + sc1;\n"
1035                         "    sb_out.r0 = sc0;\n"
1036                         "    sb_out.r1 = sc1;\n",
1037                         makeVector(OffsetValue(1, 0, makeValueInt8(65)),
1038                                            OffsetValue(1, 1, makeValueInt8(-128))),
1039                         FEATURE_SHADER_INT_8,
1040                         false,
1041                 },
1042                 {
1043                         "uint8",
1044                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint8_t sc0 = int8_t(15);", 1, makeValueUint8(254)),
1045                                            SpecConstant(2u, "layout(constant_id = ${ID}) const uint8_t sc1 = int8_t(43);")),
1046                         2,
1047                         "    uint8_t r0;\n"
1048                         "    uint8_t r1;\n",
1049                         "",
1050                         "    uint8_t aux = sc0 + sc1;\n"
1051                         "    sb_out.r0 = sc0;\n"
1052                         "    sb_out.r1 = sc1;\n",
1053                         makeVector(OffsetValue(1, 0, makeValueUint8(254)),
1054                                            OffsetValue(1, 1, makeValueUint8(43))),
1055                         FEATURE_SHADER_INT_8,
1056                         false,
1057                 },
1058                 {
1059                         "uint8_2",
1060                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint8_t sc0 = int8_t(99);", 1, makeValueUint8(254)),
1061                                            SpecConstant(2u, "layout(constant_id = ${ID}) const uint8_t sc1 = int8_t(81);", 1, makeValueUint8(255))),
1062                         2,
1063                         "    uint8_t r0;\n"
1064                         "    uint8_t r1;\n",
1065                         "",
1066                         "    uint8_t aux = sc0 + sc1;\n"
1067                         "    sb_out.r0 = sc0;\n"
1068                         "    sb_out.r1 = sc1;\n",
1069                         makeVector(OffsetValue(1, 0, makeValueUint8(254)),
1070                                            OffsetValue(1, 1, makeValueUint8(255))),
1071                         FEATURE_SHADER_INT_8,
1072                         false,
1073                 },
1074                 {
1075                         "int16",
1076                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int16_t sc0 = 20000s;", 2, makeValueInt16(32000)),
1077                                            SpecConstant(2u, "layout(constant_id = ${ID}) const int16_t sc1 = -20000s;")),
1078                         4,
1079                         "    int16_t r0;\n"
1080                         "    int16_t r1;\n",
1081                         "",
1082                         "    int16_t aux = sc0 + sc1;\n"
1083                         "    sb_out.r0 = sc0;\n"
1084                         "    sb_out.r1 = sc1;\n",
1085                         makeVector(OffsetValue(2, 0, makeValueInt16(32000)),
1086                                            OffsetValue(2, 2, makeValueInt16(-20000))),
1087                         FEATURE_SHADER_INT_16,
1088                         false,
1089                 },
1090                 {
1091                         "int16_2",
1092                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int16_t sc0 = 20000s;", 2, makeValueInt16(32000)),
1093                                            SpecConstant(2u, "layout(constant_id = ${ID}) const int16_t sc1 = -20000s;", 2, makeValueInt16(-21000))),
1094                         4,
1095                         "    int16_t r0;\n"
1096                         "    int16_t r1;\n",
1097                         "",
1098                         "    int16_t aux = sc0 + sc1;\n"
1099                         "    sb_out.r0 = sc0;\n"
1100                         "    sb_out.r1 = sc1;\n",
1101                         makeVector(OffsetValue(2, 0, makeValueInt16(32000)),
1102                                            OffsetValue(2, 2, makeValueInt16(-21000))),
1103                         FEATURE_SHADER_INT_16,
1104                         false,
1105                 },
1106                 {
1107                         "uint16",
1108                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint16_t sc0 = 64000us;", 2, makeValueUint16(65000)),
1109                                            SpecConstant(2u, "layout(constant_id = ${ID}) const uint16_t sc1 = 51829us;")),
1110                         4,
1111                         "    uint16_t r0;\n"
1112                         "    uint16_t r1;\n",
1113                         "",
1114                         "    uint16_t aux = sc0 + sc1;\n"
1115                         "    sb_out.r0 = sc0;\n"
1116                         "    sb_out.r1 = sc1;\n",
1117                         makeVector(OffsetValue(2, 0, makeValueUint16(65000)),
1118                                            OffsetValue(2, 2, makeValueUint16(51829))),
1119                         FEATURE_SHADER_INT_16,
1120                         false,
1121                 },
1122                 {
1123                         "uint16_2",
1124                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint16_t sc0 = 64000us;", 2, makeValueUint16(65000)),
1125                                            SpecConstant(2u, "layout(constant_id = ${ID}) const uint16_t sc1 = 51829us;", 2, makeValueUint16(63000))),
1126                         4,
1127                         "    uint16_t r0;\n"
1128                         "    uint16_t r1;\n",
1129                         "",
1130                         "    uint16_t aux = sc0 + sc1;\n"
1131                         "    sb_out.r0 = sc0;\n"
1132                         "    sb_out.r1 = sc1;\n",
1133                         makeVector(OffsetValue(2, 0, makeValueUint16(65000)),
1134                                            OffsetValue(2, 2, makeValueUint16(63000))),
1135                         FEATURE_SHADER_INT_16,
1136                         false,
1137                 },
1138                 {
1139                         "int",
1140                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = -3;", 4, makeValueInt32(33)),
1141                                            SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 91;"),
1142                                            SpecConstant(3u, "layout(constant_id = ${ID}) const int sc2 = 17;", 4, makeValueInt32(-15))),
1143                         12,
1144                         "    int r0;\n"
1145                         "    int r1;\n"
1146                         "    int r2;\n",
1147                         "",
1148                         "    sb_out.r0 = sc0;\n"
1149                         "    sb_out.r1 = sc1;\n"
1150                         "    sb_out.r2 = sc2;\n",
1151                         makeVector(OffsetValue(4, 0, makeValueInt32(33)),
1152                                            OffsetValue(4, 4, makeValueInt32(91)),
1153                                            OffsetValue(4, 8, makeValueInt32(-15))),
1154                         (FeatureFlags)0,
1155                         false,
1156                 },
1157                 {
1158                         "uint",
1159                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint sc0 = 42u;", 4, makeValueUint32(97u)),
1160                                            SpecConstant(2u, "layout(constant_id = ${ID}) const uint sc1 = 7u;")),
1161                         8,
1162                         "    uint r0;\n"
1163                         "    uint r1;\n",
1164                         "",
1165                         "    sb_out.r0 = sc0;\n"
1166                         "    sb_out.r1 = sc1;\n",
1167                         makeVector(OffsetValue(4, 0, makeValueUint32(97u)),
1168                                            OffsetValue(4, 4, makeValueUint32(7u))),
1169                         (FeatureFlags)0,
1170                         false,
1171                 },
1172                 {
1173                         "uint_2",
1174                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint sc0 = 305419896u;", 4, makeValueUint32(1985229328u)),
1175                                            SpecConstant(2u, "layout(constant_id = ${ID}) const uint sc1 = 591751049u;"),
1176                                            SpecConstant(3u, "layout(constant_id = ${ID}) const uint sc2 = 878082202u;", 4, makeValueUint32(1698898186u))),
1177                         12,
1178                         "    uint r0;\n"
1179                         "    uint r1;\n"
1180                         "    uint r2;\n",
1181                         "",
1182                         "    sb_out.r0 = sc0;\n"
1183                         "    sb_out.r1 = sc1;\n"
1184                         "    sb_out.r2 = sc2;\n",
1185                         makeVector(OffsetValue(4, 0, makeValueUint32(1985229328u)),
1186                                            OffsetValue(4, 4, makeValueUint32(591751049u)),
1187                                            OffsetValue(4, 8, makeValueUint32(1698898186u))),
1188                         (FeatureFlags)0,
1189                         false,
1190                 },
1191                 {
1192                         "int64",
1193                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int64_t sc0 = 9141386509785772560l;", 8, makeValueInt64(9137147825770275585ll)),
1194                                            SpecConstant(2u, "layout(constant_id = ${ID}) const int64_t sc1 = -9141386509785772560l;")),
1195                         16,
1196                         "    int64_t r0;\n"
1197                         "    int64_t r1;\n",
1198                         "",
1199                         "    sb_out.r0 = sc0;\n"
1200                         "    sb_out.r1 = sc1;\n",
1201                         makeVector(OffsetValue(8, 0, makeValueInt64(9137147825770275585ll)),
1202                                            OffsetValue(8, 8, makeValueInt64(-9141386509785772560ll))),
1203                         FEATURE_SHADER_INT_64,
1204                         false,
1205                 },
1206                 {
1207                         "int64_2",
1208                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int64_t sc0 = 9141386509785772560l;", 8, makeValueInt64(9137147825770275585ll)),
1209                                            SpecConstant(2u, "layout(constant_id = ${ID}) const int64_t sc1 = -9141386509785772560l;", 8, makeValueInt64(-9137164382869201665ll))),
1210                         16,
1211                         "    int64_t r0;\n"
1212                         "    int64_t r1;\n",
1213                         "",
1214                         "    sb_out.r0 = sc0;\n"
1215                         "    sb_out.r1 = sc1;\n",
1216                         makeVector(OffsetValue(8, 0, makeValueInt64(9137147825770275585ll)),
1217                                            OffsetValue(8, 8, makeValueInt64(-9137164382869201665ll))),
1218                         FEATURE_SHADER_INT_64,
1219                         false,
1220                 },
1221                 {
1222                         "uint64",
1223                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint64_t sc0 = 18364758544493064720ul;", 8, makeValueUint64(17279655951921914625ull)),
1224                                            SpecConstant(2u, "layout(constant_id = ${ID}) const uint64_t sc1 = 17298946664678735070ul;")),
1225                         16,
1226                         "    uint64_t r0;\n"
1227                         "    uint64_t r1;\n",
1228                         "",
1229                         "    sb_out.r0 = sc0;\n"
1230                         "    sb_out.r1 = sc1;\n",
1231                         makeVector(OffsetValue(8, 0, makeValueUint64(17279655951921914625ull)),
1232                                            OffsetValue(8, 8, makeValueUint64(17298946664678735070ull))),
1233                         FEATURE_SHADER_INT_64,
1234                         false,
1235                 },
1236                 {
1237                         "uint64_2",
1238                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint64_t sc0 = 18364758544493064720ul;", 8, makeValueUint64(17279655951921914625ull)),
1239                                            SpecConstant(2u, "layout(constant_id = ${ID}) const uint64_t sc1 = 17298946664678735070ul;", 8, makeValueUint64(17270123250533606145ull))),
1240                         16,
1241                         "    uint64_t r0;\n"
1242                         "    uint64_t r1;\n",
1243                         "",
1244                         "    sb_out.r0 = sc0;\n"
1245                         "    sb_out.r1 = sc1;\n",
1246                         makeVector(OffsetValue(8, 0, makeValueUint64(17279655951921914625ull)),
1247                                            OffsetValue(8, 8, makeValueUint64(17270123250533606145ull))),
1248                         FEATURE_SHADER_INT_64,
1249                         false,
1250                 },
1251                 // We create some floating point values below as unsigned integers to make sure all bytes are set to different values, avoiding special patterns and denormals.
1252                 {
1253                         "float16",
1254                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const float16_t sc0 = 7.5hf;", 2, makeValueFloat16(tcu::Float16(15.75))),
1255                                            SpecConstant(2u, "layout(constant_id = ${ID}) const float16_t sc1 = 1.125hf;")),
1256                         4,
1257                         "    float16_t r0;\n"
1258                         "    float16_t r1;\n",
1259                         "",
1260                         "    float16_t aux = sc0 + sc1;\n"
1261                         "    sb_out.r0 = sc0;\n"
1262                         "    sb_out.r1 = sc1;\n",
1263                         makeVector(OffsetValue(2, 0, makeValueFloat16(tcu::Float16(15.75))),
1264                                            OffsetValue(2, 2, makeValueFloat16(tcu::Float16(1.125)))),
1265                         FEATURE_SHADER_FLOAT_16,
1266                         false,
1267                 },
1268                 {
1269                         "float16_2",
1270                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const float16_t sc0 = 7.5hf;", 2, makeValueUint16(0x0123u)),
1271                                            SpecConstant(2u, "layout(constant_id = ${ID}) const float16_t sc1 = 1.125hf;"),
1272                                            SpecConstant(3u, "layout(constant_id = ${ID}) const float16_t sc2 = 1.125hf;", 2, makeValueUint16(0xFEDCu))),
1273                         6,
1274                         "    float16_t r0;\n"
1275                         "    float16_t r1;\n"
1276                         "    float16_t r2;\n",
1277                         "",
1278                         "    float16_t aux = sc0 + sc1;\n"
1279                         "    sb_out.r0 = sc0;\n"
1280                         "    sb_out.r1 = sc1;\n"
1281                         "    sb_out.r2 = sc2;\n",
1282                         makeVector(OffsetValue(2, 0, makeValueUint16(0x0123u)),
1283                                            OffsetValue(2, 2, makeValueFloat16(tcu::Float16(1.125))),
1284                                            OffsetValue(2, 4, makeValueUint16(0xFEDCu))),
1285                         FEATURE_SHADER_FLOAT_16,
1286                         false,
1287                 },
1288                 {
1289                         "float",
1290                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const float sc0 = 7.5;", 4, makeValueFloat32(15.75f)),
1291                                            SpecConstant(2u, "layout(constant_id = ${ID}) const float sc1 = 1.125;")),
1292                         8,
1293                         "    float r0;\n"
1294                         "    float r1;\n",
1295                         "",
1296                         "    sb_out.r0 = sc0;\n"
1297                         "    sb_out.r1 = sc1;\n",
1298                         makeVector(OffsetValue(4, 0, makeValueFloat32(15.75f)),
1299                                            OffsetValue(4, 4, makeValueFloat32(1.125f))),
1300                         (FeatureFlags)0,
1301                         false,
1302                 },
1303                 {
1304                         "float_2",
1305                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const float sc0 = 7.5;", 4, makeValueUint32(0x01234567u)),
1306                                            SpecConstant(2u, "layout(constant_id = ${ID}) const float sc1 = 1.125;"),
1307                                            SpecConstant(3u, "layout(constant_id = ${ID}) const float sc2 = 1.125;", 4, makeValueUint32(0xfedcba98u))),
1308                         12,
1309                         "    float r0;\n"
1310                         "    float r1;\n"
1311                         "    float r2;\n",
1312                         "",
1313                         "    sb_out.r0 = sc0;\n"
1314                         "    sb_out.r1 = sc1;\n"
1315                         "    sb_out.r2 = sc2;\n",
1316                         makeVector(OffsetValue(4, 0, makeValueUint32(0x01234567u)),
1317                                            OffsetValue(4, 4, makeValueFloat32(1.125f)),
1318                                            OffsetValue(4, 8, makeValueUint32(0xfedcba98u))),
1319                         (FeatureFlags)0,
1320                         false,
1321                 },
1322                 {
1323                         "double",
1324                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const double sc0 = 2.75LF;", 8, makeValueUint64(0xFEDCBA9876543210ull)),
1325                                            SpecConstant(2u, "layout(constant_id = ${ID}) const double sc1 = 9.25LF;")),
1326                         16,
1327                         "    double r0;\n"
1328                         "    double r1;\n",
1329                         "",
1330                         "    sb_out.r0 = sc0;\n"
1331                         "    sb_out.r1 = sc1;\n",
1332                         makeVector(OffsetValue(8, 0, makeValueUint64(0xFEDCBA9876543210ull)),
1333                                            OffsetValue(8, 8, makeValueFloat64(9.25))),
1334                         FEATURE_SHADER_FLOAT_64,
1335                         false,
1336                 },
1337                 {
1338                         "double_2",
1339                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const double sc0 = 2.75LF;", 8, makeValueUint64(0xFEDCBA9876543210ull)),
1340                                            SpecConstant(2u, "layout(constant_id = ${ID}) const double sc1 = 9.25LF;", 8, makeValueUint64(0xEFCDAB8967452301ull))),
1341                         16,
1342                         "    double r0;\n"
1343                         "    double r1;\n",
1344                         "",
1345                         "    sb_out.r0 = sc0;\n"
1346                         "    sb_out.r1 = sc1;\n",
1347                         makeVector(OffsetValue(8, 0, makeValueUint64(0xFEDCBA9876543210ull)),
1348                                            OffsetValue(8, 8, makeValueUint64(0xEFCDAB8967452301ull))),
1349                         FEATURE_SHADER_FLOAT_64,
1350                         false,
1351                 },
1352                 {
1353                         "mixed",
1354                         makeVector(
1355                                 SpecConstant(1u, "layout(constant_id = ${ID}) const uint8_t  sc0 = uint8_t  (0);", 1, makeValueUint8(0x98)),
1356                                 SpecConstant(2u, "layout(constant_id = ${ID}) const uint16_t sc1 = uint16_t (0);", 2, makeValueUint16(0x9876)),
1357                                 SpecConstant(3u, "layout(constant_id = ${ID}) const uint     sc2 = uint     (0);", 4, makeValueUint32(0xba987654u)),
1358                                 SpecConstant(4u, "layout(constant_id = ${ID}) const uint64_t sc3 = uint64_t (0);", 8, makeValueUint64(0xfedcba9876543210ull))),
1359                         8+4+2+1,
1360                         "    uint64_t r0;\n"
1361                         "    uint     r1;\n"
1362                         "    uint16_t r2;\n"
1363                         "    uint8_t  r3;\n",
1364                         "",
1365                         "    uint64_t i0 = sc3;\n"
1366                         "    uint     i1 = sc2;\n"
1367                         "    uint16_t i2 = sc1;\n"
1368                         "    uint8_t  i3 = sc0;\n"
1369                         "    sb_out.r0 = i0;\n"
1370                         "    sb_out.r1 = i1;\n"
1371                         "    sb_out.r2 = i2;\n"
1372                         "    sb_out.r3 = i3;\n",
1373                         makeVector(
1374                                 OffsetValue(8, 0, makeValueUint64(0xfedcba9876543210ull)),
1375                                 OffsetValue(4, 8, makeValueUint32(0xba987654u)),
1376                                 OffsetValue(2, 12, makeValueUint16(0x9876)),
1377                                 OffsetValue(1, 14, makeValueUint8(0x98))),
1378                         (FEATURE_SHADER_INT_8 | FEATURE_SHADER_INT_16 | FEATURE_SHADER_INT_64),
1379                         false,
1380                 },
1381                 {
1382                         "mixed_reversed",
1383                         makeVector(
1384                                 SpecConstant(1u, "layout(constant_id = ${ID}) const uint64_t sc3 = uint64_t (0);", 8, makeValueUint64(0xfedcba9876543210ull)),
1385                                 SpecConstant(2u, "layout(constant_id = ${ID}) const uint     sc2 = uint     (0);", 4, makeValueUint32(0xba987654u)),
1386                                 SpecConstant(3u, "layout(constant_id = ${ID}) const uint16_t sc1 = uint16_t (0);", 2, makeValueUint16(0x9876)),
1387                                 SpecConstant(4u, "layout(constant_id = ${ID}) const uint8_t  sc0 = uint8_t  (0);", 1, makeValueUint8(0x98))),
1388                         8+4+2+1,
1389                         "    uint64_t r0;\n"
1390                         "    uint     r1;\n"
1391                         "    uint16_t r2;\n"
1392                         "    uint8_t  r3;\n",
1393                         "",
1394                         "    uint64_t i0 = sc3;\n"
1395                         "    uint     i1 = sc2;\n"
1396                         "    uint16_t i2 = sc1;\n"
1397                         "    uint8_t  i3 = sc0;\n"
1398                         "    sb_out.r0 = i0;\n"
1399                         "    sb_out.r1 = i1;\n"
1400                         "    sb_out.r2 = i2;\n"
1401                         "    sb_out.r3 = i3;\n",
1402                         makeVector(
1403                                 OffsetValue(8, 0, makeValueUint64(0xfedcba9876543210ull)),
1404                                 OffsetValue(4, 8, makeValueUint32(0xba987654u)),
1405                                 OffsetValue(2, 12, makeValueUint16(0x9876)),
1406                                 OffsetValue(1, 14, makeValueUint8(0x98))),
1407                         (FEATURE_SHADER_INT_8 | FEATURE_SHADER_INT_16 | FEATURE_SHADER_INT_64),
1408                         false,
1409                 },
1410         };
1411
1412         for (int i = 0; i < 2; ++i)
1413         {
1414                 const bool packData = (i > 0);
1415                 for (int defNdx = 0; defNdx < DE_LENGTH_OF_ARRAY(defs); ++defNdx)
1416                 {
1417                         auto& def = defs[defNdx];
1418                         def.packData = packData;
1419                         if (packData)
1420                                 def.name += "_packed";
1421                         testGroup->addChild(new SpecConstantTest(testCtx, shaderStage, def));
1422                 }
1423         }
1424
1425         CaseDefinition defsUnusedCases[] =
1426         {
1427                 {
1428                         "unused_single",
1429                         makeVector(SpecConstant(0u, "", 0u, GenericValue(), true)),
1430                         4,
1431                         "    int r0;\n",
1432                         "",
1433                         "    sb_out.r0 = 77;\n",
1434                         makeVector(OffsetValue(4u, 0u, makeValueInt32(77))),
1435                         (FeatureFlags)0,
1436                         false,
1437                 },
1438                 {
1439                         "unused_single_packed",
1440                         makeVector(SpecConstant(0u, "", 0u, GenericValue(), true),
1441                                            SpecConstant(1u, "layout(constant_id = ${ID}) const int sc1 = 0;", 4u, makeValueInt32(100))),
1442                         4,
1443                         "    int r1;\n",
1444                         "",
1445                         "    sb_out.r1 = sc1;\n",
1446                         makeVector(OffsetValue(4u, 0u, makeValueInt32(100))),
1447                         (FeatureFlags)0,
1448                         true,
1449                 },
1450                 {
1451                         "unused_multiple",
1452                         makeVector(SpecConstant( 7u, "layout(constant_id = ${ID}) const int sc0 = 0;", 4u, makeValueInt32(-999)),
1453                                            SpecConstant( 1u, "", 0u, GenericValue(), true),
1454                                            SpecConstant(17u, "layout(constant_id = ${ID}) const int sc1 = 0;", 4u, makeValueInt32( 999)),
1455                                            SpecConstant( 3u, "", 0u, GenericValue(), true)),
1456                         8,
1457                         "    int r0;\n"
1458                         "    int r1;\n",
1459                         "",
1460                         "    sb_out.r0 = sc0;\n"
1461                         "    sb_out.r1 = sc1;\n",
1462                         makeVector(OffsetValue(4, 0, makeValueInt32(-999)),
1463                                            OffsetValue(4, 4, makeValueInt32( 999))),
1464                         (FeatureFlags)0,
1465                         false,
1466                 },
1467                 {
1468                         "unused_multiple_packed",
1469                         makeVector(SpecConstant( 7u, "layout(constant_id = ${ID}) const int sc0 = 0;", 4u, makeValueInt32(-999)),
1470                                            SpecConstant( 1u, "", 0u, GenericValue(), true),
1471                                            SpecConstant( 3u, "", 0u, GenericValue(), true),
1472                                            SpecConstant(17u, "layout(constant_id = ${ID}) const int sc1 = 0;", 4u, makeValueInt32( 999))),
1473                         8,
1474                         "    int r0;\n"
1475                         "    int r1;\n",
1476                         "",
1477                         "    sb_out.r0 = sc0;\n"
1478                         "    sb_out.r1 = sc1;\n",
1479                         makeVector(OffsetValue(4, 0, makeValueInt32(-999)),
1480                                            OffsetValue(4, 4, makeValueInt32( 999))),
1481                         (FeatureFlags)0,
1482                         true,
1483                 },
1484         };
1485
1486         for (const auto& caseDef : defsUnusedCases)
1487                 testGroup->addChild(new SpecConstantTest(testCtx, shaderStage, caseDef));
1488
1489         return testGroup.release();
1490 }
1491
1492 //! Specify compute shader work group size through specialization constants.
1493 tcu::TestCaseGroup* createWorkGroupSizeTests (tcu::TestContext& testCtx)
1494 {
1495         de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "local_size", "work group size specialization"));
1496
1497         const deUint32 ssboSize = 16;
1498         const std::string ssboDecl =
1499                 "    uvec3 workGroupSize;\n"
1500                 "    uint  checksum;\n";
1501         const std::string globalDecl = "shared uint count;\n";
1502         const std::string mainCode =
1503                 "    count = 0u;\n"
1504                 "\n"
1505                 "    groupMemoryBarrier();\n"
1506                 "    barrier();\n"
1507                 "\n"
1508                 "    atomicAdd(count, 1u);\n"
1509                 "\n"
1510                 "    groupMemoryBarrier();\n"
1511                 "    barrier();\n"
1512                 "\n"
1513                 "    sb_out.workGroupSize = gl_WorkGroupSize;\n"
1514                 "    sb_out.checksum      = count;\n";
1515
1516         const CaseDefinition defs[] =
1517         {
1518                 {
1519                         "x",
1520                         makeVector(SpecConstant(1u, "layout(local_size_x_id = ${ID}) in;",  4, makeValueUint32(7u))),
1521                         ssboSize, ssboDecl, globalDecl, mainCode,
1522                         makeVector(OffsetValue(4,  0, makeValueUint32(7u)),
1523                                            OffsetValue(4,  4, makeValueUint32(1u)),
1524                                            OffsetValue(4,  8, makeValueUint32(1u)),
1525                                            OffsetValue(4, 12, makeValueUint32(7u))),
1526                         (FeatureFlags)0,
1527                         false,
1528                 },
1529                 {
1530                         "y",
1531                         makeVector(SpecConstant(1u, "layout(local_size_y_id = ${ID}) in;",  4, makeValueUint32(5u))),
1532                         ssboSize, ssboDecl, globalDecl, mainCode,
1533                         makeVector(OffsetValue(4,  0, makeValueUint32(1u)),
1534                                            OffsetValue(4,  4, makeValueUint32(5u)),
1535                                            OffsetValue(4,  8, makeValueUint32(1u)),
1536                                            OffsetValue(4, 12, makeValueUint32(5u))),
1537                         (FeatureFlags)0,
1538                         false,
1539                 },
1540                 {
1541                         "z",
1542                         makeVector(SpecConstant(1u, "layout(local_size_z_id = ${ID}) in;",  4, makeValueUint32(3u))),
1543                         ssboSize, ssboDecl, globalDecl, mainCode,
1544                         makeVector(OffsetValue(4,  0, makeValueUint32(1u)),
1545                                            OffsetValue(4,  4, makeValueUint32(1u)),
1546                                            OffsetValue(4,  8, makeValueUint32(3u)),
1547                                            OffsetValue(4, 12, makeValueUint32(3u))),
1548                         (FeatureFlags)0,
1549                         false,
1550                 },
1551                 {
1552                         "xy",
1553                         makeVector(SpecConstant(1u, "layout(local_size_x_id = ${ID}) in;",  4, makeValueUint32(6u)),
1554                                            SpecConstant(2u, "layout(local_size_y_id = ${ID}) in;",  4, makeValueUint32(4u))),
1555                         ssboSize, ssboDecl, globalDecl, mainCode,
1556                         makeVector(OffsetValue(4,  0, makeValueUint32(6u)),
1557                                            OffsetValue(4,  4, makeValueUint32(4u)),
1558                                            OffsetValue(4,  8, makeValueUint32(1u)),
1559                                            OffsetValue(4, 12, makeValueUint32(6u * 4u))),
1560                         (FeatureFlags)0,
1561                         false,
1562                 },
1563                 {
1564                         "xz",
1565                         makeVector(SpecConstant(1u, "layout(local_size_x_id = ${ID}) in;",  4, makeValueUint32(3u)),
1566                                            SpecConstant(2u, "layout(local_size_z_id = ${ID}) in;",  4, makeValueUint32(9u))),
1567                         ssboSize, ssboDecl, globalDecl, mainCode,
1568                         makeVector(OffsetValue(4,  0, makeValueUint32(3u)),
1569                                            OffsetValue(4,  4, makeValueUint32(1u)),
1570                                            OffsetValue(4,  8, makeValueUint32(9u)),
1571                                            OffsetValue(4, 12, makeValueUint32(3u * 9u))),
1572                         (FeatureFlags)0,
1573                         false,
1574                 },
1575                 {
1576                         "yz",
1577                         makeVector(SpecConstant(1u, "layout(local_size_y_id = ${ID}) in;",  4, makeValueUint32(2u)),
1578                                            SpecConstant(2u, "layout(local_size_z_id = ${ID}) in;",  4, makeValueUint32(5u))),
1579                         ssboSize, ssboDecl, globalDecl, mainCode,
1580                         makeVector(OffsetValue(4,  0, makeValueUint32(1u)),
1581                                            OffsetValue(4,  4, makeValueUint32(2u)),
1582                                            OffsetValue(4,  8, makeValueUint32(5u)),
1583                                            OffsetValue(4, 12, makeValueUint32(2u * 5u))),
1584                         (FeatureFlags)0,
1585                         false,
1586                 },
1587                 {
1588                         "xyz",
1589                         makeVector(SpecConstant(1u, "layout(local_size_x_id = ${ID}) in;",  4, makeValueUint32(3u)),
1590                                            SpecConstant(2u, "layout(local_size_y_id = ${ID}) in;",  4, makeValueUint32(5u)),
1591                                            SpecConstant(3u, "layout(local_size_z_id = ${ID}) in;",  4, makeValueUint32(7u))),
1592                         ssboSize, ssboDecl, globalDecl, mainCode,
1593                         makeVector(OffsetValue(4,  0, makeValueUint32(3u)),
1594                                            OffsetValue(4,  4, makeValueUint32(5u)),
1595                                            OffsetValue(4,  8, makeValueUint32(7u)),
1596                                            OffsetValue(4, 12, makeValueUint32(3u * 5u * 7u))),
1597                         (FeatureFlags)0,
1598                         false,
1599                 },
1600         };
1601
1602         for (int defNdx = 0; defNdx < DE_LENGTH_OF_ARRAY(defs); ++defNdx)
1603                 testGroup->addChild(new SpecConstantTest(testCtx, VK_SHADER_STAGE_COMPUTE_BIT, defs[defNdx]));
1604
1605         return testGroup.release();
1606 }
1607
1608 //! Override a built-in variable with specialization constant value.
1609 tcu::TestCaseGroup* createBuiltInOverrideTests (tcu::TestContext& testCtx, const VkShaderStageFlagBits shaderStage)
1610 {
1611         de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "builtin", "built-in override"));
1612
1613         const CaseDefinition defs[] =
1614         {
1615                 {
1616                         "default",
1617                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) gl_MaxImageUnits;")),
1618                         4,
1619                         "    bool ok;\n",
1620                         "",
1621                         "    sb_out.ok = (gl_MaxImageUnits >= 8);\n",   // implementation defined, 8 is the minimum
1622                         makeVector(OffsetValue(4,  0, makeValueBool32(true))),
1623                         (FeatureFlags)0,
1624                         false,
1625                 },
1626                 {
1627                         "specialized",
1628                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) gl_MaxImageUnits;", 4, makeValueInt32(12))),
1629                         4,
1630                         "    int maxImageUnits;\n",
1631                         "",
1632                         "    sb_out.maxImageUnits = gl_MaxImageUnits;\n",
1633                         makeVector(OffsetValue(4,  0, makeValueInt32(12))),
1634                         (FeatureFlags)0,
1635                         false,
1636                 },
1637         };
1638
1639         for (int defNdx = 0; defNdx < DE_LENGTH_OF_ARRAY(defs); ++defNdx)
1640                 testGroup->addChild(new SpecConstantTest(testCtx, shaderStage, defs[defNdx]));
1641
1642         return testGroup.release();
1643 }
1644
1645 //! Specialization constants used in expressions.
1646 tcu::TestCaseGroup* createExpressionTests (tcu::TestContext& testCtx, const VkShaderStageFlagBits shaderStage)
1647 {
1648         de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "expression", "specialization constants usage in expressions"));
1649
1650         const CaseDefinition defs[] =
1651         {
1652                 {
1653                         "spec_const_expression",
1654                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 2;"),
1655                                            SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 3;", 4, makeValueInt32(5))),
1656                         4,
1657                         "    int result;\n",
1658
1659                         "const int expr0 = sc0 + 1;\n"
1660                         "const int expr1 = sc0 + sc1;\n",
1661
1662                         "    sb_out.result = expr0 + expr1;\n",
1663                         makeVector(OffsetValue(4,  0, makeValueInt32(10))),
1664                         (FeatureFlags)0,
1665                         false,
1666                 },
1667                 {
1668                         "array_size",
1669                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 1;"),
1670                                            SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 2;", 4, makeValueInt32(3))),
1671                         16,
1672                         "    int r0;\n"
1673                         "    int r1[3];\n",
1674
1675                         "",
1676
1677                         "    int a0[sc0];\n"
1678                         "    int a1[sc1];\n"
1679                         "\n"
1680                         "    for (int i = 0; i < sc0; ++i)\n"
1681                         "        a0[i] = sc0 - i;\n"
1682                         "    for (int i = 0; i < sc1; ++i)\n"
1683                         "        a1[i] = sc1 - i;\n"
1684                         "\n"
1685                         "    sb_out.r0 = a0[0];\n"
1686                         "    for (int i = 0; i < sc1; ++i)\n"
1687                         "            sb_out.r1[i] = a1[i];\n",
1688                         makeVector(OffsetValue(4,  0, makeValueInt32(1)),
1689                                            OffsetValue(4,  4, makeValueInt32(3)),
1690                                            OffsetValue(4,  8, makeValueInt32(2)),
1691                                            OffsetValue(4, 12, makeValueInt32(1))),
1692                         (FeatureFlags)0,
1693                         false,
1694                 },
1695                 {
1696                         "array_size_expression",
1697                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 3;"),
1698                                            SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 5;", 4, makeValueInt32(7))),
1699                         8,
1700                         "    int r0;\n"
1701                         "    int r1;\n",
1702
1703                         "",
1704
1705                         "    int a0[sc0 + 3];\n"
1706                         "    int a1[sc0 + sc1];\n"
1707                         "\n"
1708                         "    const int size0 = sc0 + 3;\n"
1709                         "    const int size1 = sc0 + sc1;\n"
1710                         "\n"
1711                         "    for (int i = 0; i < size0; ++i)\n"
1712                         "        a0[i] = 3 - i;\n"
1713                         "    for (int i = 0; i < size1; ++i)\n"
1714                         "        a1[i] = 5 - i;\n"
1715                         "\n"
1716                         "    sb_out.r0 = a0[size0 - 1];\n"
1717                         "    sb_out.r1 = a1[size1 - 1];\n",
1718                         makeVector(OffsetValue(4,  0, makeValueInt32(-2)),
1719                                            OffsetValue(4,  4, makeValueInt32(-4))),
1720                         (FeatureFlags)0,
1721                         false,
1722                 },
1723                 {
1724                         "array_size_spec_const_expression",
1725                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 3;"),
1726                                            SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 5;", 4, makeValueInt32(7))),
1727                         8,
1728                         "    int r0;\n"
1729                         "    int r1;\n",
1730
1731                         "",
1732
1733                         "    const int size0 = sc0 + 3;\n"
1734                         "    const int size1 = sc0 + sc1;\n"
1735                         "\n"
1736                         "    int a0[size0];\n"
1737                         "    int a1[size1];\n"
1738                         "\n"
1739                         "    for (int i = 0; i < size0; ++i)\n"
1740                         "        a0[i] = 3 - i;\n"
1741                         "    for (int i = 0; i < size1; ++i)\n"
1742                         "        a1[i] = 5 - i;\n"
1743                         "\n"
1744                         "    sb_out.r0 = a0[size0 - 1];\n"
1745                         "    sb_out.r1 = a1[size1 - 1];\n",
1746                         makeVector(OffsetValue(4,  0, makeValueInt32(-2)),
1747                                            OffsetValue(4,  4, makeValueInt32(-4))),
1748                         (FeatureFlags)0,
1749                         false,
1750                 },
1751                 {
1752                         "array_size_length",
1753                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 1;"),
1754                                            SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 2;", 4, makeValueInt32(4))),
1755                         8,
1756                         "    int r0;\n"
1757                         "    int r1;\n",
1758
1759                         "",
1760
1761                         "    int a0[sc0];\n"
1762                         "    int a1[sc1];\n"
1763                         "\n"
1764                         "    sb_out.r0 = a0.length();\n"
1765                         "    sb_out.r1 = a1.length();\n",
1766                         makeVector(OffsetValue(4,  0, makeValueInt32(1)),
1767                                            OffsetValue(4,  4, makeValueInt32(4))),
1768                         (FeatureFlags)0,
1769                         false,
1770                 },
1771                 {
1772                         "array_size_pass_to_function",
1773                         makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 3;"),
1774                                            SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 1;", 4, makeValueInt32(3))),
1775                         4,
1776                         "    int result;\n",
1777
1778                         "int sumArrays (int a0[sc0], int a1[sc1])\n"
1779                         "{\n"
1780                         "    int sum = 0;\n"
1781                         "    for (int i = 0; (i < sc0) && (i < sc1); ++i)\n"
1782                         "        sum += a0[i] + a1[i];\n"
1783                         "    return sum;\n"
1784                         "}\n",
1785
1786                         "    int a0[sc0];\n"
1787                         "    int a1[sc1];\n"
1788                         "\n"
1789                         "    for (int i = 0; i < sc0; ++i)\n"
1790                         "        a0[i] = i + 1;\n"
1791                         "    for (int i = 0; i < sc1; ++i)\n"
1792                         "        a1[i] = i + 2;\n"
1793                         "\n"
1794                         "    sb_out.result = sumArrays(a0, a1);\n",
1795                         makeVector(OffsetValue(4,  0, makeValueInt32(15))),
1796                         (FeatureFlags)0,
1797                         false,
1798                 },
1799         };
1800
1801         for (int defNdx = 0; defNdx < DE_LENGTH_OF_ARRAY(defs); ++defNdx)
1802                 testGroup->addChild(new SpecConstantTest(testCtx, shaderStage, defs[defNdx]));
1803
1804         return testGroup.release();
1805 }
1806
1807 //! Helper functions internal to make*CompositeCaseDefinition functions.
1808 namespace composite_case_internal
1809 {
1810
1811 //! Generate a string like this: "1, 2, sc0, 4" or "true, true, sc0"
1812 //! castToType = true is useful when type requires more initializer values than we are providing, e.g.:
1813 //!    vec2(1), vec2(sc0), vec(3)
1814 std::string generateInitializerListWithSpecConstant (const glu::DataType        type,
1815                                                                                                          const bool                             castToType,
1816                                                                                                          const int                              idxBegin,
1817                                                                                                          const int                              idxEnd,
1818                                                                                                          const std::string&             specConstName,
1819                                                                                                          const int                              specConstNdx)
1820 {
1821         std::ostringstream str;
1822
1823         for (int i = idxBegin; i < idxEnd; ++i)
1824         {
1825                 const std::string iVal = (i == specConstNdx ? specConstName : glu::getDataTypeScalarType(type) == glu::TYPE_BOOL ? "true" : de::toString(i + 1));
1826                 str << (i != idxBegin ? ", " : "") << (castToType ? de::toString(glu::getDataTypeName(type)) + "(" + iVal + ")" : iVal);
1827         }
1828
1829         return str.str();
1830 }
1831
1832 std::string generateArrayConstructorString (const glu::DataType elemType,
1833                                                                                         const int                       size1,
1834                                                                                         const int                       size2,
1835                                                                                         const std::string&      specConstName,
1836                                                                                         const int                       specConstNdx)
1837 {
1838         const bool isArrayOfArray = (size2 > 0);
1839         const bool doCast                 = (!isDataTypeScalar(elemType));
1840
1841         std::ostringstream arrayCtorExpr;
1842
1843         if (isArrayOfArray)
1844         {
1845                 const std::string padding  (36, ' ');
1846                 int               idxBegin = 0;
1847                 int               idxEnd   = size2;
1848
1849                 for (int iterNdx = 0; iterNdx < size1; ++iterNdx)
1850                 {
1851                         // Open sub-array ctor
1852                         arrayCtorExpr << (iterNdx != 0 ? ",\n" + padding : "") << glu::getDataTypeName(elemType) << "[" << size2 << "](";
1853
1854                         // Sub-array constructor elements
1855                         arrayCtorExpr << generateInitializerListWithSpecConstant(elemType, doCast, idxBegin, idxEnd, specConstName, specConstNdx);
1856
1857                         // Close sub-array ctor, move to next range
1858                         arrayCtorExpr << ")";
1859
1860                         idxBegin += size2;
1861                         idxEnd += size2;
1862                 }
1863         }
1864         else
1865         {
1866                 // Array constructor elements
1867                 arrayCtorExpr << generateInitializerListWithSpecConstant(elemType, doCast, 0, size1, specConstName, specConstNdx);
1868         }
1869
1870         return arrayCtorExpr.str();
1871 }
1872
1873 inline GenericValue makeValue (const glu::DataType type, const int specValue)
1874 {
1875         if (type == glu::TYPE_DOUBLE)
1876                 return makeValueFloat64(static_cast<double>(specValue));
1877         else if (type == glu::TYPE_FLOAT)
1878                 return makeValueFloat32(static_cast<float>(specValue));
1879         else
1880                 return makeValueInt32(specValue);
1881 }
1882
1883 deUint32 getDataTypeScalarSizeBytes (const glu::DataType dataType)
1884 {
1885         switch (getDataTypeScalarType(dataType))
1886         {
1887                 case glu::TYPE_FLOAT:
1888                 case glu::TYPE_INT:
1889                 case glu::TYPE_UINT:
1890                 case glu::TYPE_BOOL:
1891                         return 4;
1892
1893                 case glu::TYPE_DOUBLE:
1894                         return 8;
1895
1896                 default:
1897                         DE_ASSERT(false);
1898                         return 0;
1899         }
1900 }
1901
1902 //! This applies to matrices/vectors/array cases. dataType must be a basic type.
1903 std::vector<OffsetValue> computeExpectedValues (const int specValue, const glu::DataType dataType, const int numCombinations)
1904 {
1905         DE_ASSERT(glu::isDataTypeScalar(dataType));
1906
1907         std::vector<OffsetValue> expectedValues;
1908
1909         for (int combNdx = 0; combNdx < numCombinations; ++combNdx)
1910         {
1911                 int sum = 0;
1912                 for (int i = 0; i < numCombinations; ++i)
1913                         sum += (i == combNdx ? specValue : dataType == glu::TYPE_BOOL ? 1 : (i + 1));
1914
1915                 const int dataSize = getDataTypeScalarSizeBytes(dataType);
1916                 expectedValues.push_back(OffsetValue(dataSize, dataSize * combNdx, makeValue(dataType, sum)));
1917         }
1918
1919         return expectedValues;
1920 }
1921
1922 inline std::string getFirstDataElementSubscriptString (const glu::DataType type)
1923 {
1924         // Grab the first element of a matrix/vector, if dealing with non-basic types.
1925         return (isDataTypeMatrix(type) ? "[0][0]" : isDataTypeVector(type) ? "[0]" : "");
1926 }
1927
1928 //! This code will go into the main function.
1929 std::string generateShaderChecksumComputationCode (const glu::DataType  elemType,
1930                                                                                                    const std::string&   varName,
1931                                                                                                    const std::string&   accumType,
1932                                                                                                    const int                    size1,
1933                                                                                                    const int                    size2,
1934                                                                                                    const int                    numCombinations)
1935 {
1936         std::ostringstream mainCode;
1937
1938         // Generate main code to calculate checksums for each array
1939         for (int combNdx = 0; combNdx < numCombinations; ++combNdx)
1940                 mainCode << "    "<< accumType << " sum_" << varName << combNdx << " = " << accumType << "(0);\n";
1941
1942         if (size2 > 0)
1943         {
1944                 mainCode << "\n"
1945                                         << "    for (int i = 0; i < " << size1 << "; ++i)\n"
1946                                         << "    for (int j = 0; j < " << size2 << "; ++j)\n"
1947                                         << "    {\n";
1948
1949                 for (int combNdx = 0; combNdx < numCombinations; ++combNdx)
1950                         mainCode << "        sum_" << varName << combNdx << " += " << accumType << "("
1951                                          << varName << combNdx << "[i][j]" << getFirstDataElementSubscriptString(elemType) << ");\n";
1952         }
1953         else
1954         {
1955                 mainCode << "\n"
1956                                         << "    for (int i = 0; i < " << size1 << "; ++i)\n"
1957                                         << "    {\n";
1958
1959                 for (int combNdx = 0; combNdx < numCombinations; ++combNdx)
1960                         mainCode << "        sum_" << varName << combNdx << " += " << accumType << "("
1961                                          << varName << combNdx << "[i]" << getFirstDataElementSubscriptString(elemType) << ");\n";
1962         }
1963
1964         mainCode << "    }\n"
1965                                 << "\n";
1966
1967         for (int combNdx = 0; combNdx < numCombinations; ++combNdx)
1968                 mainCode << "    sb_out.result[" << combNdx << "] = sum_" << varName << combNdx << ";\n";
1969
1970         return mainCode.str();
1971 }
1972
1973 SpecConstant makeSpecConstant (const std::string specConstName, const deUint32 specConstId, const glu::DataType type, const int specValue)
1974 {
1975         DE_ASSERT(glu::isDataTypeScalar(type));
1976
1977         const std::string typeName(glu::getDataTypeName(type));
1978
1979         return SpecConstant(
1980                 specConstId,
1981                 "layout(constant_id = ${ID}) const " + typeName + " " + specConstName + " = " + typeName + "(1);",
1982                 getDataTypeScalarSizeBytes(type), makeValue(type, specValue));
1983 }
1984
1985 } // composite_case_internal ns
1986
1987 //! Generate a CaseDefinition for a composite test using a matrix or vector (a 1-column matrix)
1988 CaseDefinition makeMatrixVectorCompositeCaseDefinition (const glu::DataType type)
1989 {
1990         using namespace composite_case_internal;
1991
1992         DE_ASSERT(!glu::isDataTypeScalar(type));
1993
1994         const std::string   varName         = (glu::isDataTypeMatrix(type) ? "m" : "v");
1995         const int           numCombinations = getDataTypeScalarSize(type);
1996         const glu::DataType scalarType      = glu::getDataTypeScalarType(type);
1997         const std::string   typeName        = glu::getDataTypeName(type);
1998         const bool                      isConst         = (scalarType != glu::TYPE_FLOAT) && (scalarType != glu::TYPE_DOUBLE);
1999
2000         std::ostringstream globalCode;
2001         {
2002                 // Build N matrices/vectors with specialization constant inserted at various locations in the constructor.
2003                 for (int combNdx = 0; combNdx < numCombinations; ++combNdx)
2004                         globalCode << ( isConst ? "const " : "" ) << typeName << " " << varName << combNdx << " = " << typeName << "("
2005                                            << generateInitializerListWithSpecConstant(type, false, 0, numCombinations, "sc0", combNdx) << ");\n";
2006         }
2007
2008         const bool        isBoolElement = (scalarType == glu::TYPE_BOOL);
2009         const int         specValue     = (isBoolElement ? 0 : 42);
2010         const std::string accumType     = glu::getDataTypeName(isBoolElement ? glu::TYPE_INT : scalarType);
2011
2012         const int size1 = glu::isDataTypeMatrix(type) ? glu::getDataTypeMatrixNumColumns(type) : glu::getDataTypeNumComponents(type);
2013         const int size2 = glu::isDataTypeMatrix(type) ? glu::getDataTypeMatrixNumRows(type)    : 0;
2014
2015         const CaseDefinition def =
2016         {
2017                 typeName,
2018                 makeVector(makeSpecConstant("sc0", 1u, scalarType, specValue)),
2019                 static_cast<VkDeviceSize>(getDataTypeScalarSizeBytes(type) * numCombinations),
2020                 "    " + accumType + " result[" + de::toString(numCombinations) + "];\n",
2021                 globalCode.str(),
2022                 generateShaderChecksumComputationCode(scalarType, varName, accumType, size1, size2, numCombinations),
2023                 computeExpectedValues(specValue, scalarType, numCombinations),
2024                 (scalarType == glu::TYPE_DOUBLE ? (FeatureFlags)FEATURE_SHADER_FLOAT_64 : (FeatureFlags)0),
2025                 false,
2026         };
2027         return def;
2028 }
2029
2030 //! Generate a CaseDefinition for a composite test using an array, or an array of array.
2031 //! If (size1, size2) = (N, 0) -> type array[N]
2032 //!                   = (N, M) -> type array[N][M]
2033 CaseDefinition makeArrayCompositeCaseDefinition (const glu::DataType elemType, const int size1, const int size2 = 0)
2034 {
2035         using namespace composite_case_internal;
2036
2037         DE_ASSERT(size1 > 0);
2038
2039         const bool        isArrayOfArray  = (size2 > 0);
2040         const std::string varName                 = "a";
2041         const std::string arraySizeDecl   = "[" + de::toString(size1) + "]" + (isArrayOfArray ? "[" + de::toString(size2) + "]" : "");
2042         const int         numCombinations = (isArrayOfArray ? size1 * size2 : size1);
2043         const std::string elemTypeName    (glu::getDataTypeName(elemType));
2044
2045         std::ostringstream globalCode;
2046         {
2047                 // Create several arrays with specialization constant inserted in different positions.
2048                 for (int combNdx = 0; combNdx < numCombinations; ++combNdx)
2049                         globalCode << elemTypeName << " " << varName << combNdx << arraySizeDecl << " = "
2050                                            << elemTypeName << arraySizeDecl << "(" << generateArrayConstructorString(elemType, size1, size2, "sc0", combNdx) << ");\n";
2051         }
2052
2053         const glu::DataType scalarType = glu::getDataTypeScalarType(elemType);
2054         const bool          isBoolData = (scalarType == glu::TYPE_BOOL);
2055         const int           specValue  = (isBoolData ? 0 : 19);
2056         const std::string   caseName   = (isArrayOfArray ? "array_" : "") + elemTypeName;
2057         const std::string   accumType  = (glu::getDataTypeName(isBoolData ? glu::TYPE_INT : scalarType));
2058
2059         const CaseDefinition def =
2060         {
2061                 caseName,
2062                 makeVector(makeSpecConstant("sc0", 1u, scalarType, specValue)),
2063                 static_cast<VkDeviceSize>(getDataTypeScalarSizeBytes(elemType) * numCombinations),
2064                 "    " + accumType + " result[" + de::toString(numCombinations) + "];\n",
2065                 globalCode.str(),
2066                 generateShaderChecksumComputationCode(elemType, varName, accumType, size1, size2, numCombinations),
2067                 computeExpectedValues(specValue, scalarType, numCombinations),
2068                 (scalarType == glu::TYPE_DOUBLE ? (FeatureFlags)FEATURE_SHADER_FLOAT_64 : (FeatureFlags)0),
2069                 false,
2070         };
2071         return def;
2072 }
2073
2074 //! A basic struct case, where one member is a specialization constant, or a specialization constant composite
2075 //! (a matrix/vector with a spec. const. element).
2076 CaseDefinition makeStructCompositeCaseDefinition (const glu::DataType memberType)
2077 {
2078         using namespace composite_case_internal;
2079
2080         std::ostringstream globalCode;
2081         {
2082                 globalCode << "struct Data {\n"
2083                                    << "    int   i;\n"
2084                                    << "    float f;\n"
2085                                    << "    bool  b;\n"
2086                                    << "    " << glu::getDataTypeName(memberType) << " sc;\n"
2087                                    << "    uint  ui;\n"
2088                                    << "};\n"
2089                                    << "\n"
2090                                    << "Data s0 = Data(3, 2.0, true, " << glu::getDataTypeName(memberType) << "(sc0), 8u);\n";
2091         }
2092
2093         const glu::DataType scalarType   = glu::getDataTypeScalarType(memberType);
2094         const bool          isBoolData   = (scalarType == glu::TYPE_BOOL);
2095         const int           specValue    = (isBoolData ? 0 : 23);
2096         const int           checksum     = (3 + 2 + 1 + specValue + 8);  // matches the shader code
2097         const glu::DataType accumType    = (isBoolData ? glu::TYPE_INT : scalarType);
2098         const std::string   accumTypeStr = glu::getDataTypeName(accumType);
2099
2100         std::ostringstream mainCode;
2101         {
2102                 mainCode << "    " << accumTypeStr << " sum_s0 = " << accumTypeStr << "(0);\n"
2103                                  << "\n"
2104                                  << "    sum_s0 += " << accumTypeStr << "(s0.i);\n"
2105                                  << "    sum_s0 += " << accumTypeStr << "(s0.f);\n"
2106                                  << "    sum_s0 += " << accumTypeStr << "(s0.b);\n"
2107                                  << "    sum_s0 += " << accumTypeStr << "(s0.sc" << getFirstDataElementSubscriptString(memberType) << ");\n"
2108                                  << "    sum_s0 += " << accumTypeStr << "(s0.ui);\n"
2109                                  << "\n"
2110                                  << "    sb_out.result = sum_s0;\n";
2111         }
2112
2113         const std::string caseName = glu::getDataTypeName(memberType);
2114
2115         const CaseDefinition def =
2116         {
2117                 caseName,
2118                 makeVector(makeSpecConstant("sc0", 1u, scalarType, specValue)),
2119                 getDataTypeScalarSizeBytes(accumType),
2120                 "    " + accumTypeStr + " result;\n",
2121                 globalCode.str(),
2122                 mainCode.str(),
2123                 makeVector(OffsetValue(getDataTypeScalarSizeBytes(memberType), 0, makeValue(scalarType, checksum))),
2124                 (scalarType == glu::TYPE_DOUBLE ? (FeatureFlags)FEATURE_SHADER_FLOAT_64 : (FeatureFlags)0),
2125                 false,
2126         };
2127         return def;
2128 }
2129
2130 //! Specialization constants used in composites.
2131 tcu::TestCaseGroup* createCompositeTests (tcu::TestContext& testCtx, const VkShaderStageFlagBits shaderStage)
2132 {
2133         de::MovePtr<tcu::TestCaseGroup> compositeTests (new tcu::TestCaseGroup(testCtx, "composite", "specialization constants usage in composite types"));
2134
2135         // Vectors
2136         {
2137                 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "vector", ""));
2138
2139                 const glu::DataType types[] =
2140                 {
2141                         glu::TYPE_FLOAT_VEC2,
2142                         glu::TYPE_FLOAT_VEC3,
2143                         glu::TYPE_FLOAT_VEC4,
2144
2145                         glu::TYPE_DOUBLE_VEC2,
2146                         glu::TYPE_DOUBLE_VEC3,
2147                         glu::TYPE_DOUBLE_VEC4,
2148
2149                         glu::TYPE_BOOL_VEC2,
2150                         glu::TYPE_BOOL_VEC3,
2151                         glu::TYPE_BOOL_VEC4,
2152
2153                         glu::TYPE_INT_VEC2,
2154                         glu::TYPE_INT_VEC3,
2155                         glu::TYPE_INT_VEC4,
2156
2157                         glu::TYPE_UINT_VEC2,
2158                         glu::TYPE_UINT_VEC3,
2159                         glu::TYPE_UINT_VEC4,
2160                 };
2161                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); ++typeNdx)
2162                         group->addChild(new SpecConstantTest(testCtx, shaderStage, makeMatrixVectorCompositeCaseDefinition(types[typeNdx])));
2163
2164                 compositeTests->addChild(group.release());
2165         }
2166
2167         // Matrices
2168         {
2169                 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "matrix", ""));
2170
2171                 const glu::DataType types[] =
2172                 {
2173                         glu::TYPE_FLOAT_MAT2,
2174                         glu::TYPE_FLOAT_MAT2X3,
2175                         glu::TYPE_FLOAT_MAT2X4,
2176                         glu::TYPE_FLOAT_MAT3X2,
2177                         glu::TYPE_FLOAT_MAT3,
2178                         glu::TYPE_FLOAT_MAT3X4,
2179                         glu::TYPE_FLOAT_MAT4X2,
2180                         glu::TYPE_FLOAT_MAT4X3,
2181                         glu::TYPE_FLOAT_MAT4,
2182
2183                         glu::TYPE_DOUBLE_MAT2,
2184                         glu::TYPE_DOUBLE_MAT2X3,
2185                         glu::TYPE_DOUBLE_MAT2X4,
2186                         glu::TYPE_DOUBLE_MAT3X2,
2187                         glu::TYPE_DOUBLE_MAT3,
2188                         glu::TYPE_DOUBLE_MAT3X4,
2189                         glu::TYPE_DOUBLE_MAT4X2,
2190                         glu::TYPE_DOUBLE_MAT4X3,
2191                         glu::TYPE_DOUBLE_MAT4,
2192                 };
2193                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); ++typeNdx)
2194                         group->addChild(new SpecConstantTest(testCtx, shaderStage, makeMatrixVectorCompositeCaseDefinition(types[typeNdx])));
2195
2196                 compositeTests->addChild(group.release());
2197         }
2198
2199         const glu::DataType allTypes[] =
2200         {
2201                 glu::TYPE_FLOAT,
2202                 glu::TYPE_FLOAT_VEC2,
2203                 glu::TYPE_FLOAT_VEC3,
2204                 glu::TYPE_FLOAT_VEC4,
2205                 glu::TYPE_FLOAT_MAT2,
2206                 glu::TYPE_FLOAT_MAT2X3,
2207                 glu::TYPE_FLOAT_MAT2X4,
2208                 glu::TYPE_FLOAT_MAT3X2,
2209                 glu::TYPE_FLOAT_MAT3,
2210                 glu::TYPE_FLOAT_MAT3X4,
2211                 glu::TYPE_FLOAT_MAT4X2,
2212                 glu::TYPE_FLOAT_MAT4X3,
2213                 glu::TYPE_FLOAT_MAT4,
2214
2215                 glu::TYPE_DOUBLE,
2216                 glu::TYPE_DOUBLE_VEC2,
2217                 glu::TYPE_DOUBLE_VEC3,
2218                 glu::TYPE_DOUBLE_VEC4,
2219                 glu::TYPE_DOUBLE_MAT2,
2220                 glu::TYPE_DOUBLE_MAT2X3,
2221                 glu::TYPE_DOUBLE_MAT2X4,
2222                 glu::TYPE_DOUBLE_MAT3X2,
2223                 glu::TYPE_DOUBLE_MAT3,
2224                 glu::TYPE_DOUBLE_MAT3X4,
2225                 glu::TYPE_DOUBLE_MAT4X2,
2226                 glu::TYPE_DOUBLE_MAT4X3,
2227                 glu::TYPE_DOUBLE_MAT4,
2228
2229                 glu::TYPE_INT,
2230                 glu::TYPE_INT_VEC2,
2231                 glu::TYPE_INT_VEC3,
2232                 glu::TYPE_INT_VEC4,
2233
2234                 glu::TYPE_UINT,
2235                 glu::TYPE_UINT_VEC2,
2236                 glu::TYPE_UINT_VEC3,
2237                 glu::TYPE_UINT_VEC4,
2238
2239                 glu::TYPE_BOOL,
2240                 glu::TYPE_BOOL_VEC2,
2241                 glu::TYPE_BOOL_VEC3,
2242                 glu::TYPE_BOOL_VEC4,
2243         };
2244
2245         // Array cases
2246         {
2247                 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "array", ""));
2248
2249                 // Array of T
2250                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(allTypes); ++typeNdx)
2251                         group->addChild(new SpecConstantTest(testCtx, shaderStage, makeArrayCompositeCaseDefinition(allTypes[typeNdx], 3)));
2252
2253                 // Array of array of T
2254                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(allTypes); ++typeNdx)
2255                         group->addChild(new SpecConstantTest(testCtx, shaderStage, makeArrayCompositeCaseDefinition(allTypes[typeNdx], 3, 2)));
2256
2257                 // Special case - array of struct
2258                 {
2259                         const int checksum = (3 + 2 + 1) + (1 + 5 + 1) + (1 + 2 + 0);
2260                         const CaseDefinition def =
2261                         {
2262                                 "struct",
2263                                 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int   sc0 = 1;",    4, makeValueInt32  (3)),
2264                                                    SpecConstant(2u, "layout(constant_id = ${ID}) const float sc1 = 1.0;",  4, makeValueFloat32(5.0f)),
2265                                                    SpecConstant(3u, "layout(constant_id = ${ID}) const bool  sc2 = true;", 4, makeValueBool32 (false))),
2266                                 4,
2267                                 "    int result;\n",
2268
2269                                 "struct Data {\n"
2270                                 "    int   x;\n"
2271                                 "    float y;\n"
2272                                 "    bool  z;\n"
2273                                 "};\n"
2274                                 "\n"
2275                                 "Data a0[3] = Data[3](Data(sc0, 2.0, true), Data(1, sc1, true), Data(1, 2.0, sc2));\n",
2276
2277                                 "    int sum_a0 = 0;\n"
2278                                 "\n"
2279                                 "    for (int i = 0; i < 3; ++i)\n"
2280                                 "        sum_a0 += int(a0[i].x) + int(a0[i].y) + int(a0[i].z);\n"
2281                                 "\n"
2282                                 "    sb_out.result = sum_a0;\n",
2283
2284                                 makeVector(OffsetValue(4,  0, makeValueInt32(checksum))),
2285                                 (FeatureFlags)0,
2286                                 false,
2287                         };
2288
2289                         group->addChild(new SpecConstantTest(testCtx, shaderStage, def));
2290                 }
2291
2292                 compositeTests->addChild(group.release());
2293         }
2294
2295         // Struct cases
2296         {
2297                 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "struct", ""));
2298
2299                 // Struct with one member being a specialization constant (or spec. const. composite) of a given type
2300                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(allTypes); ++typeNdx)
2301                         group->addChild(new SpecConstantTest(testCtx, shaderStage, makeStructCompositeCaseDefinition(allTypes[typeNdx])));
2302
2303                 // Special case - struct with array
2304                 {
2305                         const int checksum = (1 + 2 + 31 + 4 + 0);
2306                         const CaseDefinition def =
2307                         {
2308                                 "array",
2309                                 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const float sc0 = 1.0;",  4, makeValueFloat32(31.0f))),
2310                                 4,
2311                                 "    float result;\n",
2312
2313                                 "struct Data {\n"
2314                                 "    int  i;\n"
2315                                 "    vec3 sc[3];\n"
2316                                 "    bool b;\n"
2317                                 "};\n"
2318                                 "\n"
2319                                 "Data s0 = Data(1, vec3[3](vec3(2.0), vec3(sc0), vec3(4.0)), false);\n",
2320
2321                                 "    float sum_s0 = 0;\n"
2322                                 "\n"
2323                                 "    sum_s0 += float(s0.i);\n"
2324                                 "    sum_s0 += float(s0.sc[0][0]);\n"
2325                                 "    sum_s0 += float(s0.sc[1][0]);\n"
2326                                 "    sum_s0 += float(s0.sc[2][0]);\n"
2327                                 "    sum_s0 += float(s0.b);\n"
2328                                 "\n"
2329                                 "    sb_out.result = sum_s0;\n",
2330
2331                                 makeVector(OffsetValue(4,  0, makeValueFloat32(static_cast<float>(checksum)))),
2332                                 (FeatureFlags)0,
2333                                 false,
2334                         };
2335
2336                         group->addChild(new SpecConstantTest(testCtx, shaderStage, def));
2337                 }
2338
2339                 // Special case - struct of struct
2340                 {
2341                         const int checksum = (1 + 2 + 11 + 4 + 1);
2342                         const CaseDefinition def =
2343                         {
2344                                 "struct",
2345                                 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 1;",  4, makeValueInt32(11))),
2346                                 4,
2347                                 "    int result;\n",
2348
2349                                 "struct Nested {\n"
2350                                 "    vec2  v;\n"
2351                                 "    int   sc;\n"
2352                                 "    float f;\n"
2353                                 "};\n"
2354                                 "\n"
2355                                 "struct Data {\n"
2356                                 "    uint   ui;\n"
2357                                 "    Nested s;\n"
2358                                 "    bool   b;\n"
2359                                 "};\n"
2360                                 "\n"
2361                                 "Data s0 = Data(1u, Nested(vec2(2.0), sc0, 4.0), true);\n",
2362
2363                                 "    int sum_s0 = 0;\n"
2364                                 "\n"
2365                                 "    sum_s0 += int(s0.ui);\n"
2366                                 "    sum_s0 += int(s0.s.v[0]);\n"
2367                                 "    sum_s0 += int(s0.s.sc);\n"
2368                                 "    sum_s0 += int(s0.s.f);\n"
2369                                 "    sum_s0 += int(s0.b);\n"
2370                                 "\n"
2371                                 "    sb_out.result = sum_s0;\n",
2372
2373                                 makeVector(OffsetValue(4,  0, makeValueInt32(checksum))),
2374                                 (FeatureFlags)0,
2375                                 false,
2376                         };
2377
2378                         group->addChild(new SpecConstantTest(testCtx, shaderStage, def));
2379                 }
2380
2381                 compositeTests->addChild(group.release());
2382         }
2383
2384         return compositeTests.release();
2385 }
2386
2387 } // anonymous ns
2388
2389 tcu::TestCaseGroup* createSpecConstantTests (tcu::TestContext& testCtx)
2390 {
2391         de::MovePtr<tcu::TestCaseGroup> allTests (new tcu::TestCaseGroup(testCtx, "spec_constant", "Specialization constants tests"));
2392         de::MovePtr<tcu::TestCaseGroup> graphicsGroup (new tcu::TestCaseGroup(testCtx, "graphics", ""));
2393
2394         struct StageDef
2395         {
2396                 tcu::TestCaseGroup*             parentGroup;
2397                 const char*                             name;
2398                 VkShaderStageFlagBits   stage;
2399         };
2400
2401         const StageDef stages[] =
2402         {
2403                 { graphicsGroup.get(),  "vertex",               VK_SHADER_STAGE_VERTEX_BIT                                      },
2404                 { graphicsGroup.get(),  "fragment",             VK_SHADER_STAGE_FRAGMENT_BIT                            },
2405                 { graphicsGroup.get(),  "tess_control", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT        },
2406                 { graphicsGroup.get(),  "tess_eval",    VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT     },
2407                 { graphicsGroup.get(),  "geometry",             VK_SHADER_STAGE_GEOMETRY_BIT                            },
2408                 { allTests.get(),               "compute",              VK_SHADER_STAGE_COMPUTE_BIT                                     },
2409         };
2410
2411         allTests->addChild(graphicsGroup.release());
2412
2413         for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
2414         {
2415                 const StageDef& stage = stages[stageNdx];
2416                 de::MovePtr<tcu::TestCaseGroup> stageGroup (new tcu::TestCaseGroup(testCtx, stage.name, ""));
2417
2418                 stageGroup->addChild(createDefaultValueTests       (testCtx, stage.stage));
2419                 stageGroup->addChild(createBasicSpecializationTests(testCtx, stage.stage));
2420                 stageGroup->addChild(createBuiltInOverrideTests    (testCtx, stage.stage));
2421                 stageGroup->addChild(createExpressionTests         (testCtx, stage.stage));
2422                 stageGroup->addChild(createCompositeTests          (testCtx, stage.stage));
2423
2424                 if (stage.stage == VK_SHADER_STAGE_COMPUTE_BIT)
2425                         stageGroup->addChild(createWorkGroupSizeTests(testCtx));
2426
2427                 stage.parentGroup->addChild(stageGroup.release());
2428         }
2429
2430         return allTests.release();
2431 }
2432
2433 } // pipeline
2434 } // vkt