Merge vulkan-cts-1.0 to vulkan-cts-1.0-dev
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / vktShaderLibrary.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 Google 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 ShaderLibrary Vulkan implementation
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktShaderLibrary.hpp"
25 #include "vktTestCase.hpp"
26
27 #include "vkPrograms.hpp"
28 #include "vkRef.hpp"
29 #include "vkRefUtil.hpp"
30 #include "vkMemUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkTypeUtil.hpp"
34
35 #include "gluShaderLibrary.hpp"
36 #include "gluShaderUtil.hpp"
37
38 #include "tcuStringTemplate.hpp"
39 #include "tcuTexture.hpp"
40 #include "tcuTestLog.hpp"
41 #include "tcuVector.hpp"
42 #include "tcuVectorUtil.hpp"
43
44 #include "deStringUtil.hpp"
45 #include "deArrayUtil.hpp"
46 #include "deMemory.h"
47
48 #include <sstream>
49 #include <map>
50
51 namespace vkt
52 {
53
54 using std::string;
55 using std::vector;
56 using std::map;
57 using std::pair;
58 using std::ostringstream;
59
60 using de::MovePtr;
61 using de::UniquePtr;
62
63 using glu::ShaderType;
64 using glu::ProgramSources;
65 using glu::DataType;
66
67 using glu::sl::ShaderCaseSpecification;
68 using glu::sl::ProgramSpecializationParams;
69 using glu::sl::RequiredExtension;
70 using glu::sl::Value;
71 using glu::sl::ValueBlock;
72
73 using tcu::TestStatus;
74 using tcu::StringTemplate;
75 using tcu::Vec2;
76 using tcu::ConstPixelBufferAccess;
77 using tcu::TextureFormat;
78 using tcu::TestLog;
79
80 using vk::SourceCollections;
81 using vk::Move;
82 using vk::Unique;
83
84 namespace
85 {
86
87 enum
88 {
89         REFERENCE_UNIFORM_BINDING       = 0,
90         USER_UNIFORM_BINDING            = 1
91 };
92
93 string getShaderName (ShaderType shaderType, size_t progNdx)
94 {
95         ostringstream str;
96         str << glu::getShaderTypeName(shaderType);
97         if (progNdx > 0)
98                 str << "_" << progNdx;
99         return str.str();
100 }
101
102 void genUniformBlock (ostringstream& out, const string& blockName, const string& instanceName, int setNdx, int bindingNdx, const vector<Value>& uniforms)
103 {
104         out << "layout(";
105
106         if (setNdx != 0)
107                 out << "set = " << setNdx << ", ";
108
109         out << "binding = " << bindingNdx << ", std140) uniform " << blockName << "\n"
110                 << "{\n";
111
112         for (vector<Value>::const_iterator val = uniforms.begin(); val != uniforms.end(); ++val)
113                 out << "\t" << glu::declare(val->type, val->name, 1) << ";\n";
114
115         out << "}";
116
117         if (!instanceName.empty())
118                 out << " " << instanceName;
119
120         out << ";\n";
121 }
122
123 void declareReferenceBlock (ostringstream& out, const ValueBlock& valueBlock)
124 {
125         if (!valueBlock.outputs.empty())
126                 genUniformBlock(out, "Reference", "ref", 0, REFERENCE_UNIFORM_BINDING, valueBlock.outputs);
127 }
128
129 void declareUniforms (ostringstream& out, const ValueBlock& valueBlock)
130 {
131         if (!valueBlock.uniforms.empty())
132                 genUniformBlock(out, "Uniforms", "", 0, USER_UNIFORM_BINDING, valueBlock.uniforms);
133 }
134
135 DataType getTransportType (DataType valueType)
136 {
137         if (isDataTypeBoolOrBVec(valueType))
138                 return glu::getDataTypeIntVec(getDataTypeScalarSize(valueType));
139         else
140                 return valueType;
141 }
142
143 int getNumTransportLocations (DataType valueType)
144 {
145         return isDataTypeMatrix(valueType) ? getDataTypeMatrixNumColumns(valueType) : 1;
146 }
147
148 // This functions builds a matching vertex shader for a 'both' case, when
149 // the fragment shader is being tested.
150 // We need to build attributes and varyings for each 'input'.
151 string genVertexShader (const ShaderCaseSpecification& spec)
152 {
153         ostringstream   res;
154         int                             curInputLoc             = 0;
155         int                             curOutputLoc    = 0;
156
157         res << glu::getGLSLVersionDeclaration(spec.targetVersion) << "\n";
158
159         // Declarations (position + attribute/varying for each input).
160         res << "precision highp float;\n";
161         res << "precision highp int;\n";
162         res << "\n";
163         res << "layout(location = 0) in highp vec4 dEQP_Position;\n";
164         curInputLoc += 1;
165
166         for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
167         {
168                 const Value&            val                                     = spec.values.inputs[ndx];
169                 const DataType          valueType                       = val.type.getBasicType();
170                 const DataType          transportType           = getTransportType(valueType);
171                 const char* const       transportTypeStr        = getDataTypeName(transportType);
172                 const int                       numLocs                         = getNumTransportLocations(valueType);
173
174                 res << "layout(location = " << curInputLoc << ") in " << transportTypeStr << " a_" << val.name << ";\n";
175                 res << "layout(location = " << curOutputLoc << ") flat out " << transportTypeStr << " " << (transportType != valueType ? "v_" : "") << val.name << ";\n";
176
177                 curInputLoc             += numLocs;
178                 curOutputLoc    += numLocs;
179         }
180         res << "\n";
181
182         // Main function.
183         // - gl_Position = dEQP_Position;
184         // - for each input: write attribute directly to varying
185         res << "void main()\n";
186         res << "{\n";
187         res << "        gl_Position = dEQP_Position;\n";
188         for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
189         {
190                 const Value&    val             = spec.values.inputs[ndx];
191                 const string&   name    = val.name;
192
193                 res << "        " << (getTransportType(val.type.getBasicType()) != val.type.getBasicType() ? "v_" : "")
194                         << name << " = a_" << name << ";\n";
195         }
196
197         res << "}\n";
198         return res.str();
199 }
200
201 void genCompareOp (ostringstream& output, const char* dstVec4Var, const ValueBlock& valueBlock, const char* checkVarName)
202 {
203         bool isFirstOutput = true;
204
205         for (size_t ndx = 0; ndx < valueBlock.outputs.size(); ndx++)
206         {
207                 const Value&    val             = valueBlock.outputs[ndx];
208
209                 // Check if we're only interested in one variable (then skip if not the right one).
210                 if (checkVarName && val.name != checkVarName)
211                         continue;
212
213                 // Prefix.
214                 if (isFirstOutput)
215                 {
216                         output << "bool RES = ";
217                         isFirstOutput = false;
218                 }
219                 else
220                         output << "RES = RES && ";
221
222                 // Generate actual comparison.
223                 if (getDataTypeScalarType(val.type.getBasicType()) == glu::TYPE_FLOAT)
224                         output << "isOk(" << val.name << ", ref." << val.name << ", 0.05);\n";
225                 else
226                         output << "isOk(" << val.name << ", ref." << val.name << ");\n";
227         }
228
229         if (isFirstOutput)
230                 output << dstVec4Var << " = vec4(1.0);\n";
231         else
232                 output << dstVec4Var << " = vec4(RES, RES, RES, 1.0);\n";
233 }
234
235 string genFragmentShader (const ShaderCaseSpecification& spec)
236 {
237         ostringstream   shader;
238         ostringstream   setup;
239         int                             curInLoc        = 0;
240
241         shader << glu::getGLSLVersionDeclaration(spec.targetVersion) << "\n";
242
243         shader << "precision highp float;\n";
244         shader << "precision highp int;\n";
245         shader << "\n";
246
247         shader << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
248         shader << "\n";
249
250         genCompareFunctions(shader, spec.values, false);
251         shader << "\n";
252
253         // Declarations (varying, reference for each output).
254         for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++)
255         {
256                 const Value&            val                                     = spec.values.outputs[ndx];
257                 const DataType          valueType                       = val.type.getBasicType();
258                 const char*     const   valueTypeStr            = getDataTypeName(valueType);
259                 const DataType          transportType           = getTransportType(valueType);
260                 const char* const       transportTypeStr        = getDataTypeName(transportType);
261                 const int                       numLocs                         = getNumTransportLocations(valueType);
262
263                 shader << "layout(location = " << curInLoc << ") flat in " << transportTypeStr << " " << (valueType != transportType ? "v_" : "") << val.name << ";\n";
264
265                 if (valueType != transportType)
266                         setup << "      " << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(v_" << val.name << ");\n";
267
268                 curInLoc += numLocs;
269         }
270
271         declareReferenceBlock(shader, spec.values);
272
273         shader << "\n";
274         shader << "void main()\n";
275         shader << "{\n";
276
277         shader << setup.str();
278
279         shader << "     ";
280         genCompareOp(shader, "dEQP_FragColor", spec.values, DE_NULL);
281
282         shader << "}\n";
283         return shader.str();
284 }
285
286 // Specialize a shader for the vertex shader test case.
287 string specializeVertexShader (const ShaderCaseSpecification& spec, const string& src)
288 {
289         ostringstream           decl;
290         ostringstream           setup;
291         ostringstream           output;
292         int                                     curInputLoc             = 0;
293         int                                     curOutputLoc    = 0;
294
295         // generated from "both" case
296         DE_ASSERT(spec.caseType == glu::sl::CASETYPE_VERTEX_ONLY);
297
298         // Output (write out position).
299         output << "gl_Position = dEQP_Position;\n";
300
301         // Declarations (position + attribute for each input, varying for each output).
302         decl << "layout(location = 0) in highp vec4 dEQP_Position;\n";
303         curInputLoc += 1;
304
305         for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
306         {
307                 const Value&            val                                     = spec.values.inputs[ndx];
308                 const DataType          valueType                       = val.type.getBasicType();
309                 const char*     const   valueTypeStr            = getDataTypeName(valueType);
310                 const DataType          transportType           = getTransportType(valueType);
311                 const char* const       transportTypeStr        = getDataTypeName(transportType);
312                 const int                       numLocs                         = getNumTransportLocations(valueType);
313
314                 decl << "layout(location = " << curInputLoc << ") in ";
315
316                 curInputLoc += numLocs;
317
318                 if (valueType == transportType)
319                         decl << transportTypeStr << " " << val.name << ";\n";
320                 else
321                 {
322                         decl << transportTypeStr << " a_" << val.name << ";\n";
323                         setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(a_" << val.name << ");\n";
324                 }
325         }
326
327         declareUniforms(decl, spec.values);
328
329         for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++)
330         {
331                 const Value&            val                                     = spec.values.outputs[ndx];
332                 const DataType          valueType                       = val.type.getBasicType();
333                 const char*     const   valueTypeStr            = getDataTypeName(valueType);
334                 const DataType          transportType           = getTransportType(valueType);
335                 const char* const       transportTypeStr        = getDataTypeName(transportType);
336                 const int                       numLocs                         = getNumTransportLocations(valueType);
337
338                 decl << "layout(location = " << curOutputLoc << ") flat out ";
339
340                 curOutputLoc += numLocs;
341
342                 if (valueType == transportType)
343                         decl << transportTypeStr << " " << val.name << ";\n";
344                 else
345                 {
346                         decl << transportTypeStr << " v_" << val.name << ";\n";
347                         decl << valueTypeStr << " " << val.name << ";\n";
348
349                         output << "v_" << val.name << " = " << transportTypeStr << "(" << val.name << ");\n";
350                 }
351         }
352
353         // Shader specialization.
354         map<string, string> params;
355         params.insert(pair<string, string>("DECLARATIONS", decl.str()));
356         params.insert(pair<string, string>("SETUP", setup.str()));
357         params.insert(pair<string, string>("OUTPUT", output.str()));
358         params.insert(pair<string, string>("POSITION_FRAG_COLOR", "gl_Position"));
359
360         StringTemplate  tmpl    (src);
361         const string    baseSrc = tmpl.specialize(params);
362         const string    withExt = injectExtensionRequirements(baseSrc, spec.programs[0].requiredExtensions, glu::SHADERTYPE_VERTEX);
363
364         return withExt;
365 }
366
367 // Specialize a shader for the fragment shader test case.
368 string specializeFragmentShader (const ShaderCaseSpecification& spec, const string& src)
369 {
370         ostringstream           decl;
371         ostringstream           setup;
372         ostringstream           output;
373         int                                     curInputLoc     = 0;
374
375         // generated from "both" case
376         DE_ASSERT(spec.caseType == glu::sl::CASETYPE_FRAGMENT_ONLY);
377
378         genCompareFunctions(decl, spec.values, false);
379         genCompareOp(output, "dEQP_FragColor", spec.values, DE_NULL);
380
381         decl << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
382
383         for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
384         {
385                 const Value&            val                                     = spec.values.inputs[ndx];
386                 const DataType          valueType                       = val.type.getBasicType();
387                 const char*     const   valueTypeStr            = getDataTypeName(valueType);
388                 const DataType          transportType           = getTransportType(valueType);
389                 const char* const       transportTypeStr        = getDataTypeName(transportType);
390                 const int                       numLocs                         = getNumTransportLocations(valueType);
391
392                 decl << "layout(location = " << curInputLoc << ") flat in ";
393
394                 curInputLoc += numLocs;
395
396                 if (valueType == transportType)
397                         decl << transportTypeStr << " " << val.name << ";\n";
398                 else
399                 {
400                         decl << transportTypeStr << " v_" << val.name << ";\n";
401                         setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(v_" << val.name << ");\n";
402                 }
403         }
404
405         declareUniforms(decl, spec.values);
406         declareReferenceBlock(decl, spec.values);
407
408         for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++)
409         {
410                 const Value&            val                             = spec.values.outputs[ndx];
411                 const DataType          basicType               = val.type.getBasicType();
412                 const char* const       refTypeStr              = getDataTypeName(basicType);
413
414                 decl << refTypeStr << " " << val.name << ";\n";
415         }
416
417         // Shader specialization.
418         map<string, string> params;
419         params.insert(pair<string, string>("DECLARATIONS", decl.str()));
420         params.insert(pair<string, string>("SETUP", setup.str()));
421         params.insert(pair<string, string>("OUTPUT", output.str()));
422         params.insert(pair<string, string>("POSITION_FRAG_COLOR", "dEQP_FragColor"));
423
424         StringTemplate  tmpl    (src);
425         const string    baseSrc = tmpl.specialize(params);
426         const string    withExt = injectExtensionRequirements(baseSrc, spec.programs[0].requiredExtensions, glu::SHADERTYPE_FRAGMENT);
427
428         return withExt;
429 }
430
431 map<string, string> generateVertexSpecialization (const ProgramSpecializationParams& specParams)
432 {
433         ostringstream                   decl;
434         ostringstream                   setup;
435         map<string, string>             params;
436         int                                             curInputLoc             = 0;
437
438         decl << "layout(location = 0) in highp vec4 dEQP_Position;\n";
439         curInputLoc += 1;
440
441         for (size_t ndx = 0; ndx < specParams.caseSpec.values.inputs.size(); ndx++)
442         {
443                 const Value&            val                                     = specParams.caseSpec.values.inputs[ndx];
444                 const DataType          valueType                       = val.type.getBasicType();
445                 const char*     const   valueTypeStr            = getDataTypeName(valueType);
446                 const DataType          transportType           = getTransportType(valueType);
447                 const char* const       transportTypeStr        = getDataTypeName(transportType);
448                 const int                       numLocs                         = getNumTransportLocations(valueType);
449
450                 decl << "layout(location = " << curInputLoc << ") in ";
451
452                 curInputLoc += numLocs;
453
454                 if (valueType == transportType)
455                         decl << transportTypeStr << " " << val.name << ";\n";
456                 else
457                 {
458                         decl << transportTypeStr << " a_" << val.name << ";\n";
459                         setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(a_" << val.name << ");\n";
460                 }
461         }
462
463         declareUniforms(decl, specParams.caseSpec.values);
464
465         params.insert(pair<string, string>("VERTEX_DECLARATIONS",       decl.str()));
466         params.insert(pair<string, string>("VERTEX_SETUP",                      setup.str()));
467         params.insert(pair<string, string>("VERTEX_OUTPUT",                     string("gl_Position = dEQP_Position;\n")));
468
469         return params;
470 }
471
472 map<string, string> generateFragmentSpecialization (const ProgramSpecializationParams& specParams)
473 {
474         ostringstream           decl;
475         ostringstream           output;
476         map<string, string>     params;
477
478         genCompareFunctions(decl, specParams.caseSpec.values, false);
479         genCompareOp(output, "dEQP_FragColor", specParams.caseSpec.values, DE_NULL);
480
481         decl << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
482
483         for (size_t ndx = 0; ndx < specParams.caseSpec.values.outputs.size(); ndx++)
484         {
485                 const Value&            val                     = specParams.caseSpec.values.outputs[ndx];
486                 const char*     const   refTypeStr      = getDataTypeName(val.type.getBasicType());
487
488                 decl << refTypeStr << " " << val.name << ";\n";
489         }
490
491         declareReferenceBlock(decl, specParams.caseSpec.values);
492         declareUniforms(decl, specParams.caseSpec.values);
493
494         params.insert(pair<string, string>("FRAGMENT_DECLARATIONS",     decl.str()));
495         params.insert(pair<string, string>("FRAGMENT_OUTPUT",           output.str()));
496         params.insert(pair<string, string>("FRAG_COLOR",                        "dEQP_FragColor"));
497
498         return params;
499 }
500
501 map<string, string> generateGeometrySpecialization (const ProgramSpecializationParams& specParams)
502 {
503         ostringstream           decl;
504         map<string, string>     params;
505
506         decl << "layout (triangles) in;\n";
507         decl << "layout (triangle_strip, max_vertices=3) out;\n";
508         decl << "\n";
509
510         declareUniforms(decl, specParams.caseSpec.values);
511
512         params.insert(pair<string, string>("GEOMETRY_DECLARATIONS",             decl.str()));
513
514         return params;
515 }
516
517 map<string, string> generateTessControlSpecialization (const ProgramSpecializationParams& specParams)
518 {
519         ostringstream           decl;
520         ostringstream           output;
521         map<string, string>     params;
522
523         decl << "layout (vertices=3) out;\n";
524         decl << "\n";
525
526         declareUniforms(decl, specParams.caseSpec.values);
527
528         output <<       "gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
529                                 "gl_TessLevelInner[0] = 2.0;\n"
530                                 "gl_TessLevelInner[1] = 2.0;\n"
531                                 "gl_TessLevelOuter[0] = 2.0;\n"
532                                 "gl_TessLevelOuter[1] = 2.0;\n"
533                                 "gl_TessLevelOuter[2] = 2.0;\n"
534                                 "gl_TessLevelOuter[3] = 2.0;";
535
536         params.insert(pair<string, string>("TESSELLATION_CONTROL_DECLARATIONS", decl.str()));
537         params.insert(pair<string, string>("TESSELLATION_CONTROL_OUTPUT",               output.str()));
538         params.insert(pair<string, string>("GL_MAX_PATCH_VERTICES",                             de::toString(specParams.maxPatchVertices)));
539
540         return params;
541 }
542
543 map<string, string> generateTessEvalSpecialization (const ProgramSpecializationParams& specParams)
544 {
545         ostringstream           decl;
546         ostringstream           output;
547         map<string, string>     params;
548
549         decl << "layout (triangles) in;\n";
550         decl << "\n";
551
552         declareUniforms(decl, specParams.caseSpec.values);
553
554         output <<       "gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position + gl_TessCoord[1] * gl_in[1].gl_Position + gl_TessCoord[2] * gl_in[2].gl_Position;\n";
555
556         params.insert(pair<string, string>("TESSELLATION_EVALUATION_DECLARATIONS",      decl.str()));
557         params.insert(pair<string, string>("TESSELLATION_EVALUATION_OUTPUT",            output.str()));
558         params.insert(pair<string, string>("GL_MAX_PATCH_VERTICES",                                     de::toString(specParams.maxPatchVertices)));
559
560         return params;
561 }
562
563 void specializeShaderSources (ProgramSources&                                           dst,
564                                                           const ProgramSources&                                 src,
565                                                           const ProgramSpecializationParams&    specParams,
566                                                           glu::ShaderType                                               shaderType,
567                                                           map<string, string>                                   (*specializationGenerator) (const ProgramSpecializationParams& specParams))
568 {
569         if (!src.sources[shaderType].empty())
570         {
571                 const map<string, string>       tmplParams      = specializationGenerator(specParams);
572
573                 for (size_t ndx = 0; ndx < src.sources[shaderType].size(); ++ndx)
574                 {
575                         const StringTemplate    tmpl                    (src.sources[shaderType][ndx]);
576                         const string                    baseGLSLCode    = tmpl.specialize(tmplParams);
577                         const string                    sourceWithExts  = injectExtensionRequirements(baseGLSLCode, specParams.requiredExtensions, shaderType);
578
579                         dst << glu::ShaderSource(shaderType, sourceWithExts);
580                 }
581         }
582 }
583
584 void specializeProgramSources (glu::ProgramSources&                                     dst,
585                                                            const glu::ProgramSources&                   src,
586                                                            const ProgramSpecializationParams&   specParams)
587 {
588         specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_VERTEX,                                   generateVertexSpecialization);
589         specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_FRAGMENT,                                 generateFragmentSpecialization);
590         specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_GEOMETRY,                                 generateGeometrySpecialization);
591         specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_TESSELLATION_CONTROL,             generateTessControlSpecialization);
592         specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_TESSELLATION_EVALUATION,  generateTessEvalSpecialization);
593
594         dst << glu::ProgramSeparable(src.separable);
595 }
596
597 struct ValueBufferLayout
598 {
599         struct Entry
600         {
601                 int             offset;
602                 int             vecStride;      //! Applies to matrices only
603
604                 Entry (void) : offset(0), vecStride(0) {}
605                 Entry (int offset_, int vecStride_) : offset(offset_), vecStride(vecStride_) {}
606         };
607
608         vector<Entry>   entries;
609         int                             size;
610
611         ValueBufferLayout (void) : size(0) {}
612 };
613
614 ValueBufferLayout computeStd140Layout (const vector<Value>& values)
615 {
616         ValueBufferLayout layout;
617
618         layout.entries.resize(values.size());
619
620         for (size_t ndx = 0; ndx < values.size(); ++ndx)
621         {
622                 const DataType  basicType       = values[ndx].type.getBasicType();
623                 const bool              isMatrix        = isDataTypeMatrix(basicType);
624                 const int               numVecs         = isMatrix ? getDataTypeMatrixNumColumns(basicType) : 1;
625                 const DataType  vecType         = isMatrix ? glu::getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType)) : basicType;
626                 const int               vecSize         = getDataTypeScalarSize(vecType);
627                 const int               alignment       = ((isMatrix || vecSize == 3) ? 4 : vecSize)*int(sizeof(deUint32));
628
629                 layout.size                     = deAlign32(layout.size, alignment);
630                 layout.entries[ndx] = ValueBufferLayout::Entry(layout.size, alignment);
631                 layout.size                     += alignment*(numVecs-1) + vecSize*int(sizeof(deUint32));
632         }
633
634         return layout;
635 }
636
637 ValueBufferLayout computeStd430Layout (const vector<Value>& values)
638 {
639         ValueBufferLayout layout;
640
641         layout.entries.resize(values.size());
642
643         for (size_t ndx = 0; ndx < values.size(); ++ndx)
644         {
645                 const DataType  basicType       = values[ndx].type.getBasicType();
646                 const int               numVecs         = isDataTypeMatrix(basicType) ? getDataTypeMatrixNumColumns(basicType) : 1;
647                 const DataType  vecType         = isDataTypeMatrix(basicType) ? glu::getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType)) : basicType;
648                 const int               vecSize         = getDataTypeScalarSize(vecType);
649                 const int               alignment       = (vecSize == 3 ? 4 : vecSize)*int(sizeof(deUint32));
650
651                 layout.size                     = deAlign32(layout.size, alignment);
652                 layout.entries[ndx] = ValueBufferLayout::Entry(layout.size, alignment);
653                 layout.size                     += alignment*(numVecs-1) + vecSize*int(sizeof(deUint32));
654         }
655
656         return layout;
657 }
658
659 void copyToLayout (void* dst, const ValueBufferLayout::Entry& entryLayout, const Value& value, int arrayNdx)
660 {
661         const DataType  basicType       = value.type.getBasicType();
662         const int               scalarSize      = getDataTypeScalarSize(basicType);
663         const int               numVecs         = isDataTypeMatrix(basicType) ? getDataTypeMatrixNumColumns(basicType) : 1;
664         const int               numComps        = isDataTypeMatrix(basicType) ? getDataTypeMatrixNumRows(basicType) : scalarSize;
665
666         DE_ASSERT(size_t((arrayNdx+1)*scalarSize) <= value.elements.size());
667
668         if (isDataTypeBoolOrBVec(basicType))
669         {
670                 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
671                 {
672                         for (int compNdx = 0; compNdx < numComps; compNdx++)
673                         {
674                                 const deUint32 data = value.elements[arrayNdx*scalarSize + vecNdx*numComps + compNdx].bool32 ? ~0u : 0u;
675
676                                 deMemcpy((deUint8*)dst + entryLayout.offset + vecNdx*entryLayout.vecStride + compNdx * sizeof(deUint32),
677                                                  &data,
678                                                  sizeof(deUint32));
679                         }
680                 }
681         }
682         else
683         {
684                 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
685                         deMemcpy((deUint8*)dst + entryLayout.offset + vecNdx*entryLayout.vecStride,
686                                          &value.elements[arrayNdx*scalarSize + vecNdx*numComps],
687                                          numComps*sizeof(deUint32));
688         }
689 }
690
691 void copyToLayout (void* dst, const ValueBufferLayout& layout, const vector<Value>& values, int arrayNdx)
692 {
693         DE_ASSERT(layout.entries.size() == values.size());
694
695         for (size_t ndx = 0; ndx < values.size(); ndx++)
696                 copyToLayout(dst, layout.entries[ndx], values[ndx], arrayNdx);
697 }
698
699 deUint32 getShaderStages (const ShaderCaseSpecification& spec)
700 {
701         if (spec.caseType == glu::sl::CASETYPE_COMPLETE)
702         {
703                 deUint32        stages  = 0u;
704
705                 for (size_t progNdx = 0; progNdx < spec.programs.size(); progNdx++)
706                 {
707                         for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
708                         {
709                                 if (!spec.programs[progNdx].sources.sources[shaderType].empty())
710                                         stages |= (1u << shaderType);
711                         }
712                 }
713
714                 return stages;
715         }
716         else
717                 return (1u << glu::SHADERTYPE_VERTEX) | (1u << glu::SHADERTYPE_FRAGMENT);
718 }
719
720 class PipelineProgram
721 {
722 public:
723                                                                 PipelineProgram         (Context& context, const ShaderCaseSpecification& spec);
724
725         deUint32                                        getStages                       (void) const                                    { return m_stages;                                                      }
726
727         bool                                            hasShader                       (glu::ShaderType type) const    { return (m_stages & (1u << type)) != 0;        }
728         vk::VkShaderModule                      getShader                       (glu::ShaderType type) const    { return *m_shaderModules[type];                        }
729
730 private:
731         const deUint32                          m_stages;
732         Move<vk::VkShaderModule>        m_shaderModules[glu::SHADERTYPE_LAST];
733 };
734
735 PipelineProgram::PipelineProgram (Context& context, const ShaderCaseSpecification& spec)
736         : m_stages(getShaderStages(spec))
737 {
738         // \note Currently only a single source program is supported as framework lacks SPIR-V linking capability
739         TCU_CHECK_INTERNAL(spec.programs.size() == 1);
740
741         for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
742         {
743                 if ((m_stages & (1u << shaderType)) != 0)
744                 {
745                         m_shaderModules[shaderType]     = vk::createShaderModule(context.getDeviceInterface(), context.getDevice(),
746                                                                                                                                  context.getBinaryCollection().get(getShaderName((glu::ShaderType)shaderType, 0)), 0u);
747                 }
748         }
749 }
750
751 vector<vk::VkPipelineShaderStageCreateInfo> getPipelineShaderStageCreateInfo (const PipelineProgram& program)
752 {
753         vector<vk::VkPipelineShaderStageCreateInfo>     infos;
754
755         for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
756         {
757                 if (program.hasShader((glu::ShaderType)shaderType))
758                 {
759                         const vk::VkPipelineShaderStageCreateInfo info =
760                         {
761                                 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,        // sType
762                                 DE_NULL,                                                                                                        // pNext
763                                 (vk::VkPipelineShaderStageCreateFlags)0,
764                                 vk::getVkShaderStage((glu::ShaderType)shaderType),                      // stage
765                                 program.getShader((glu::ShaderType)shaderType),                         // module
766                                 "main",
767                                 DE_NULL,                                                                                                        // pSpecializationInfo
768                         };
769
770                         infos.push_back(info);
771                 }
772         }
773
774         return infos;
775 }
776
777 Move<vk::VkBuffer> createBuffer (Context& context, vk::VkDeviceSize size, vk::VkBufferUsageFlags usageFlags)
778 {
779         const deUint32                                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
780         const vk::VkBufferCreateInfo    params                          =
781         {
782                 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,       // sType
783                 DE_NULL,                                                                        // pNext
784                 0u,                                                                                     // flags
785                 size,                                                                           // size
786                 usageFlags,                                                                     // usage
787                 vk::VK_SHARING_MODE_EXCLUSIVE,                          // sharingMode
788                 1u,                                                                                     // queueFamilyCount
789                 &queueFamilyIndex,                                                      // pQueueFamilyIndices
790         };
791
792         return vk::createBuffer(context.getDeviceInterface(), context.getDevice(), &params);
793 }
794
795 Move<vk::VkImage> createImage2D (Context& context, deUint32 width, deUint32 height, vk::VkFormat format, vk::VkImageTiling tiling, vk::VkImageUsageFlags usageFlags)
796 {
797         const deUint32                                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
798         const vk::VkImageCreateInfo             params                          =
799         {
800                 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,        // sType
801                 DE_NULL,                                                                        // pNext
802                 0u,                                                                                     // flags
803                 vk::VK_IMAGE_TYPE_2D,                                           // imageType
804                 format,                                                                         // format
805                 { width, height, 1u },                                          // extent
806                 1u,                                                                                     // mipLevels
807                 1u,                                                                                     // arraySize
808                 vk::VK_SAMPLE_COUNT_1_BIT,                                      // samples
809                 tiling,                                                                         // tiling
810                 usageFlags,                                                                     // usage
811                 vk::VK_SHARING_MODE_EXCLUSIVE,                          // sharingMode
812                 1u,                                                                                     // queueFamilyCount
813                 &queueFamilyIndex,                                                      // pQueueFamilyIndices
814                 vk::VK_IMAGE_LAYOUT_UNDEFINED,                          // initialLayout
815         };
816
817         return vk::createImage(context.getDeviceInterface(), context.getDevice(), &params);
818 }
819
820 Move<vk::VkImageView> createAttachmentView (Context& context, vk::VkImage image, vk::VkFormat format)
821 {
822         const vk::VkImageViewCreateInfo params                          =
823         {
824                 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,           // sType
825                 DE_NULL,                                                                                        // pNext
826                 0u,                                                                                                     // flags
827                 image,                                                                                          // image
828                 vk::VK_IMAGE_VIEW_TYPE_2D,                                                      // viewType
829                 format,                                                                                         // format
830                 vk::makeComponentMappingRGBA(),                                         // channels
831                 {
832                         vk::VK_IMAGE_ASPECT_COLOR_BIT,                                          // aspectMask
833                         0u,                                                                                                     // baseMipLevel
834                         1u,                                                                                                     // mipLevels
835                         0u,                                                                                                     // baseArrayLayer
836                         1u,                                                                                                     // arraySize
837                 },                                                                                                      // subresourceRange
838         };
839
840         return vk::createImageView(context.getDeviceInterface(), context.getDevice(), &params);
841 }
842
843 Move<vk::VkRenderPass> createRenderPass (Context& context, vk::VkFormat colorAttFormat)
844 {
845         const vk::VkAttachmentDescription       colorAttDesc            =
846         {
847                 0u,                                                                                                             // flags
848                 colorAttFormat,                                                                                 // format
849                 vk::VK_SAMPLE_COUNT_1_BIT,                                                              // samples
850                 vk::VK_ATTACHMENT_LOAD_OP_CLEAR,                                                // loadOp
851                 vk::VK_ATTACHMENT_STORE_OP_STORE,                                               // storeOp
852                 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                    // stencilLoadOp
853                 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,                                   // stencilStoreOp
854                 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                   // initialLayout
855                 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                   // finalLayout
856         };
857         const vk::VkAttachmentReference         colorAttRef                     =
858         {
859                 0u,                                                                                                             // attachment
860                 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                   // layout
861         };
862         const vk::VkAttachmentReference         dsAttRef                        =
863         {
864                 vk::VK_NO_ATTACHMENT,                                                                   // attachment
865                 vk::VK_IMAGE_LAYOUT_GENERAL,                                                    // layout
866         };
867         const vk::VkSubpassDescription          subpassDesc                     =
868         {
869                 (vk::VkSubpassDescriptionFlags)0,
870                 vk::VK_PIPELINE_BIND_POINT_GRAPHICS,                                    // pipelineBindPoint
871                 0u,                                                                                                             // inputCount
872                 DE_NULL,                                                                                                // pInputAttachments
873                 1u,                                                                                                             // colorCount
874                 &colorAttRef,                                                                                   // pColorAttachments
875                 DE_NULL,                                                                                                // pResolveAttachments
876                 &dsAttRef,                                                                                              // depthStencilAttachment
877                 0u,                                                                                                             // preserveCount
878                 DE_NULL,                                                                                                // pPreserveAttachments
879
880         };
881         const vk::VkRenderPassCreateInfo        renderPassParams        =
882         {
883                 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                  // sType
884                 DE_NULL,                                                                                                // pNext
885                 (vk::VkRenderPassCreateFlags)0,
886                 1u,                                                                                                             // attachmentCount
887                 &colorAttDesc,                                                                                  // pAttachments
888                 1u,                                                                                                             // subpassCount
889                 &subpassDesc,                                                                                   // pSubpasses
890                 0u,                                                                                                             // dependencyCount
891                 DE_NULL,                                                                                                // pDependencies
892         };
893
894         return vk::createRenderPass(context.getDeviceInterface(), context.getDevice(), &renderPassParams);
895 }
896
897 vk::VkShaderStageFlags getVkStageFlags (deUint32 stages)
898 {
899         vk::VkShaderStageFlags  vkStages        = 0u;
900
901         for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
902         {
903                 if ((stages & (1u << shaderType)) != 0)
904                         vkStages |= vk::getVkShaderStage((glu::ShaderType)shaderType);
905         }
906
907         return vkStages;
908 }
909
910 Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (Context& context, deUint32 shaderStages)
911 {
912         DE_STATIC_ASSERT(REFERENCE_UNIFORM_BINDING      == 0);
913         DE_STATIC_ASSERT(USER_UNIFORM_BINDING           == 1);
914
915         return vk::DescriptorSetLayoutBuilder()
916                                 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT)
917                                 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, getVkStageFlags(shaderStages))
918                                 .build(context.getDeviceInterface(), context.getDevice());
919 }
920
921 Move<vk::VkPipelineLayout> createPipelineLayout (Context& context, vk::VkDescriptorSetLayout descriptorSetLayout)
922 {
923         const vk::VkPipelineLayoutCreateInfo    params  =
924         {
925                 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,      // sType
926                 DE_NULL,                                                                                        // pNext
927                 (vk::VkPipelineLayoutCreateFlags)0,
928                 1u,                                                                                                     // descriptorSetCount
929                 &descriptorSetLayout,                                                           // pSetLayouts
930                 0u,                                                                                                     // pushConstantRangeCount
931                 DE_NULL,                                                                                        // pPushConstantRanges
932         };
933
934         return vk::createPipelineLayout(context.getDeviceInterface(), context.getDevice(), &params);
935 }
936
937 vk::VkFormat getVecFormat (DataType scalarType, int scalarSize)
938 {
939         switch (scalarType)
940         {
941                 case glu::TYPE_FLOAT:
942                 {
943                         const vk::VkFormat vecFmts[] =
944                         {
945                                 vk::VK_FORMAT_R32_SFLOAT,
946                                 vk::VK_FORMAT_R32G32_SFLOAT,
947                                 vk::VK_FORMAT_R32G32B32_SFLOAT,
948                                 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
949                         };
950                         return de::getSizedArrayElement<4>(vecFmts, scalarSize-1);
951                 }
952
953                 case glu::TYPE_INT:
954                 {
955                         const vk::VkFormat vecFmts[] =
956                         {
957                                 vk::VK_FORMAT_R32_SINT,
958                                 vk::VK_FORMAT_R32G32_SINT,
959                                 vk::VK_FORMAT_R32G32B32_SINT,
960                                 vk::VK_FORMAT_R32G32B32A32_SINT,
961                         };
962                         return de::getSizedArrayElement<4>(vecFmts, scalarSize-1);
963                 }
964
965                 case glu::TYPE_UINT:
966                 {
967                         const vk::VkFormat vecFmts[] =
968                         {
969                                 vk::VK_FORMAT_R32_UINT,
970                                 vk::VK_FORMAT_R32G32_UINT,
971                                 vk::VK_FORMAT_R32G32B32_UINT,
972                                 vk::VK_FORMAT_R32G32B32A32_UINT,
973                         };
974                         return de::getSizedArrayElement<4>(vecFmts, scalarSize-1);
975                 }
976
977                 case glu::TYPE_BOOL:
978                 {
979                         const vk::VkFormat vecFmts[] =
980                         {
981                                 vk::VK_FORMAT_R32_UINT,
982                                 vk::VK_FORMAT_R32G32_UINT,
983                                 vk::VK_FORMAT_R32G32B32_UINT,
984                                 vk::VK_FORMAT_R32G32B32A32_UINT,
985                         };
986                         return de::getSizedArrayElement<4>(vecFmts, scalarSize-1);
987                 }
988
989                 default:
990                         DE_FATAL("Unknown scalar type");
991                         return vk::VK_FORMAT_R8G8B8A8_UINT;
992         }
993 }
994
995 vector<vk::VkVertexInputAttributeDescription> getVertexAttributeDescriptions (const vector<Value>& inputValues, const ValueBufferLayout& layout)
996 {
997         vector<vk::VkVertexInputAttributeDescription>   attribs;
998
999         // Position
1000         {
1001                 const vk::VkVertexInputAttributeDescription     posDesc =
1002                 {
1003                         0u,                                                             // location
1004                         0u,                                                             // binding
1005                         vk::VK_FORMAT_R32G32_SFLOAT,    // format
1006                         0u,                                                             // offset
1007                 };
1008
1009                 attribs.push_back(posDesc);
1010         }
1011
1012         // Input values
1013         for (size_t inputNdx = 0; inputNdx < inputValues.size(); inputNdx++)
1014         {
1015                 const Value&                                    input           = inputValues[inputNdx];
1016                 const ValueBufferLayout::Entry& layoutEntry     = layout.entries[inputNdx];
1017                 const DataType                                  basicType       = input.type.getBasicType();
1018                 const int                                               numVecs         = isDataTypeMatrix(basicType)
1019                                                                                                         ? getDataTypeMatrixNumColumns(basicType)
1020                                                                                                         : 1;
1021                 const int                                               vecSize         = isDataTypeMatrix(basicType)
1022                                                                                                         ? getDataTypeMatrixNumRows(basicType)
1023                                                                                                         : getDataTypeScalarSize(basicType);
1024                 const DataType                                  scalarType      = getDataTypeScalarType(basicType);
1025                 const vk::VkFormat                              vecFmt          = getVecFormat(scalarType, vecSize);
1026
1027                 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
1028                 {
1029                         const deUint32                                                          curLoc  = (deUint32)attribs.size();
1030                         const deUint32                                                          offset  = (deUint32)(layoutEntry.offset + layoutEntry.vecStride*vecNdx);
1031                         const vk::VkVertexInputAttributeDescription     desc    =
1032                         {
1033                                 curLoc,         // location
1034                                 1u,                     // binding
1035                                 vecFmt,         // format
1036                                 offset,         // offset
1037                         };
1038
1039                         attribs.push_back(desc);
1040                 }
1041         }
1042
1043         return attribs;
1044 }
1045
1046 Move<vk::VkPipeline> createPipeline (Context&                                   context,
1047                                                                          const vector<Value>&           inputValues,
1048                                                                          const ValueBufferLayout&       inputLayout,
1049                                                                          const PipelineProgram&         program,
1050                                                                          vk::VkRenderPass                       renderPass,
1051                                                                          vk::VkPipelineLayout           pipelineLayout,
1052                                                                          tcu::UVec2                                     renderSize)
1053 {
1054         const vector<vk::VkPipelineShaderStageCreateInfo>       shaderStageParams               (getPipelineShaderStageCreateInfo(program));
1055         const vector<vk::VkVertexInputAttributeDescription>     vertexAttribParams              (getVertexAttributeDescriptions(inputValues, inputLayout));
1056         const vk::VkPipelineDepthStencilStateCreateInfo         depthStencilParams              =
1057         {
1058                 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,         // sType
1059                 DE_NULL,                                                                                                                        // pNext
1060                 (vk::VkPipelineDepthStencilStateCreateFlags)0,
1061                 vk::VK_FALSE,                                                                                                           // depthTestEnable
1062                 vk::VK_FALSE,                                                                                                           // depthWriteEnable
1063                 vk::VK_COMPARE_OP_ALWAYS,                                                                                       // depthCompareOp
1064                 vk::VK_FALSE,                                                                                                           // depthBoundsTestEnable
1065                 vk::VK_FALSE,                                                                                                           // stencilTestEnable
1066                 {
1067                         vk::VK_STENCIL_OP_KEEP,                                                                                         // stencilFailOp;
1068                         vk::VK_STENCIL_OP_KEEP,                                                                                         // stencilPassOp;
1069                         vk::VK_STENCIL_OP_KEEP,                                                                                         // stencilDepthFailOp;
1070                         vk::VK_COMPARE_OP_ALWAYS,                                                                                       // stencilCompareOp;
1071                         0u,                                                                                                                                     // stencilCompareMask
1072                         0u,                                                                                                                                     // stencilWriteMask
1073                         0u,                                                                                                                                     // stencilReference
1074                 },                                                                                                                                      // front;
1075                 {
1076                         vk::VK_STENCIL_OP_KEEP,                                                                                         // stencilFailOp;
1077                         vk::VK_STENCIL_OP_KEEP,                                                                                         // stencilPassOp;
1078                         vk::VK_STENCIL_OP_KEEP,                                                                                         // stencilDepthFailOp;
1079                         vk::VK_COMPARE_OP_ALWAYS,                                                                                       // stencilCompareOp;
1080                         0u,                                                                                                                                     // stencilCompareMask
1081                         0u,                                                                                                                                     // stencilWriteMask
1082                         0u,                                                                                                                                     // stencilReference
1083                 },                                                                                                                                      // back;
1084                 -1.0f,                                                                                                                          // minDepthBounds
1085                 +1.0f,                                                                                                                          // maxDepthBounds
1086         };
1087         const vk::VkViewport                                                            viewport0                               =
1088         {
1089                 0.0f,                                                                                                                           // originX
1090                 0.0f,                                                                                                                           // originY
1091                 (float)renderSize.x(),                                                                                          // width
1092                 (float)renderSize.y(),                                                                                          // height
1093                 0.0f,                                                                                                                           // minDepth
1094                 1.0f,                                                                                                                           // maxDepth
1095         };
1096         const vk::VkRect2D                                                                      scissor0                                =
1097         {
1098                 { 0u, 0u },                                                                                                                     // offset
1099                 { renderSize.x(), renderSize.y() }                                                                      // extent
1100         };
1101         const vk::VkPipelineViewportStateCreateInfo                     viewportParams                  =
1102         {
1103                 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,                      // sType
1104                 DE_NULL,                                                                                                                        // pNext
1105                 (vk::VkPipelineViewportStateCreateFlags)0,
1106                 1u,                                                                                                                                     // viewportCount
1107                 &viewport0,                                                                                                                     // pViewports
1108                 1u,                                                                                                                                     // scissorCount
1109                 &scissor0,                                                                                                                      // pScissors
1110         };
1111         const vk::VkPipelineMultisampleStateCreateInfo          multisampleParams               =
1112         {
1113                 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,           // sType
1114                 DE_NULL,                                                                                                                        // pNext
1115                 (vk::VkPipelineMultisampleStateCreateFlags)0,
1116                 vk::VK_SAMPLE_COUNT_1_BIT,                                                                                      // rasterSamples
1117                 DE_FALSE,                                                                                                                       // sampleShadingEnable
1118                 0.0f,                                                                                                                           // minSampleShading
1119                 DE_NULL,                                                                                                                        // pSampleMask
1120                 vk::VK_FALSE,                                                                                                           // alphaToCoverageEnable
1121                 vk::VK_FALSE,                                                                                                           // alphaToOneEnable
1122         };
1123         const vk::VkPipelineRasterizationStateCreateInfo        rasterParams                    =
1124         {
1125                 vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,         // sType
1126                 DE_NULL,                                                                                                                        // pNext
1127                 (vk::VkPipelineRasterizationStateCreateFlags)0,
1128                 DE_TRUE,                                                                                                                        // depthClipEnable
1129                 DE_FALSE,                                                                                                                       // rasterizerDiscardEnable
1130                 vk::VK_POLYGON_MODE_FILL,                                                                                       // fillMode
1131                 vk::VK_CULL_MODE_NONE,                                                                                          // cullMode;
1132                 vk::VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                            // frontFace;
1133                 vk::VK_FALSE,                                                                                                           // depthBiasEnable
1134                 0.0f,                                                                                                                           // depthBiasConstantFactor
1135                 0.0f,                                                                                                                           // depthBiasClamp
1136                 0.0f,                                                                                                                           // depthBiasSlopeFactor
1137                 1.0f,                                                                                                                           // lineWidth
1138         };
1139         const vk::VkPipelineInputAssemblyStateCreateInfo        inputAssemblyParams             =
1140         {
1141                 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,        // sType
1142                 DE_NULL,                                                                                                                        // pNext
1143                 (vk::VkPipelineInputAssemblyStateCreateFlags)0,
1144                 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,                                                        // topology
1145                 DE_FALSE,                                                                                                                       // primitiveRestartEnable
1146         };
1147         const vk::VkVertexInputBindingDescription                       vertexBindings[]                =
1148         {
1149                 {
1150                         0u,                                                                                                                                     // binding
1151                         (deUint32)sizeof(tcu::Vec2),                                                                            // stride
1152                         vk::VK_VERTEX_INPUT_RATE_VERTEX,                                                                        // stepRate
1153                 },
1154                 {
1155                         1u,                                                                                                                                     // binding
1156                         0u,                                                                                                                                     // stride
1157                         vk::VK_VERTEX_INPUT_RATE_INSTANCE,                                                                      // stepRate
1158                 },
1159         };
1160         const vk::VkPipelineVertexInputStateCreateInfo          vertexInputStateParams  =
1161         {
1162                 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,          // sType
1163                 DE_NULL,                                                                                                                        // pNext
1164                 (vk::VkPipelineVertexInputStateCreateFlags)0,
1165                 DE_LENGTH_OF_ARRAY(vertexBindings),                                                                     // bindingCount
1166                 vertexBindings,                                                                                                         // pVertexBindingDescriptions
1167                 (deUint32)vertexAttribParams.size(),                                                            // attributeCount
1168                 &vertexAttribParams[0],                                                                                         // pVertexAttributeDescriptions
1169         };
1170         const vk::VkColorComponentFlags                                         allCompMask                             = vk::VK_COLOR_COMPONENT_R_BIT
1171                                                                                                                                                                 | vk::VK_COLOR_COMPONENT_G_BIT
1172                                                                                                                                                                 | vk::VK_COLOR_COMPONENT_B_BIT
1173                                                                                                                                                                 | vk::VK_COLOR_COMPONENT_A_BIT;
1174         const vk::VkPipelineColorBlendAttachmentState           attBlendParams                  =
1175         {
1176                 vk::VK_FALSE,                                                                                                           // blendEnable
1177                 vk::VK_BLEND_FACTOR_ONE,                                                                                        // srcBlendColor
1178                 vk::VK_BLEND_FACTOR_ZERO,                                                                                       // destBlendColor
1179                 vk::VK_BLEND_OP_ADD,                                                                                            // blendOpColor
1180                 vk::VK_BLEND_FACTOR_ONE,                                                                                        // srcBlendAlpha
1181                 vk::VK_BLEND_FACTOR_ZERO,                                                                                       // destBlendAlpha
1182                 vk::VK_BLEND_OP_ADD,                                                                                            // blendOpAlpha
1183                 allCompMask,                                                                                                            // componentWriteMask
1184         };
1185         const vk::VkPipelineColorBlendStateCreateInfo           blendParams                             =
1186         {
1187                 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,           // sType
1188                 DE_NULL,                                                                                                                        // pNext
1189                 (vk::VkPipelineColorBlendStateCreateFlags)0,
1190                 vk::VK_FALSE,                                                                                                           // logicOpEnable
1191                 vk::VK_LOGIC_OP_COPY,                                                                                           // logicOp
1192                 1u,                                                                                                                                     // attachmentCount
1193                 &attBlendParams,                                                                                                        // pAttachments
1194                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                                     // blendConstants
1195         };
1196         const vk::VkPipelineDynamicStateCreateInfo                      dynStateParams                  =
1197         {
1198                 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,                       // sType
1199                 DE_NULL,                                                                                                                        // pNext
1200                 (vk::VkPipelineDynamicStateCreateFlags)0,
1201                 0u,                                                                                                                                     // dynamicStateCount
1202                 DE_NULL,                                                                                                                        // pDynamicStates
1203         };
1204         const vk::VkGraphicsPipelineCreateInfo                          pipelineParams                  =
1205         {
1206                 vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,                            // sType
1207                 DE_NULL,                                                                                                                        // pNext
1208                 0u,                                                                                                                                     // flags
1209                 (deUint32)shaderStageParams.size(),                                                                     // stageCount
1210                 &shaderStageParams[0],                                                                                          // pStages
1211                 &vertexInputStateParams,                                                                                        // pVertexInputState
1212                 &inputAssemblyParams,                                                                                           // pInputAssemblyState
1213                 DE_NULL,                                                                                                                        // pTessellationState
1214                 &viewportParams,                                                                                                        // pViewportState
1215                 &rasterParams,                                                                                                          // pRasterState
1216                 &multisampleParams,                                                                                                     // pMultisampleState
1217                 &depthStencilParams,                                                                                            // pDepthStencilState
1218                 &blendParams,                                                                                                           // pColorBlendState
1219                 &dynStateParams,                                                                                                        // pDynamicState
1220                 pipelineLayout,                                                                                                         // layout
1221                 renderPass,                                                                                                                     // renderPass
1222                 0u,                                                                                                                                     // subpass
1223                 DE_NULL,                                                                                                                        // basePipelineHandle
1224                 0u,                                                                                                                                     // basePipelineIndex
1225         };
1226
1227         return vk::createGraphicsPipeline(context.getDeviceInterface(), context.getDevice(), DE_NULL, &pipelineParams);
1228 }
1229
1230 Move<vk::VkFramebuffer> createFramebuffer (Context& context, vk::VkRenderPass renderPass, vk::VkImageView colorAttView, int width, int height)
1231 {
1232         const vk::VkFramebufferCreateInfo       framebufferParams       =
1233         {
1234                 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,  // sType
1235                 DE_NULL,                                                                                // pNext
1236                 (vk::VkFramebufferCreateFlags)0,
1237                 renderPass,                                                                             // renderPass
1238                 1u,                                                                                             // attachmentCount
1239                 &colorAttView,                                                                  // pAttachments
1240                 (deUint32)width,                                                                // width
1241                 (deUint32)height,                                                               // height
1242                 1u,                                                                                             // layers
1243         };
1244
1245         return vk::createFramebuffer(context.getDeviceInterface(), context.getDevice(), &framebufferParams);
1246 }
1247
1248 Move<vk::VkCommandPool> createCommandPool (Context& context)
1249 {
1250         const deUint32                                          queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
1251         const vk::VkCommandPoolCreateInfo       params                          =
1252         {
1253                 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,         // sType
1254                 DE_NULL,                                                                                        // pNext
1255                 (vk::VkCommandPoolCreateFlags)0,
1256                 queueFamilyIndex,                                                                       // queueFamilyIndex
1257         };
1258
1259         return vk::createCommandPool(context.getDeviceInterface(), context.getDevice(), &params);
1260 }
1261
1262 Move<vk::VkDescriptorPool> createDescriptorPool (Context& context)
1263 {
1264         return vk::DescriptorPoolBuilder()
1265                                 .addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u)
1266                                 .build(context.getDeviceInterface(), context.getDevice(), vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1267 }
1268
1269 Move<vk::VkDescriptorSet> allocateDescriptorSet (Context& context, vk::VkDescriptorPool descriptorPool, vk::VkDescriptorSetLayout setLayout)
1270 {
1271         const vk::VkDescriptorSetAllocateInfo   params  =
1272         {
1273                 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1274                 DE_NULL,
1275                 descriptorPool,
1276                 1u,
1277                 &setLayout
1278         };
1279
1280         return vk::allocateDescriptorSet(context.getDeviceInterface(), context.getDevice(), &params);
1281 }
1282
1283 Move<vk::VkCommandBuffer> allocateCommandBuffer (Context& context, vk::VkCommandPool cmdPool)
1284 {
1285         const vk::VkCommandBufferAllocateInfo   params  =
1286         {
1287                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,     // sType
1288                 DE_NULL,                                                                                        // pNext
1289                 cmdPool,                                                                                        // commandPool
1290                 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,                            // level
1291                 1u,                                                                                                     // bufferCount
1292         };
1293
1294         return vk::allocateCommandBuffer(context.getDeviceInterface(), context.getDevice(), &params);
1295 }
1296
1297 MovePtr<vk::Allocation> allocateAndBindMemory (Context& context, vk::VkBuffer buffer, vk::MemoryRequirement memReqs)
1298 {
1299         const vk::DeviceInterface&              vkd             = context.getDeviceInterface();
1300         const vk::VkMemoryRequirements  bufReqs = vk::getBufferMemoryRequirements(vkd, context.getDevice(), buffer);
1301         MovePtr<vk::Allocation>                 memory  = context.getDefaultAllocator().allocate(bufReqs, memReqs);
1302
1303         vkd.bindBufferMemory(context.getDevice(), buffer, memory->getMemory(), memory->getOffset());
1304
1305         return memory;
1306 }
1307
1308 MovePtr<vk::Allocation> allocateAndBindMemory (Context& context, vk::VkImage image, vk::MemoryRequirement memReqs)
1309 {
1310         const vk::DeviceInterface&              vkd             = context.getDeviceInterface();
1311         const vk::VkMemoryRequirements  imgReqs = vk::getImageMemoryRequirements(vkd, context.getDevice(), image);
1312         MovePtr<vk::Allocation>                 memory  = context.getDefaultAllocator().allocate(imgReqs, memReqs);
1313
1314         vkd.bindImageMemory(context.getDevice(), image, memory->getMemory(), memory->getOffset());
1315
1316         return memory;
1317 }
1318
1319 void writeValuesToMem (Context& context, const vk::Allocation& dst, const ValueBufferLayout& layout, const vector<Value>& values, int arrayNdx)
1320 {
1321         copyToLayout(dst.getHostPtr(), layout, values, arrayNdx);
1322
1323         // \note Buffers are not allocated with coherency / uncached requirement so we need to manually flush CPU write caches
1324         flushMappedMemoryRange(context.getDeviceInterface(), context.getDevice(), dst.getMemory(), dst.getOffset(), (vk::VkDeviceSize)layout.size);
1325 }
1326
1327 class ShaderCaseInstance : public TestInstance
1328 {
1329 public:
1330                                                                                                         ShaderCaseInstance              (Context& context, const ShaderCaseSpecification& spec);
1331                                                                                                         ~ShaderCaseInstance             (void);
1332
1333         TestStatus                                                                              iterate                                 (void);
1334
1335 private:
1336         enum
1337         {
1338                 RENDER_WIDTH            = 64,
1339                 RENDER_HEIGHT           = 64,
1340
1341                 POSITIONS_OFFSET        = 0,
1342                 POSITIONS_SIZE          = (int)sizeof(Vec2)*4,
1343
1344                 INDICES_OFFSET          = POSITIONS_SIZE,
1345                 INDICES_SIZE            = (int)sizeof(deUint16)*6,
1346
1347                 TOTAL_POS_NDX_SIZE      = POSITIONS_SIZE+INDICES_SIZE
1348         };
1349
1350         const ShaderCaseSpecification&                                  m_spec;
1351
1352         const Unique<vk::VkBuffer>                                              m_posNdxBuffer;
1353         const UniquePtr<vk::Allocation>                                 m_posNdxMem;
1354
1355         const ValueBufferLayout                                                 m_inputLayout;
1356         const Unique<vk::VkBuffer>                                              m_inputBuffer;                  // Input values (attributes). Can be NULL if no inputs present
1357         const UniquePtr<vk::Allocation>                                 m_inputMem;                             // Input memory, can be NULL if no input buffer exists
1358
1359         const ValueBufferLayout                                                 m_referenceLayout;
1360         const Unique<vk::VkBuffer>                                              m_referenceBuffer;              // Output (reference) values. Can be NULL if no outputs present
1361         const UniquePtr<vk::Allocation>                                 m_referenceMem;                 // Output (reference) memory, can be NULL if no reference buffer exists
1362
1363         const ValueBufferLayout                                                 m_uniformLayout;
1364         const Unique<vk::VkBuffer>                                              m_uniformBuffer;                // Uniform values. Can be NULL if no uniforms present
1365         const UniquePtr<vk::Allocation>                                 m_uniformMem;                   // Uniform memory, can be NULL if no uniform buffer exists
1366
1367         const Unique<vk::VkBuffer>                                              m_readImageBuffer;
1368         const UniquePtr<vk::Allocation>                                 m_readImageMem;
1369
1370         const Unique<vk::VkImage>                                               m_rtImage;
1371         const UniquePtr<vk::Allocation>                                 m_rtMem;
1372         const Unique<vk::VkImageView>                                   m_rtView;
1373
1374         const Unique<vk::VkRenderPass>                                  m_renderPass;
1375         const Unique<vk::VkFramebuffer>                                 m_framebuffer;
1376         const PipelineProgram                                                   m_program;
1377         const Unique<vk::VkDescriptorSetLayout>                 m_descriptorSetLayout;
1378         const Unique<vk::VkPipelineLayout>                              m_pipelineLayout;
1379         const Unique<vk::VkPipeline>                                    m_pipeline;
1380
1381         const Unique<vk::VkDescriptorPool>                              m_descriptorPool;
1382         const Unique<vk::VkDescriptorSet>                               m_descriptorSet;
1383
1384         const Unique<vk::VkCommandPool>                                 m_cmdPool;
1385         const Unique<vk::VkCommandBuffer>                               m_cmdBuffer;
1386
1387         int                                                                                             m_subCaseNdx;
1388 };
1389
1390 ShaderCaseInstance::ShaderCaseInstance (Context& context, const ShaderCaseSpecification& spec)
1391         : TestInstance                  (context)
1392         , m_spec                                (spec)
1393
1394         , m_posNdxBuffer                (createBuffer(context, (vk::VkDeviceSize)TOTAL_POS_NDX_SIZE, vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT|vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))
1395         , m_posNdxMem                   (allocateAndBindMemory(context, *m_posNdxBuffer, vk::MemoryRequirement::HostVisible))
1396
1397         , m_inputLayout                 (computeStd430Layout(spec.values.inputs))
1398         , m_inputBuffer                 (m_inputLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_inputLayout.size, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) : Move<vk::VkBuffer>())
1399         , m_inputMem                    (m_inputLayout.size > 0 ? allocateAndBindMemory(context, *m_inputBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>())
1400
1401         , m_referenceLayout             (computeStd140Layout(spec.values.outputs))
1402         , m_referenceBuffer             (m_referenceLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_referenceLayout.size, vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : Move<vk::VkBuffer>())
1403         , m_referenceMem                (m_referenceLayout.size > 0 ? allocateAndBindMemory(context, *m_referenceBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>())
1404
1405         , m_uniformLayout               (computeStd140Layout(spec.values.uniforms))
1406         , m_uniformBuffer               (m_uniformLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_uniformLayout.size, vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : Move<vk::VkBuffer>())
1407         , m_uniformMem                  (m_uniformLayout.size > 0 ? allocateAndBindMemory(context, *m_uniformBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>())
1408
1409         , m_readImageBuffer             (createBuffer(context, (vk::VkDeviceSize)(RENDER_WIDTH*RENDER_HEIGHT*4), vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT))
1410         , m_readImageMem                (allocateAndBindMemory(context, *m_readImageBuffer, vk::MemoryRequirement::HostVisible))
1411
1412         , m_rtImage                             (createImage2D(context, RENDER_WIDTH, RENDER_HEIGHT, vk::VK_FORMAT_R8G8B8A8_UNORM, vk::VK_IMAGE_TILING_OPTIMAL, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT))
1413         , m_rtMem                               (allocateAndBindMemory(context, *m_rtImage, vk::MemoryRequirement::Any))
1414         , m_rtView                              (createAttachmentView(context, *m_rtImage, vk::VK_FORMAT_R8G8B8A8_UNORM))
1415
1416         , m_renderPass                  (createRenderPass(context, vk::VK_FORMAT_R8G8B8A8_UNORM))
1417         , m_framebuffer                 (createFramebuffer(context, *m_renderPass, *m_rtView, RENDER_WIDTH, RENDER_HEIGHT))
1418         , m_program                             (context, spec)
1419         , m_descriptorSetLayout (createDescriptorSetLayout(context, m_program.getStages()))
1420         , m_pipelineLayout              (createPipelineLayout(context, *m_descriptorSetLayout))
1421         , m_pipeline                    (createPipeline(context, spec.values.inputs, m_inputLayout, m_program, *m_renderPass, *m_pipelineLayout, tcu::UVec2(RENDER_WIDTH, RENDER_HEIGHT)))
1422
1423         , m_descriptorPool              (createDescriptorPool(context))
1424         , m_descriptorSet               (allocateDescriptorSet(context, *m_descriptorPool, *m_descriptorSetLayout))
1425
1426         , m_cmdPool                             (createCommandPool(context))
1427         , m_cmdBuffer                   (allocateCommandBuffer(context, *m_cmdPool))
1428
1429         , m_subCaseNdx                  (0)
1430 {
1431         const vk::DeviceInterface&      vkd                                     = context.getDeviceInterface();
1432         const deUint32                          queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
1433
1434         {
1435                 const Vec2                      s_positions[]   =
1436                 {
1437                         Vec2(-1.0f, -1.0f),
1438                         Vec2(-1.0f, +1.0f),
1439                         Vec2(+1.0f, -1.0f),
1440                         Vec2(+1.0f, +1.0f)
1441                 };
1442                 const deUint16          s_indices[]             =
1443                 {
1444                         0, 1, 2,
1445                         1, 3, 2
1446                 };
1447
1448                 DE_STATIC_ASSERT(sizeof(s_positions) == POSITIONS_SIZE);
1449                 DE_STATIC_ASSERT(sizeof(s_indices) == INDICES_SIZE);
1450
1451                 deMemcpy((deUint8*)m_posNdxMem->getHostPtr() + POSITIONS_OFFSET,        &s_positions[0],        sizeof(s_positions));
1452                 deMemcpy((deUint8*)m_posNdxMem->getHostPtr() + INDICES_OFFSET,          &s_indices[0],          sizeof(s_indices));
1453
1454                 flushMappedMemoryRange(m_context.getDeviceInterface(), context.getDevice(), m_posNdxMem->getMemory(), m_posNdxMem->getOffset(), sizeof(s_positions)+sizeof(s_indices));
1455         }
1456
1457         if (!m_spec.values.uniforms.empty())
1458         {
1459                 const vk::VkDescriptorBufferInfo        bufInfo =
1460                 {
1461                         *m_uniformBuffer,
1462                         (vk::VkDeviceSize)0,    // offset
1463                         (vk::VkDeviceSize)m_uniformLayout.size
1464                 };
1465
1466                 vk::DescriptorSetUpdateBuilder()
1467                         .writeSingle(*m_descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(USER_UNIFORM_BINDING),
1468                                                  vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufInfo)
1469                         .update(vkd, m_context.getDevice());
1470         }
1471
1472         if (!m_spec.values.outputs.empty())
1473         {
1474                 const vk::VkDescriptorBufferInfo        bufInfo =
1475                 {
1476                         *m_referenceBuffer,
1477                         (vk::VkDeviceSize)0,    // offset
1478                         (vk::VkDeviceSize)m_referenceLayout.size
1479                 };
1480
1481                 vk::DescriptorSetUpdateBuilder()
1482                         .writeSingle(*m_descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(REFERENCE_UNIFORM_BINDING),
1483                                                  vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufInfo)
1484                         .update(vkd, m_context.getDevice());
1485         }
1486
1487         // Record command buffer
1488
1489         {
1490                 const vk::VkCommandBufferBeginInfo beginInfo    =
1491                 {
1492                         vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,        // sType
1493                         DE_NULL,                                                                                        // pNext
1494                         0u,                                                                                                     // flags
1495                         (const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
1496                 };
1497
1498                 VK_CHECK(vkd.beginCommandBuffer(*m_cmdBuffer, &beginInfo));
1499         }
1500
1501         {
1502                 const vk::VkMemoryBarrier               vertFlushBarrier        =
1503                 {
1504                         vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,                                                                                                   // sType
1505                         DE_NULL,                                                                                                                                                                // pNext
1506                         vk::VK_ACCESS_HOST_WRITE_BIT,                                                                                                                   // srcAccessMask
1507                         vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT|vk::VK_ACCESS_UNIFORM_READ_BIT,                                 // dstAccessMask
1508                 };
1509                 const vk::VkImageMemoryBarrier  colorAttBarrier         =
1510                 {
1511                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,             // sType
1512                         DE_NULL,                                                                                // pNext
1513                         0u,                                                                                             // srcAccessMask
1514                         vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,               // dstAccessMask
1515                         vk::VK_IMAGE_LAYOUT_UNDEFINED,                                  // oldLayout
1516                         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // newLayout
1517                         queueFamilyIndex,                                                               // srcQueueFamilyIndex
1518                         queueFamilyIndex,                                                               // destQueueFamilyIndex
1519                         *m_rtImage,                                                                             // image
1520                         {
1521                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,                                  // aspectMask
1522                                 0u,                                                                                             // baseMipLevel
1523                                 1u,                                                                                             // mipLevels
1524                                 0u,                                                                                             // baseArraySlice
1525                                 1u,                                                                                             // arraySize
1526                         }                                                                                               // subresourceRange
1527                 };
1528
1529                 vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (vk::VkDependencyFlags)0,
1530                                                            1, &vertFlushBarrier,
1531                                                            0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1532                                                            1, &colorAttBarrier);
1533         }
1534
1535         {
1536                 const vk::VkClearValue                  clearValue              = vk::makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
1537                 const vk::VkRenderPassBeginInfo passBeginInfo   =
1538                 {
1539                         vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,   // sType
1540                         DE_NULL,                                                                                // pNext
1541                         *m_renderPass,                                                                  // renderPass
1542                         *m_framebuffer,                                                                 // framebuffer
1543                         { { 0, 0 }, { RENDER_WIDTH, RENDER_HEIGHT } },  // renderArea
1544                         1u,                                                                                             // clearValueCount
1545                         &clearValue,                                                                    // pClearValues
1546                 };
1547
1548                 vkd.cmdBeginRenderPass(*m_cmdBuffer, &passBeginInfo, vk::VK_SUBPASS_CONTENTS_INLINE);
1549         }
1550
1551         vkd.cmdBindPipeline                     (*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1552         vkd.cmdBindDescriptorSets       (*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, DE_NULL);
1553
1554         {
1555                 const vk::VkBuffer              buffers[]       = { *m_posNdxBuffer, *m_inputBuffer };
1556                 const vk::VkDeviceSize  offsets[]       = { POSITIONS_OFFSET, 0u };
1557                 const deUint32                  numBuffers      = buffers[1] != 0 ? 2u : 1u;
1558                 vkd.cmdBindVertexBuffers(*m_cmdBuffer, 0u, numBuffers, buffers, offsets);
1559         }
1560
1561         vkd.cmdBindIndexBuffer  (*m_cmdBuffer, *m_posNdxBuffer, (vk::VkDeviceSize)INDICES_OFFSET, vk::VK_INDEX_TYPE_UINT16);
1562         vkd.cmdDrawIndexed              (*m_cmdBuffer, 6u, 1u, 0u, 0u, 0u);
1563         vkd.cmdEndRenderPass    (*m_cmdBuffer);
1564
1565         {
1566                 const vk::VkImageMemoryBarrier  renderFinishBarrier     =
1567                 {
1568                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,             // sType
1569                         DE_NULL,                                                                                // pNext
1570                         vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,               // srcAccessMask
1571                         vk::VK_ACCESS_TRANSFER_READ_BIT,                                // dstAccessMask
1572                         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // oldLayout
1573                         vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,               // newLayout
1574                         queueFamilyIndex,                                                               // srcQueueFamilyIndex
1575                         queueFamilyIndex,                                                               // destQueueFamilyIndex
1576                         *m_rtImage,                                                                             // image
1577                         {
1578                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,                                  // aspectMask
1579                                 0u,                                                                                             // baseMipLevel
1580                                 1u,                                                                                             // mipLevels
1581                                 0u,                                                                                             // baseArraySlice
1582                                 1u,                                                                                             // arraySize
1583                         }                                                                                               // subresourceRange
1584                 };
1585
1586                 vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0,
1587                                                            0, (const vk::VkMemoryBarrier*)DE_NULL,
1588                                                            0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1589                                                            1, &renderFinishBarrier);
1590         }
1591
1592         {
1593                 const vk::VkBufferImageCopy     copyParams      =
1594                 {
1595                         (vk::VkDeviceSize)0u,                                   // bufferOffset
1596                         (deUint32)RENDER_WIDTH,                                 // bufferRowLength
1597                         (deUint32)RENDER_HEIGHT,                                // bufferImageHeight
1598                         {
1599                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,                  // aspect
1600                                 0u,                                                                             // mipLevel
1601                                 0u,                                                                             // arrayLayer
1602                                 1u,                                                                             // arraySize
1603                         },                                                                              // imageSubresource
1604                         { 0u, 0u, 0u },                                                 // imageOffset
1605                         { RENDER_WIDTH, RENDER_HEIGHT, 1u }             // imageExtent
1606                 };
1607
1608                 vkd.cmdCopyImageToBuffer(*m_cmdBuffer, *m_rtImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_readImageBuffer, 1u, &copyParams);
1609         }
1610
1611         {
1612                 const vk::VkBufferMemoryBarrier copyFinishBarrier       =
1613                 {
1614                         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,            // sType
1615                         DE_NULL,                                                                                        // pNext
1616                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,                                       // srcAccessMask
1617                         vk::VK_ACCESS_HOST_READ_BIT,                                            // dstAccessMask
1618                         queueFamilyIndex,                                                                       // srcQueueFamilyIndex
1619                         queueFamilyIndex,                                                                       // destQueueFamilyIndex
1620                         *m_readImageBuffer,                                                                     // buffer
1621                         0u,                                                                                                     // offset
1622                         (vk::VkDeviceSize)(RENDER_WIDTH*RENDER_HEIGHT*4)        // size
1623                 };
1624
1625                 vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0,
1626                                                            0, (const vk::VkMemoryBarrier*)DE_NULL,
1627                                                            1, &copyFinishBarrier,
1628                                                            0, (const vk::VkImageMemoryBarrier*)DE_NULL);
1629         }
1630
1631         VK_CHECK(vkd.endCommandBuffer(*m_cmdBuffer));
1632 }
1633
1634 ShaderCaseInstance::~ShaderCaseInstance (void)
1635 {
1636 }
1637
1638 int getNumSubCases (const ValueBlock& values)
1639 {
1640         if (!values.outputs.empty())
1641                 return int(values.outputs[0].elements.size() / values.outputs[0].type.getScalarSize());
1642         else
1643                 return 1; // Always run at least one iteration even if no output values are specified
1644 }
1645
1646 bool checkResultImage (const ConstPixelBufferAccess& result)
1647 {
1648         const tcu::IVec4        refPix  (255, 255, 255, 255);
1649
1650         for (int y = 0; y < result.getHeight(); y++)
1651         {
1652                 for (int x = 0; x < result.getWidth(); x++)
1653                 {
1654                         const tcu::IVec4        resPix  = result.getPixelInt(x, y);
1655
1656                         if (boolAny(notEqual(resPix, refPix)))
1657                                 return false;
1658                 }
1659         }
1660
1661         return true;
1662 }
1663
1664 TestStatus ShaderCaseInstance::iterate (void)
1665 {
1666         const vk::DeviceInterface&      vkd             = m_context.getDeviceInterface();
1667         const vk::VkDevice                      device  = m_context.getDevice();
1668         const vk::VkQueue                       queue   = m_context.getUniversalQueue();
1669
1670         if (!m_spec.values.inputs.empty())
1671                 writeValuesToMem(m_context, *m_inputMem, m_inputLayout, m_spec.values.inputs, m_subCaseNdx);
1672
1673         if (!m_spec.values.outputs.empty())
1674                 writeValuesToMem(m_context, *m_referenceMem, m_referenceLayout, m_spec.values.outputs, m_subCaseNdx);
1675
1676         if (!m_spec.values.uniforms.empty())
1677                 writeValuesToMem(m_context, *m_uniformMem, m_uniformLayout, m_spec.values.uniforms, m_subCaseNdx);
1678
1679         {
1680                 const vk::VkSubmitInfo          submitInfo      =
1681                 {
1682                         vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1683                         DE_NULL,
1684                         0u,                                                                                     // waitSemaphoreCount
1685                         (const vk::VkSemaphore*)0,                                      // pWaitSemaphores
1686                         (const vk::VkPipelineStageFlags*)DE_NULL,
1687                         1u,
1688                         &m_cmdBuffer.get(),
1689                         0u,                                                                                     // signalSemaphoreCount
1690                         (const vk::VkSemaphore*)0,                                      // pSignalSemaphores
1691                 };
1692                 const vk::VkFenceCreateInfo     fenceParams     =
1693                 {
1694                         vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,        // sType
1695                         DE_NULL,                                                                        // pNext
1696                         0u,                                                                                     // flags
1697                 };
1698                 const Unique<vk::VkFence>       fence           (vk::createFence(vkd, device, &fenceParams));
1699
1700                 VK_CHECK(vkd.queueSubmit        (queue, 1u, &submitInfo, *fence));
1701                 VK_CHECK(vkd.waitForFences      (device, 1u, &fence.get(), DE_TRUE, ~0ull));
1702         }
1703
1704         {
1705                 const ConstPixelBufferAccess    imgAccess       (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), RENDER_WIDTH, RENDER_HEIGHT, 1, m_readImageMem->getHostPtr());
1706
1707                 invalidateMappedMemoryRange(vkd, device, m_readImageMem->getMemory(), m_readImageMem->getOffset(), (vk::VkDeviceSize)(RENDER_WIDTH*RENDER_HEIGHT*4));
1708
1709                 if (!checkResultImage(imgAccess))
1710                 {
1711                         TestLog&        log             = m_context.getTestContext().getLog();
1712
1713                         log << TestLog::Message << "ERROR: Got non-white pixels on sub-case " << m_subCaseNdx << TestLog::EndMessage
1714                                 << TestLog::Image("Result", "Result", imgAccess);
1715
1716                         dumpValues(log, m_spec.values, m_subCaseNdx);
1717
1718                         return TestStatus::fail(string("Got invalid pixels at sub-case ") + de::toString(m_subCaseNdx));
1719                 }
1720         }
1721
1722         if (++m_subCaseNdx < getNumSubCases(m_spec.values))
1723                 return TestStatus::incomplete();
1724         else
1725                 return TestStatus::pass("All sub-cases passed");
1726 }
1727
1728 class ShaderCase : public TestCase
1729 {
1730 public:
1731                                                                         ShaderCase              (tcu::TestContext& testCtx, const string& name, const string& description, const ShaderCaseSpecification& spec);
1732
1733
1734         void                                                    initPrograms    (SourceCollections& programCollection) const;
1735         TestInstance*                                   createInstance  (Context& context) const;
1736
1737 private:
1738         const ShaderCaseSpecification   m_spec;
1739 };
1740
1741 ShaderCase::ShaderCase (tcu::TestContext& testCtx, const string& name, const string& description, const ShaderCaseSpecification& spec)
1742         : TestCase      (testCtx, name, description)
1743         , m_spec        (spec)
1744 {
1745 }
1746
1747 void ShaderCase::initPrograms (SourceCollections& sourceCollection) const
1748 {
1749         vector<ProgramSources>  specializedSources      (m_spec.programs.size());
1750
1751         DE_ASSERT(isValid(m_spec));
1752
1753         if (m_spec.expectResult != glu::sl::EXPECT_PASS)
1754                 TCU_THROW(InternalError, "Only EXPECT_PASS is supported");
1755
1756         if (m_spec.caseType == glu::sl::CASETYPE_VERTEX_ONLY)
1757         {
1758                 DE_ASSERT(m_spec.programs.size() == 1 && m_spec.programs[0].sources.sources[glu::SHADERTYPE_VERTEX].size() == 1);
1759                 specializedSources[0] << glu::VertexSource(specializeVertexShader(m_spec, m_spec.programs[0].sources.sources[glu::SHADERTYPE_VERTEX][0]))
1760                                                           << glu::FragmentSource(genFragmentShader(m_spec));
1761         }
1762         else if (m_spec.caseType == glu::sl::CASETYPE_FRAGMENT_ONLY)
1763         {
1764                 DE_ASSERT(m_spec.programs.size() == 1 && m_spec.programs[0].sources.sources[glu::SHADERTYPE_FRAGMENT].size() == 1);
1765                 specializedSources[0] << glu::VertexSource(genVertexShader(m_spec))
1766                                                           << glu::FragmentSource(specializeFragmentShader(m_spec, m_spec.programs[0].sources.sources[glu::SHADERTYPE_FRAGMENT][0]));
1767         }
1768         else
1769         {
1770                 DE_ASSERT(m_spec.caseType == glu::sl::CASETYPE_COMPLETE);
1771
1772                 const int       maxPatchVertices        = 4; // \todo [2015-08-05 pyry] Query
1773
1774                 for (size_t progNdx = 0; progNdx < m_spec.programs.size(); progNdx++)
1775                 {
1776                         const ProgramSpecializationParams       progSpecParams  (m_spec, m_spec.programs[progNdx].requiredExtensions, maxPatchVertices);
1777
1778                         specializeProgramSources(specializedSources[progNdx], m_spec.programs[progNdx].sources, progSpecParams);
1779                 }
1780         }
1781
1782         for (size_t progNdx = 0; progNdx < specializedSources.size(); progNdx++)
1783         {
1784                 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
1785                 {
1786                         if (!specializedSources[progNdx].sources[shaderType].empty())
1787                         {
1788                                 glu::ProgramSources& curSrc     = sourceCollection.glslSources.add(getShaderName((glu::ShaderType)shaderType, progNdx));
1789                                 curSrc.sources[shaderType] = specializedSources[progNdx].sources[shaderType];
1790                         }
1791                 }
1792         }
1793 }
1794
1795 TestInstance* ShaderCase::createInstance (Context& context) const
1796 {
1797         return new ShaderCaseInstance(context, m_spec);
1798 }
1799
1800 class ShaderCaseFactory : public glu::sl::ShaderCaseFactory
1801 {
1802 public:
1803         ShaderCaseFactory (tcu::TestContext& testCtx)
1804                 : m_testCtx(testCtx)
1805         {
1806         }
1807
1808         tcu::TestCaseGroup* createGroup (const string& name, const string& description, const vector<tcu::TestNode*>& children)
1809         {
1810                 return new tcu::TestCaseGroup(m_testCtx, name.c_str(), description.c_str(), children);
1811         }
1812
1813         tcu::TestCase* createCase (const string& name, const string& description, const ShaderCaseSpecification& spec)
1814         {
1815                 return new ShaderCase(m_testCtx, name, description, spec);
1816         }
1817
1818 private:
1819         tcu::TestContext&       m_testCtx;
1820 };
1821
1822 class ShaderLibraryGroup : public tcu::TestCaseGroup
1823 {
1824 public:
1825         ShaderLibraryGroup (tcu::TestContext& testCtx, const string& name, const string& description, const string& filename)
1826                  : tcu::TestCaseGroup   (testCtx, name.c_str(), description.c_str())
1827                  , m_filename                   (filename)
1828         {
1829         }
1830
1831         void init (void)
1832         {
1833                 ShaderCaseFactory                               caseFactory     (m_testCtx);
1834                 const vector<tcu::TestNode*>    children        = glu::sl::parseFile(m_testCtx.getArchive(), m_filename, &caseFactory);
1835
1836                 for (size_t ndx = 0; ndx < children.size(); ndx++)
1837                 {
1838                         try
1839                         {
1840                                 addChild(children[ndx]);
1841                         }
1842                         catch (...)
1843                         {
1844                                 for (; ndx < children.size(); ndx++)
1845                                         delete children[ndx];
1846                                 throw;
1847                         }
1848                 }
1849         }
1850
1851 private:
1852         const string    m_filename;
1853 };
1854
1855 } // anonymous
1856
1857 MovePtr<tcu::TestCaseGroup> createShaderLibraryGroup (tcu::TestContext& testCtx, const string& name, const string& description, const string& filename)
1858 {
1859         return MovePtr<tcu::TestCaseGroup>(new ShaderLibraryGroup(testCtx, name, description, filename));
1860 }
1861
1862 } // vkt