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