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