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