1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 Google Inc.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and/or associated documentation files (the
9 * "Materials"), to deal in the Materials without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Materials, and to
12 * permit persons to whom the Materials are furnished to do so, subject to
13 * the following conditions:
15 * The above copyright notice(s) and this permission notice shall be
16 * included in all copies or substantial portions of the Materials.
18 * The Materials are Confidential Information as defined by the
19 * Khronos Membership Agreement until designated non-confidential by
20 * Khronos, at which point this condition clause shall be removed.
22 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
26 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
32 * \brief ShaderLibrary Vulkan implementation
33 *//*--------------------------------------------------------------------*/
35 #include "vktShaderLibrary.hpp"
36 #include "vktTestCase.hpp"
38 #include "vkPrograms.hpp"
40 #include "vkRefUtil.hpp"
41 #include "vkMemUtil.hpp"
42 #include "vkQueryUtil.hpp"
43 #include "vkBuilderUtil.hpp"
44 #include "vkTypeUtil.hpp"
46 #include "gluShaderLibrary.hpp"
47 #include "gluShaderUtil.hpp"
49 #include "tcuStringTemplate.hpp"
50 #include "tcuTexture.hpp"
51 #include "tcuTestLog.hpp"
52 #include "tcuVector.hpp"
53 #include "tcuVectorUtil.hpp"
55 #include "deStringUtil.hpp"
56 #include "deArrayUtil.hpp"
69 using std::ostringstream;
74 using glu::ShaderType;
75 using glu::ProgramSources;
78 using glu::sl::ShaderCaseSpecification;
79 using glu::sl::ProgramSpecializationParams;
80 using glu::sl::RequiredExtension;
82 using glu::sl::ValueBlock;
84 using tcu::TestStatus;
85 using tcu::StringTemplate;
87 using tcu::ConstPixelBufferAccess;
88 using tcu::TextureFormat;
91 using vk::SourceCollections;
100 REFERENCE_UNIFORM_BINDING = 0,
101 USER_UNIFORM_BINDING = 1
104 string getShaderName (ShaderType shaderType, size_t progNdx)
107 str << glu::getShaderTypeName(shaderType);
109 str << "_" << progNdx;
113 void genUniformBlock (ostringstream& out, const string& blockName, const string& instanceName, int setNdx, int bindingNdx, const vector<Value>& uniforms)
118 out << "set = " << setNdx << ", ";
120 out << "binding = " << bindingNdx << ", std140) uniform " << blockName << "\n"
123 for (vector<Value>::const_iterator val = uniforms.begin(); val != uniforms.end(); ++val)
124 out << "\t" << glu::declare(val->type, val->name, 1) << ";\n";
128 if (!instanceName.empty())
129 out << " " << instanceName;
134 void declareReferenceBlock (ostringstream& out, const ValueBlock& valueBlock)
136 if (!valueBlock.outputs.empty())
137 genUniformBlock(out, "Reference", "ref", 0, REFERENCE_UNIFORM_BINDING, valueBlock.outputs);
140 void declareUniforms (ostringstream& out, const ValueBlock& valueBlock)
142 if (!valueBlock.uniforms.empty())
143 genUniformBlock(out, "Uniforms", "", 0, USER_UNIFORM_BINDING, valueBlock.uniforms);
146 DataType getTransportType (DataType valueType)
148 if (isDataTypeBoolOrBVec(valueType))
149 return glu::getDataTypeIntVec(getDataTypeScalarSize(valueType));
154 int getNumTransportLocations (DataType valueType)
156 return isDataTypeMatrix(valueType) ? getDataTypeMatrixNumColumns(valueType) : 1;
159 // This functions builds a matching vertex shader for a 'both' case, when
160 // the fragment shader is being tested.
161 // We need to build attributes and varyings for each 'input'.
162 string genVertexShader (const ShaderCaseSpecification& spec)
166 int curOutputLoc = 0;
168 res << glu::getGLSLVersionDeclaration(spec.targetVersion) << "\n";
170 // Declarations (position + attribute/varying for each input).
171 res << "precision highp float;\n";
172 res << "precision highp int;\n";
174 res << "layout(location = 0) in highp vec4 dEQP_Position;\n";
177 for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
179 const Value& val = spec.values.inputs[ndx];
180 const DataType valueType = val.type.getBasicType();
181 const DataType transportType = getTransportType(valueType);
182 const char* const transportTypeStr = getDataTypeName(transportType);
183 const int numLocs = getNumTransportLocations(valueType);
185 res << "layout(location = " << curInputLoc << ") in " << transportTypeStr << " a_" << val.name << ";\n";
186 res << "layout(location = " << curOutputLoc << ") flat out " << transportTypeStr << " " << (transportType != valueType ? "v_" : "") << val.name << ";\n";
188 curInputLoc += numLocs;
189 curOutputLoc += numLocs;
194 // - gl_Position = dEQP_Position;
195 // - for each input: write attribute directly to varying
196 res << "void main()\n";
198 res << " gl_Position = dEQP_Position;\n";
199 for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
201 const Value& val = spec.values.inputs[ndx];
202 const string& name = val.name;
204 res << " " << (getTransportType(val.type.getBasicType()) != val.type.getBasicType() ? "v_" : "")
205 << name << " = a_" << name << ";\n";
212 void genCompareOp (ostringstream& output, const char* dstVec4Var, const ValueBlock& valueBlock, const char* checkVarName)
214 bool isFirstOutput = true;
216 for (size_t ndx = 0; ndx < valueBlock.outputs.size(); ndx++)
218 const Value& val = valueBlock.outputs[ndx];
220 // Check if we're only interested in one variable (then skip if not the right one).
221 if (checkVarName && val.name != checkVarName)
227 output << "bool RES = ";
228 isFirstOutput = false;
231 output << "RES = RES && ";
233 // Generate actual comparison.
234 if (getDataTypeScalarType(val.type.getBasicType()) == glu::TYPE_FLOAT)
235 output << "isOk(" << val.name << ", ref." << val.name << ", 0.05);\n";
237 output << "isOk(" << val.name << ", ref." << val.name << ");\n";
241 output << dstVec4Var << " = vec4(1.0);\n";
243 output << dstVec4Var << " = vec4(RES, RES, RES, 1.0);\n";
246 string genFragmentShader (const ShaderCaseSpecification& spec)
248 ostringstream shader;
252 shader << glu::getGLSLVersionDeclaration(spec.targetVersion) << "\n";
254 shader << "precision highp float;\n";
255 shader << "precision highp int;\n";
258 shader << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
261 genCompareFunctions(shader, spec.values, false);
264 // Declarations (varying, reference for each output).
265 for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++)
267 const Value& val = spec.values.outputs[ndx];
268 const DataType valueType = val.type.getBasicType();
269 const char* const valueTypeStr = getDataTypeName(valueType);
270 const DataType transportType = getTransportType(valueType);
271 const char* const transportTypeStr = getDataTypeName(transportType);
272 const int numLocs = getNumTransportLocations(valueType);
274 shader << "layout(location = " << curInLoc << ") flat in " << transportTypeStr << " " << (valueType != transportType ? "v_" : "") << val.name << ";\n";
276 if (valueType != transportType)
277 setup << " " << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(v_" << val.name << ");\n";
282 declareReferenceBlock(shader, spec.values);
285 shader << "void main()\n";
288 shader << setup.str();
291 genCompareOp(shader, "dEQP_FragColor", spec.values, DE_NULL);
297 // Specialize a shader for the vertex shader test case.
298 string specializeVertexShader (const ShaderCaseSpecification& spec, const string& src)
302 ostringstream output;
304 int curOutputLoc = 0;
306 // generated from "both" case
307 DE_ASSERT(spec.caseType == glu::sl::CASETYPE_VERTEX_ONLY);
309 // Output (write out position).
310 output << "gl_Position = dEQP_Position;\n";
312 // Declarations (position + attribute for each input, varying for each output).
313 decl << "layout(location = 0) in highp vec4 dEQP_Position;\n";
316 for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
318 const Value& val = spec.values.inputs[ndx];
319 const DataType valueType = val.type.getBasicType();
320 const char* const valueTypeStr = getDataTypeName(valueType);
321 const DataType transportType = getTransportType(valueType);
322 const char* const transportTypeStr = getDataTypeName(transportType);
323 const int numLocs = getNumTransportLocations(valueType);
325 decl << "layout(location = " << curInputLoc << ") in ";
327 curInputLoc += numLocs;
329 if (valueType == transportType)
330 decl << transportTypeStr << " " << val.name << ";\n";
333 decl << transportTypeStr << " a_" << val.name << ";\n";
334 setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(a_" << val.name << ");\n";
338 declareUniforms(decl, spec.values);
340 for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++)
342 const Value& val = spec.values.outputs[ndx];
343 const DataType valueType = val.type.getBasicType();
344 const char* const valueTypeStr = getDataTypeName(valueType);
345 const DataType transportType = getTransportType(valueType);
346 const char* const transportTypeStr = getDataTypeName(transportType);
347 const int numLocs = getNumTransportLocations(valueType);
349 decl << "layout(location = " << curOutputLoc << ") flat out ";
351 curOutputLoc += numLocs;
353 if (valueType == transportType)
354 decl << transportTypeStr << " " << val.name << ";\n";
357 decl << transportTypeStr << " v_" << val.name << ";\n";
358 decl << valueTypeStr << " " << val.name << ";\n";
360 output << "v_" << val.name << " = " << transportTypeStr << "(" << val.name << ");\n";
364 // Shader specialization.
365 map<string, string> params;
366 params.insert(pair<string, string>("DECLARATIONS", decl.str()));
367 params.insert(pair<string, string>("SETUP", setup.str()));
368 params.insert(pair<string, string>("OUTPUT", output.str()));
369 params.insert(pair<string, string>("POSITION_FRAG_COLOR", "gl_Position"));
371 StringTemplate tmpl (src);
372 const string baseSrc = tmpl.specialize(params);
373 const string withExt = injectExtensionRequirements(baseSrc, spec.programs[0].requiredExtensions, glu::SHADERTYPE_VERTEX);
378 // Specialize a shader for the fragment shader test case.
379 string specializeFragmentShader (const ShaderCaseSpecification& spec, const string& src)
383 ostringstream output;
386 // generated from "both" case
387 DE_ASSERT(spec.caseType == glu::sl::CASETYPE_FRAGMENT_ONLY);
389 genCompareFunctions(decl, spec.values, false);
390 genCompareOp(output, "dEQP_FragColor", spec.values, DE_NULL);
392 decl << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
394 for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
396 const Value& val = spec.values.inputs[ndx];
397 const DataType valueType = val.type.getBasicType();
398 const char* const valueTypeStr = getDataTypeName(valueType);
399 const DataType transportType = getTransportType(valueType);
400 const char* const transportTypeStr = getDataTypeName(transportType);
401 const int numLocs = getNumTransportLocations(valueType);
403 decl << "layout(location = " << curInputLoc << ") flat in ";
405 curInputLoc += numLocs;
407 if (valueType == transportType)
408 decl << transportTypeStr << " " << val.name << ";\n";
411 decl << transportTypeStr << " v_" << val.name << ";\n";
412 setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(v_" << val.name << ");\n";
416 declareUniforms(decl, spec.values);
417 declareReferenceBlock(decl, spec.values);
419 for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++)
421 const Value& val = spec.values.outputs[ndx];
422 const DataType basicType = val.type.getBasicType();
423 const char* const refTypeStr = getDataTypeName(basicType);
425 decl << refTypeStr << " " << val.name << ";\n";
428 // Shader specialization.
429 map<string, string> params;
430 params.insert(pair<string, string>("DECLARATIONS", decl.str()));
431 params.insert(pair<string, string>("SETUP", setup.str()));
432 params.insert(pair<string, string>("OUTPUT", output.str()));
433 params.insert(pair<string, string>("POSITION_FRAG_COLOR", "dEQP_FragColor"));
435 StringTemplate tmpl (src);
436 const string baseSrc = tmpl.specialize(params);
437 const string withExt = injectExtensionRequirements(baseSrc, spec.programs[0].requiredExtensions, glu::SHADERTYPE_FRAGMENT);
442 map<string, string> generateVertexSpecialization (const ProgramSpecializationParams& specParams)
446 map<string, string> params;
449 decl << "layout(location = 0) in highp vec4 dEQP_Position;\n";
452 for (size_t ndx = 0; ndx < specParams.caseSpec.values.inputs.size(); ndx++)
454 const Value& val = specParams.caseSpec.values.inputs[ndx];
455 const DataType valueType = val.type.getBasicType();
456 const char* const valueTypeStr = getDataTypeName(valueType);
457 const DataType transportType = getTransportType(valueType);
458 const char* const transportTypeStr = getDataTypeName(transportType);
459 const int numLocs = getNumTransportLocations(valueType);
461 decl << "layout(location = " << curInputLoc << ") in ";
463 curInputLoc += numLocs;
465 if (valueType == transportType)
466 decl << transportTypeStr << " " << val.name << ";\n";
469 decl << transportTypeStr << " a_" << val.name << ";\n";
470 setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(a_" << val.name << ");\n";
474 declareUniforms(decl, specParams.caseSpec.values);
476 params.insert(pair<string, string>("VERTEX_DECLARATIONS", decl.str()));
477 params.insert(pair<string, string>("VERTEX_SETUP", setup.str()));
478 params.insert(pair<string, string>("VERTEX_OUTPUT", string("gl_Position = dEQP_Position;\n")));
483 map<string, string> generateFragmentSpecialization (const ProgramSpecializationParams& specParams)
486 ostringstream output;
487 map<string, string> params;
489 genCompareFunctions(decl, specParams.caseSpec.values, false);
490 genCompareOp(output, "dEQP_FragColor", specParams.caseSpec.values, DE_NULL);
492 decl << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
494 for (size_t ndx = 0; ndx < specParams.caseSpec.values.outputs.size(); ndx++)
496 const Value& val = specParams.caseSpec.values.outputs[ndx];
497 const char* const refTypeStr = getDataTypeName(val.type.getBasicType());
499 decl << refTypeStr << " " << val.name << ";\n";
502 declareReferenceBlock(decl, specParams.caseSpec.values);
503 declareUniforms(decl, specParams.caseSpec.values);
505 params.insert(pair<string, string>("FRAGMENT_DECLARATIONS", decl.str()));
506 params.insert(pair<string, string>("FRAGMENT_OUTPUT", output.str()));
507 params.insert(pair<string, string>("FRAG_COLOR", "dEQP_FragColor"));
512 map<string, string> generateGeometrySpecialization (const ProgramSpecializationParams& specParams)
515 map<string, string> params;
517 decl << "layout (triangles) in;\n";
518 decl << "layout (triangle_strip, max_vertices=3) out;\n";
521 declareUniforms(decl, specParams.caseSpec.values);
523 params.insert(pair<string, string>("GEOMETRY_DECLARATIONS", decl.str()));
528 map<string, string> generateTessControlSpecialization (const ProgramSpecializationParams& specParams)
531 ostringstream output;
532 map<string, string> params;
534 decl << "layout (vertices=3) out;\n";
537 declareUniforms(decl, specParams.caseSpec.values);
539 output << "gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
540 "gl_TessLevelInner[0] = 2.0;\n"
541 "gl_TessLevelInner[1] = 2.0;\n"
542 "gl_TessLevelOuter[0] = 2.0;\n"
543 "gl_TessLevelOuter[1] = 2.0;\n"
544 "gl_TessLevelOuter[2] = 2.0;\n"
545 "gl_TessLevelOuter[3] = 2.0;";
547 params.insert(pair<string, string>("TESSELLATION_CONTROL_DECLARATIONS", decl.str()));
548 params.insert(pair<string, string>("TESSELLATION_CONTROL_OUTPUT", output.str()));
549 params.insert(pair<string, string>("GL_MAX_PATCH_VERTICES", de::toString(specParams.maxPatchVertices)));
554 map<string, string> generateTessEvalSpecialization (const ProgramSpecializationParams& specParams)
557 ostringstream output;
558 map<string, string> params;
560 decl << "layout (triangles) in;\n";
563 declareUniforms(decl, specParams.caseSpec.values);
565 output << "gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position + gl_TessCoord[1] * gl_in[1].gl_Position + gl_TessCoord[2] * gl_in[2].gl_Position;\n";
567 params.insert(pair<string, string>("TESSELLATION_EVALUATION_DECLARATIONS", decl.str()));
568 params.insert(pair<string, string>("TESSELLATION_EVALUATION_OUTPUT", output.str()));
569 params.insert(pair<string, string>("GL_MAX_PATCH_VERTICES", de::toString(specParams.maxPatchVertices)));
574 void specializeShaderSources (ProgramSources& dst,
575 const ProgramSources& src,
576 const ProgramSpecializationParams& specParams,
577 glu::ShaderType shaderType,
578 map<string, string> (*specializationGenerator) (const ProgramSpecializationParams& specParams))
580 if (!src.sources[shaderType].empty())
582 const map<string, string> tmplParams = specializationGenerator(specParams);
584 for (size_t ndx = 0; ndx < src.sources[shaderType].size(); ++ndx)
586 const StringTemplate tmpl (src.sources[shaderType][ndx]);
587 const string baseGLSLCode = tmpl.specialize(tmplParams);
588 const string sourceWithExts = injectExtensionRequirements(baseGLSLCode, specParams.requiredExtensions, shaderType);
590 dst << glu::ShaderSource(shaderType, sourceWithExts);
595 void specializeProgramSources (glu::ProgramSources& dst,
596 const glu::ProgramSources& src,
597 const ProgramSpecializationParams& specParams)
599 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_VERTEX, generateVertexSpecialization);
600 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_FRAGMENT, generateFragmentSpecialization);
601 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_GEOMETRY, generateGeometrySpecialization);
602 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_TESSELLATION_CONTROL, generateTessControlSpecialization);
603 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_TESSELLATION_EVALUATION, generateTessEvalSpecialization);
605 dst << glu::ProgramSeparable(src.separable);
608 struct ValueBufferLayout
613 int vecStride; //! Applies to matrices only
615 Entry (void) : offset(0), vecStride(0) {}
616 Entry (int offset_, int vecStride_) : offset(offset_), vecStride(vecStride_) {}
619 vector<Entry> entries;
622 ValueBufferLayout (void) : size(0) {}
625 ValueBufferLayout computeStd140Layout (const vector<Value>& values)
627 ValueBufferLayout layout;
629 layout.entries.resize(values.size());
631 for (size_t ndx = 0; ndx < values.size(); ++ndx)
633 const DataType basicType = values[ndx].type.getBasicType();
634 const bool isMatrix = isDataTypeMatrix(basicType);
635 const int numVecs = isMatrix ? getDataTypeMatrixNumColumns(basicType) : 1;
636 const DataType vecType = isMatrix ? glu::getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType)) : basicType;
637 const int vecSize = getDataTypeScalarSize(vecType);
638 const int alignment = ((isMatrix || vecSize == 3) ? 4 : vecSize)*int(sizeof(deUint32));
640 layout.size = deAlign32(layout.size, alignment);
641 layout.entries[ndx] = ValueBufferLayout::Entry(layout.size, alignment);
642 layout.size += alignment*(numVecs-1) + vecSize*int(sizeof(deUint32));
648 ValueBufferLayout computeStd430Layout (const vector<Value>& values)
650 ValueBufferLayout layout;
652 layout.entries.resize(values.size());
654 for (size_t ndx = 0; ndx < values.size(); ++ndx)
656 const DataType basicType = values[ndx].type.getBasicType();
657 const int numVecs = isDataTypeMatrix(basicType) ? getDataTypeMatrixNumColumns(basicType) : 1;
658 const DataType vecType = isDataTypeMatrix(basicType) ? glu::getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType)) : basicType;
659 const int vecSize = getDataTypeScalarSize(vecType);
660 const int alignment = (vecSize == 3 ? 4 : vecSize)*int(sizeof(deUint32));
662 layout.size = deAlign32(layout.size, alignment);
663 layout.entries[ndx] = ValueBufferLayout::Entry(layout.size, alignment);
664 layout.size += alignment*(numVecs-1) + vecSize*int(sizeof(deUint32));
670 void copyToLayout (void* dst, const ValueBufferLayout::Entry& entryLayout, const Value& value, int arrayNdx)
672 const DataType basicType = value.type.getBasicType();
673 const int scalarSize = getDataTypeScalarSize(basicType);
674 const int numVecs = isDataTypeMatrix(basicType) ? getDataTypeMatrixNumColumns(basicType) : 1;
675 const int numComps = isDataTypeMatrix(basicType) ? getDataTypeMatrixNumRows(basicType) : scalarSize;
677 DE_ASSERT(size_t((arrayNdx+1)*scalarSize) <= value.elements.size());
679 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
680 deMemcpy((deUint8*)dst + entryLayout.offset + vecNdx*entryLayout.vecStride,
681 &value.elements[arrayNdx*scalarSize + vecNdx*numComps],
682 numComps*sizeof(deUint32));
685 void copyToLayout (void* dst, const ValueBufferLayout& layout, const vector<Value>& values, int arrayNdx)
687 DE_ASSERT(layout.entries.size() == values.size());
689 for (size_t ndx = 0; ndx < values.size(); ndx++)
690 copyToLayout(dst, layout.entries[ndx], values[ndx], arrayNdx);
693 deUint32 getShaderStages (const ShaderCaseSpecification& spec)
695 if (spec.caseType == glu::sl::CASETYPE_COMPLETE)
697 deUint32 stages = 0u;
699 for (size_t progNdx = 0; progNdx < spec.programs.size(); progNdx++)
701 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
703 if (!spec.programs[progNdx].sources.sources[shaderType].empty())
704 stages |= (1u << shaderType);
711 return (1u << glu::SHADERTYPE_VERTEX) | (1u << glu::SHADERTYPE_FRAGMENT);
714 class PipelineProgram
717 PipelineProgram (Context& context, const ShaderCaseSpecification& spec);
719 deUint32 getStages (void) const { return m_stages; }
721 bool hasShader (glu::ShaderType type) const { return (m_stages & (1u << type)) != 0; }
722 vk::VkShaderModule getShader (glu::ShaderType type) const { return *m_shaderModules[type]; }
725 const deUint32 m_stages;
726 Move<vk::VkShaderModule> m_shaderModules[glu::SHADERTYPE_LAST];
729 PipelineProgram::PipelineProgram (Context& context, const ShaderCaseSpecification& spec)
730 : m_stages(getShaderStages(spec))
732 // \note Currently only a single source program is supported as framework lacks SPIR-V linking capability
733 TCU_CHECK_INTERNAL(spec.programs.size() == 1);
735 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
737 if ((m_stages & (1u << shaderType)) != 0)
739 m_shaderModules[shaderType] = vk::createShaderModule(context.getDeviceInterface(), context.getDevice(),
740 context.getBinaryCollection().get(getShaderName((glu::ShaderType)shaderType, 0)), 0u);
745 vector<vk::VkPipelineShaderStageCreateInfo> getPipelineShaderStageCreateInfo (const PipelineProgram& program)
747 vector<vk::VkPipelineShaderStageCreateInfo> infos;
749 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
751 if (program.hasShader((glu::ShaderType)shaderType))
753 const vk::VkPipelineShaderStageCreateInfo info =
755 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType
757 (vk::VkPipelineShaderStageCreateFlags)0,
758 vk::getVkShaderStage((glu::ShaderType)shaderType), // stage
759 program.getShader((glu::ShaderType)shaderType), // module
761 DE_NULL, // pSpecializationInfo
764 infos.push_back(info);
771 Move<vk::VkBuffer> createBuffer (Context& context, vk::VkDeviceSize size, vk::VkBufferUsageFlags usageFlags)
773 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
774 const vk::VkBufferCreateInfo params =
776 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
781 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
782 1u, // queueFamilyCount
783 &queueFamilyIndex, // pQueueFamilyIndices
786 return vk::createBuffer(context.getDeviceInterface(), context.getDevice(), ¶ms);
789 Move<vk::VkImage> createImage2D (Context& context, deUint32 width, deUint32 height, vk::VkFormat format, vk::VkImageTiling tiling, vk::VkImageUsageFlags usageFlags)
791 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
792 const vk::VkImageCreateInfo params =
794 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
797 vk::VK_IMAGE_TYPE_2D, // imageType
799 { width, height, 1u }, // extent
802 vk::VK_SAMPLE_COUNT_1_BIT, // samples
805 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
806 1u, // queueFamilyCount
807 &queueFamilyIndex, // pQueueFamilyIndices
808 vk::VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
811 return vk::createImage(context.getDeviceInterface(), context.getDevice(), ¶ms);
814 Move<vk::VkImageView> createAttachmentView (Context& context, vk::VkImage image, vk::VkFormat format)
816 const vk::VkImageViewCreateInfo params =
818 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType
822 vk::VK_IMAGE_VIEW_TYPE_2D, // viewType
824 vk::makeComponentMappingRGBA(), // channels
826 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
829 0u, // baseArrayLayer
831 }, // subresourceRange
834 return vk::createImageView(context.getDeviceInterface(), context.getDevice(), ¶ms);
837 Move<vk::VkRenderPass> createRenderPass (Context& context, vk::VkFormat colorAttFormat)
839 const vk::VkAttachmentDescription colorAttDesc =
842 colorAttFormat, // format
843 vk::VK_SAMPLE_COUNT_1_BIT, // samples
844 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // loadOp
845 vk::VK_ATTACHMENT_STORE_OP_STORE, // storeOp
846 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
847 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
848 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // initialLayout
849 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // finalLayout
851 const vk::VkAttachmentReference colorAttRef =
854 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // layout
856 const vk::VkAttachmentReference dsAttRef =
858 vk::VK_NO_ATTACHMENT, // attachment
859 vk::VK_IMAGE_LAYOUT_GENERAL, // layout
861 const vk::VkSubpassDescription subpassDesc =
863 (vk::VkSubpassDescriptionFlags)0,
864 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
866 DE_NULL, // pInputAttachments
868 &colorAttRef, // pColorAttachments
869 DE_NULL, // pResolveAttachments
870 &dsAttRef, // depthStencilAttachment
872 DE_NULL, // pPreserveAttachments
875 const vk::VkRenderPassCreateInfo renderPassParams =
877 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // sType
879 (vk::VkRenderPassCreateFlags)0,
880 1u, // attachmentCount
881 &colorAttDesc, // pAttachments
883 &subpassDesc, // pSubpasses
884 0u, // dependencyCount
885 DE_NULL, // pDependencies
888 return vk::createRenderPass(context.getDeviceInterface(), context.getDevice(), &renderPassParams);
891 vk::VkShaderStageFlags getVkStageFlags (deUint32 stages)
893 vk::VkShaderStageFlags vkStages = 0u;
895 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
897 if ((stages & (1u << shaderType)) != 0)
898 vkStages |= vk::getVkShaderStage((glu::ShaderType)shaderType);
904 Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (Context& context, deUint32 shaderStages)
906 DE_STATIC_ASSERT(REFERENCE_UNIFORM_BINDING == 0);
907 DE_STATIC_ASSERT(USER_UNIFORM_BINDING == 1);
909 return vk::DescriptorSetLayoutBuilder()
910 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT)
911 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, getVkStageFlags(shaderStages))
912 .build(context.getDeviceInterface(), context.getDevice());
915 Move<vk::VkPipelineLayout> createPipelineLayout (Context& context, vk::VkDescriptorSetLayout descriptorSetLayout)
917 const vk::VkPipelineLayoutCreateInfo params =
919 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
921 (vk::VkPipelineLayoutCreateFlags)0,
922 1u, // descriptorSetCount
923 &descriptorSetLayout, // pSetLayouts
924 0u, // pushConstantRangeCount
925 DE_NULL, // pPushConstantRanges
928 return vk::createPipelineLayout(context.getDeviceInterface(), context.getDevice(), ¶ms);
931 vk::VkFormat getFloatVecFormat (int scalarSize)
933 const vk::VkFormat vecFmts[] =
935 vk::VK_FORMAT_R32_SFLOAT,
936 vk::VK_FORMAT_R32G32_SFLOAT,
937 vk::VK_FORMAT_R32G32B32_SFLOAT,
938 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
940 return de::getSizedArrayElement<4>(vecFmts, scalarSize-1);
943 vector<vk::VkVertexInputAttributeDescription> getVertexAttributeDescriptions (const vector<Value>& inputValues, const ValueBufferLayout& layout)
945 vector<vk::VkVertexInputAttributeDescription> attribs;
949 const vk::VkVertexInputAttributeDescription posDesc =
953 vk::VK_FORMAT_R32G32_SFLOAT, // format
957 attribs.push_back(posDesc);
961 for (size_t inputNdx = 0; inputNdx < inputValues.size(); inputNdx++)
963 const Value& input = inputValues[inputNdx];
964 const ValueBufferLayout::Entry& layoutEntry = layout.entries[inputNdx];
965 const DataType basicType = input.type.getBasicType();
966 const int numVecs = isDataTypeMatrix(basicType)
967 ? getDataTypeMatrixNumColumns(basicType)
969 const int vecSize = isDataTypeMatrix(basicType)
970 ? getDataTypeMatrixNumRows(basicType)
971 : getDataTypeScalarSize(basicType);
972 const vk::VkFormat vecFmt = getFloatVecFormat(vecSize);
974 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
976 const deUint32 curLoc = (deUint32)attribs.size();
977 const deUint32 offset = (deUint32)(layoutEntry.offset + layoutEntry.vecStride*vecNdx);
978 const vk::VkVertexInputAttributeDescription desc =
986 attribs.push_back(desc);
993 Move<vk::VkPipeline> createPipeline (Context& context,
994 const vector<Value>& inputValues,
995 const ValueBufferLayout& inputLayout,
996 const PipelineProgram& program,
997 vk::VkRenderPass renderPass,
998 vk::VkPipelineLayout pipelineLayout,
999 tcu::UVec2 renderSize)
1001 const vector<vk::VkPipelineShaderStageCreateInfo> shaderStageParams (getPipelineShaderStageCreateInfo(program));
1002 const vector<vk::VkVertexInputAttributeDescription> vertexAttribParams (getVertexAttributeDescriptions(inputValues, inputLayout));
1003 const vk::VkPipelineDepthStencilStateCreateInfo depthStencilParams =
1005 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // sType
1007 (vk::VkPipelineDepthStencilStateCreateFlags)0,
1008 vk::VK_FALSE, // depthTestEnable
1009 vk::VK_FALSE, // depthWriteEnable
1010 vk::VK_COMPARE_OP_ALWAYS, // depthCompareOp
1011 vk::VK_FALSE, // depthBoundsTestEnable
1012 vk::VK_FALSE, // stencilTestEnable
1014 vk::VK_STENCIL_OP_KEEP, // stencilFailOp;
1015 vk::VK_STENCIL_OP_KEEP, // stencilPassOp;
1016 vk::VK_STENCIL_OP_KEEP, // stencilDepthFailOp;
1017 vk::VK_COMPARE_OP_ALWAYS, // stencilCompareOp;
1018 0u, // stencilCompareMask
1019 0u, // stencilWriteMask
1020 0u, // stencilReference
1023 vk::VK_STENCIL_OP_KEEP, // stencilFailOp;
1024 vk::VK_STENCIL_OP_KEEP, // stencilPassOp;
1025 vk::VK_STENCIL_OP_KEEP, // stencilDepthFailOp;
1026 vk::VK_COMPARE_OP_ALWAYS, // stencilCompareOp;
1027 0u, // stencilCompareMask
1028 0u, // stencilWriteMask
1029 0u, // stencilReference
1031 -1.0f, // minDepthBounds
1032 +1.0f, // maxDepthBounds
1034 const vk::VkViewport viewport0 =
1038 (float)renderSize.x(), // width
1039 (float)renderSize.y(), // height
1043 const vk::VkRect2D scissor0 =
1045 { 0u, 0u }, // offset
1046 { renderSize.x(), renderSize.y() } // extent
1048 const vk::VkPipelineViewportStateCreateInfo viewportParams =
1050 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // sType
1052 (vk::VkPipelineViewportStateCreateFlags)0,
1053 1u, // viewportCount
1054 &viewport0, // pViewports
1056 &scissor0, // pScissors
1058 const vk::VkPipelineMultisampleStateCreateInfo multisampleParams =
1060 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // sType
1062 (vk::VkPipelineMultisampleStateCreateFlags)0,
1063 vk::VK_SAMPLE_COUNT_1_BIT, // rasterSamples
1064 DE_FALSE, // sampleShadingEnable
1065 0.0f, // minSampleShading
1066 DE_NULL, // pSampleMask
1067 vk::VK_FALSE, // alphaToCoverageEnable
1068 vk::VK_FALSE, // alphaToOneEnable
1070 const vk::VkPipelineRasterizationStateCreateInfo rasterParams =
1072 vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // sType
1074 (vk::VkPipelineRasterizationStateCreateFlags)0,
1075 DE_TRUE, // depthClipEnable
1076 DE_FALSE, // rasterizerDiscardEnable
1077 vk::VK_POLYGON_MODE_FILL, // fillMode
1078 vk::VK_CULL_MODE_NONE, // cullMode;
1079 vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace;
1080 vk::VK_FALSE, // depthBiasEnable
1081 0.0f, // depthBiasConstantFactor
1082 0.0f, // depthBiasClamp
1083 0.0f, // depthBiasSlopeFactor
1086 const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyParams =
1088 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // sType
1090 (vk::VkPipelineInputAssemblyStateCreateFlags)0,
1091 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // topology
1092 DE_FALSE, // primitiveRestartEnable
1094 const vk::VkVertexInputBindingDescription vertexBindings[] =
1098 (deUint32)sizeof(tcu::Vec2), // stride
1099 vk::VK_VERTEX_INPUT_RATE_VERTEX, // stepRate
1104 vk::VK_VERTEX_INPUT_RATE_INSTANCE, // stepRate
1107 const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
1109 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // sType
1111 (vk::VkPipelineVertexInputStateCreateFlags)0,
1112 DE_LENGTH_OF_ARRAY(vertexBindings), // bindingCount
1113 vertexBindings, // pVertexBindingDescriptions
1114 (deUint32)vertexAttribParams.size(), // attributeCount
1115 &vertexAttribParams[0], // pVertexAttributeDescriptions
1117 const vk::VkColorComponentFlags allCompMask = vk::VK_COLOR_COMPONENT_R_BIT
1118 | vk::VK_COLOR_COMPONENT_G_BIT
1119 | vk::VK_COLOR_COMPONENT_B_BIT
1120 | vk::VK_COLOR_COMPONENT_A_BIT;
1121 const vk::VkPipelineColorBlendAttachmentState attBlendParams =
1123 vk::VK_FALSE, // blendEnable
1124 vk::VK_BLEND_FACTOR_ONE, // srcBlendColor
1125 vk::VK_BLEND_FACTOR_ZERO, // destBlendColor
1126 vk::VK_BLEND_OP_ADD, // blendOpColor
1127 vk::VK_BLEND_FACTOR_ONE, // srcBlendAlpha
1128 vk::VK_BLEND_FACTOR_ZERO, // destBlendAlpha
1129 vk::VK_BLEND_OP_ADD, // blendOpAlpha
1130 allCompMask, // componentWriteMask
1132 const vk::VkPipelineColorBlendStateCreateInfo blendParams =
1134 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // sType
1136 (vk::VkPipelineColorBlendStateCreateFlags)0,
1137 vk::VK_FALSE, // logicOpEnable
1138 vk::VK_LOGIC_OP_COPY, // logicOp
1139 1u, // attachmentCount
1140 &attBlendParams, // pAttachments
1141 { 0.0f, 0.0f, 0.0f, 0.0f }, // blendConstants
1143 const vk::VkPipelineDynamicStateCreateInfo dynStateParams =
1145 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // sType
1147 (vk::VkPipelineDynamicStateCreateFlags)0,
1148 0u, // dynamicStateCount
1149 DE_NULL, // pDynamicStates
1151 const vk::VkGraphicsPipelineCreateInfo pipelineParams =
1153 vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // sType
1156 (deUint32)shaderStageParams.size(), // stageCount
1157 &shaderStageParams[0], // pStages
1158 &vertexInputStateParams, // pVertexInputState
1159 &inputAssemblyParams, // pInputAssemblyState
1160 DE_NULL, // pTessellationState
1161 &viewportParams, // pViewportState
1162 &rasterParams, // pRasterState
1163 &multisampleParams, // pMultisampleState
1164 &depthStencilParams, // pDepthStencilState
1165 &blendParams, // pColorBlendState
1166 &dynStateParams, // pDynamicState
1167 pipelineLayout, // layout
1168 renderPass, // renderPass
1170 DE_NULL, // basePipelineHandle
1171 0u, // basePipelineIndex
1174 return vk::createGraphicsPipeline(context.getDeviceInterface(), context.getDevice(), DE_NULL, &pipelineParams);
1177 Move<vk::VkFramebuffer> createFramebuffer (Context& context, vk::VkRenderPass renderPass, vk::VkImageView colorAttView, int width, int height)
1179 const vk::VkFramebufferCreateInfo framebufferParams =
1181 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // sType
1183 (vk::VkFramebufferCreateFlags)0,
1184 renderPass, // renderPass
1185 1u, // attachmentCount
1186 &colorAttView, // pAttachments
1187 (deUint32)width, // width
1188 (deUint32)height, // height
1192 return vk::createFramebuffer(context.getDeviceInterface(), context.getDevice(), &framebufferParams);
1195 Move<vk::VkCommandPool> createCommandPool (Context& context)
1197 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1198 const vk::VkCommandPoolCreateInfo params =
1200 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType
1202 (vk::VkCommandPoolCreateFlags)0,
1203 queueFamilyIndex, // queueFamilyIndex
1206 return vk::createCommandPool(context.getDeviceInterface(), context.getDevice(), ¶ms);
1209 Move<vk::VkDescriptorPool> createDescriptorPool (Context& context)
1211 return vk::DescriptorPoolBuilder()
1212 .addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u)
1213 .build(context.getDeviceInterface(), context.getDevice(), vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1216 Move<vk::VkDescriptorSet> allocateDescriptorSet (Context& context, vk::VkDescriptorPool descriptorPool, vk::VkDescriptorSetLayout setLayout)
1218 const vk::VkDescriptorSetAllocateInfo params =
1220 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1227 return vk::allocateDescriptorSet(context.getDeviceInterface(), context.getDevice(), ¶ms);
1230 Move<vk::VkCommandBuffer> allocateCommandBuffer (Context& context, vk::VkCommandPool cmdPool)
1232 const vk::VkCommandBufferAllocateInfo params =
1234 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
1236 cmdPool, // commandPool
1237 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
1241 return vk::allocateCommandBuffer(context.getDeviceInterface(), context.getDevice(), ¶ms);
1244 MovePtr<vk::Allocation> allocateAndBindMemory (Context& context, vk::VkBuffer buffer, vk::MemoryRequirement memReqs)
1246 const vk::DeviceInterface& vkd = context.getDeviceInterface();
1247 const vk::VkMemoryRequirements bufReqs = vk::getBufferMemoryRequirements(vkd, context.getDevice(), buffer);
1248 MovePtr<vk::Allocation> memory = context.getDefaultAllocator().allocate(bufReqs, memReqs);
1250 vkd.bindBufferMemory(context.getDevice(), buffer, memory->getMemory(), memory->getOffset());
1255 MovePtr<vk::Allocation> allocateAndBindMemory (Context& context, vk::VkImage image, vk::MemoryRequirement memReqs)
1257 const vk::DeviceInterface& vkd = context.getDeviceInterface();
1258 const vk::VkMemoryRequirements imgReqs = vk::getImageMemoryRequirements(vkd, context.getDevice(), image);
1259 MovePtr<vk::Allocation> memory = context.getDefaultAllocator().allocate(imgReqs, memReqs);
1261 vkd.bindImageMemory(context.getDevice(), image, memory->getMemory(), memory->getOffset());
1266 void writeValuesToMem (Context& context, const vk::Allocation& dst, const ValueBufferLayout& layout, const vector<Value>& values, int arrayNdx)
1268 copyToLayout(dst.getHostPtr(), layout, values, arrayNdx);
1270 // \note Buffers are not allocated with coherency / uncached requirement so we need to manually flush CPU write caches
1271 flushMappedMemoryRange(context.getDeviceInterface(), context.getDevice(), dst.getMemory(), dst.getOffset(), (vk::VkDeviceSize)layout.size);
1274 class ShaderCaseInstance : public TestInstance
1277 ShaderCaseInstance (Context& context, const ShaderCaseSpecification& spec);
1278 ~ShaderCaseInstance (void);
1280 TestStatus iterate (void);
1288 POSITIONS_OFFSET = 0,
1289 POSITIONS_SIZE = (int)sizeof(Vec2)*4,
1291 INDICES_OFFSET = POSITIONS_SIZE,
1292 INDICES_SIZE = (int)sizeof(deUint16)*6,
1294 TOTAL_POS_NDX_SIZE = POSITIONS_SIZE+INDICES_SIZE
1297 const ShaderCaseSpecification& m_spec;
1299 const Unique<vk::VkBuffer> m_posNdxBuffer;
1300 const UniquePtr<vk::Allocation> m_posNdxMem;
1302 const ValueBufferLayout m_inputLayout;
1303 const Unique<vk::VkBuffer> m_inputBuffer; // Input values (attributes). Can be NULL if no inputs present
1304 const UniquePtr<vk::Allocation> m_inputMem; // Input memory, can be NULL if no input buffer exists
1306 const ValueBufferLayout m_referenceLayout;
1307 const Unique<vk::VkBuffer> m_referenceBuffer; // Output (reference) values. Can be NULL if no outputs present
1308 const UniquePtr<vk::Allocation> m_referenceMem; // Output (reference) memory, can be NULL if no reference buffer exists
1310 const ValueBufferLayout m_uniformLayout;
1311 const Unique<vk::VkBuffer> m_uniformBuffer; // Uniform values. Can be NULL if no uniforms present
1312 const UniquePtr<vk::Allocation> m_uniformMem; // Uniform memory, can be NULL if no uniform buffer exists
1314 const Unique<vk::VkBuffer> m_readImageBuffer;
1315 const UniquePtr<vk::Allocation> m_readImageMem;
1317 const Unique<vk::VkImage> m_rtImage;
1318 const UniquePtr<vk::Allocation> m_rtMem;
1319 const Unique<vk::VkImageView> m_rtView;
1321 const Unique<vk::VkRenderPass> m_renderPass;
1322 const Unique<vk::VkFramebuffer> m_framebuffer;
1323 const PipelineProgram m_program;
1324 const Unique<vk::VkDescriptorSetLayout> m_descriptorSetLayout;
1325 const Unique<vk::VkPipelineLayout> m_pipelineLayout;
1326 const Unique<vk::VkPipeline> m_pipeline;
1328 const Unique<vk::VkDescriptorPool> m_descriptorPool;
1329 const Unique<vk::VkDescriptorSet> m_descriptorSet;
1331 const Unique<vk::VkCommandPool> m_cmdPool;
1332 const Unique<vk::VkCommandBuffer> m_cmdBuffer;
1337 ShaderCaseInstance::ShaderCaseInstance (Context& context, const ShaderCaseSpecification& spec)
1338 : TestInstance (context)
1341 , m_posNdxBuffer (createBuffer(context, (vk::VkDeviceSize)TOTAL_POS_NDX_SIZE, vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT|vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))
1342 , m_posNdxMem (allocateAndBindMemory(context, *m_posNdxBuffer, vk::MemoryRequirement::HostVisible))
1344 , m_inputLayout (computeStd430Layout(spec.values.inputs))
1345 , m_inputBuffer (m_inputLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_inputLayout.size, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) : Move<vk::VkBuffer>())
1346 , m_inputMem (m_inputLayout.size > 0 ? allocateAndBindMemory(context, *m_inputBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>())
1348 , m_referenceLayout (computeStd140Layout(spec.values.outputs))
1349 , m_referenceBuffer (m_referenceLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_referenceLayout.size, vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : Move<vk::VkBuffer>())
1350 , m_referenceMem (m_referenceLayout.size > 0 ? allocateAndBindMemory(context, *m_referenceBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>())
1352 , m_uniformLayout (computeStd140Layout(spec.values.uniforms))
1353 , m_uniformBuffer (m_uniformLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_uniformLayout.size, vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : Move<vk::VkBuffer>())
1354 , m_uniformMem (m_uniformLayout.size > 0 ? allocateAndBindMemory(context, *m_uniformBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>())
1356 , m_readImageBuffer (createBuffer(context, (vk::VkDeviceSize)(RENDER_WIDTH*RENDER_HEIGHT*4), vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT))
1357 , m_readImageMem (allocateAndBindMemory(context, *m_readImageBuffer, vk::MemoryRequirement::HostVisible))
1359 , m_rtImage (createImage2D(context, RENDER_WIDTH, RENDER_HEIGHT, vk::VK_FORMAT_R8G8B8A8_UNORM, vk::VK_IMAGE_TILING_OPTIMAL, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT))
1360 , m_rtMem (allocateAndBindMemory(context, *m_rtImage, vk::MemoryRequirement::Any))
1361 , m_rtView (createAttachmentView(context, *m_rtImage, vk::VK_FORMAT_R8G8B8A8_UNORM))
1363 , m_renderPass (createRenderPass(context, vk::VK_FORMAT_R8G8B8A8_UNORM))
1364 , m_framebuffer (createFramebuffer(context, *m_renderPass, *m_rtView, RENDER_WIDTH, RENDER_HEIGHT))
1365 , m_program (context, spec)
1366 , m_descriptorSetLayout (createDescriptorSetLayout(context, m_program.getStages()))
1367 , m_pipelineLayout (createPipelineLayout(context, *m_descriptorSetLayout))
1368 , m_pipeline (createPipeline(context, spec.values.inputs, m_inputLayout, m_program, *m_renderPass, *m_pipelineLayout, tcu::UVec2(RENDER_WIDTH, RENDER_HEIGHT)))
1370 , m_descriptorPool (createDescriptorPool(context))
1371 , m_descriptorSet (allocateDescriptorSet(context, *m_descriptorPool, *m_descriptorSetLayout))
1373 , m_cmdPool (createCommandPool(context))
1374 , m_cmdBuffer (allocateCommandBuffer(context, *m_cmdPool))
1378 const vk::DeviceInterface& vkd = context.getDeviceInterface();
1379 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1382 const Vec2 s_positions[] =
1389 const deUint16 s_indices[] =
1395 DE_STATIC_ASSERT(sizeof(s_positions) == POSITIONS_SIZE);
1396 DE_STATIC_ASSERT(sizeof(s_indices) == INDICES_SIZE);
1398 deMemcpy((deUint8*)m_posNdxMem->getHostPtr() + POSITIONS_OFFSET, &s_positions[0], sizeof(s_positions));
1399 deMemcpy((deUint8*)m_posNdxMem->getHostPtr() + INDICES_OFFSET, &s_indices[0], sizeof(s_indices));
1401 flushMappedMemoryRange(m_context.getDeviceInterface(), context.getDevice(), m_posNdxMem->getMemory(), m_posNdxMem->getOffset(), sizeof(s_positions)+sizeof(s_indices));
1404 if (!m_spec.values.uniforms.empty())
1406 const vk::VkDescriptorBufferInfo bufInfo =
1409 (vk::VkDeviceSize)0, // offset
1410 (vk::VkDeviceSize)m_uniformLayout.size
1413 vk::DescriptorSetUpdateBuilder()
1414 .writeSingle(*m_descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(USER_UNIFORM_BINDING),
1415 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufInfo)
1416 .update(vkd, m_context.getDevice());
1419 if (!m_spec.values.outputs.empty())
1421 const vk::VkDescriptorBufferInfo bufInfo =
1424 (vk::VkDeviceSize)0, // offset
1425 (vk::VkDeviceSize)m_referenceLayout.size
1428 vk::DescriptorSetUpdateBuilder()
1429 .writeSingle(*m_descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(REFERENCE_UNIFORM_BINDING),
1430 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufInfo)
1431 .update(vkd, m_context.getDevice());
1434 // Record command buffer
1437 const vk::VkCommandBufferBeginInfo beginInfo =
1439 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
1442 (const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
1445 VK_CHECK(vkd.beginCommandBuffer(*m_cmdBuffer, &beginInfo));
1449 const vk::VkMemoryBarrier vertFlushBarrier =
1451 vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER, // sType
1453 vk::VK_ACCESS_HOST_WRITE_BIT, // srcAccessMask
1454 vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT|vk::VK_ACCESS_UNIFORM_READ_BIT, // dstAccessMask
1456 const vk::VkImageMemoryBarrier colorAttBarrier =
1458 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
1460 0u, // srcAccessMask
1461 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // dstAccessMask
1462 vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
1463 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
1464 queueFamilyIndex, // srcQueueFamilyIndex
1465 queueFamilyIndex, // destQueueFamilyIndex
1466 *m_rtImage, // image
1468 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
1471 0u, // baseArraySlice
1473 } // subresourceRange
1476 vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (vk::VkDependencyFlags)0,
1477 1, &vertFlushBarrier,
1478 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1479 1, &colorAttBarrier);
1483 const vk::VkClearValue clearValue = vk::makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
1484 const vk::VkRenderPassBeginInfo passBeginInfo =
1486 vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // sType
1488 *m_renderPass, // renderPass
1489 *m_framebuffer, // framebuffer
1490 { { 0, 0 }, { RENDER_WIDTH, RENDER_HEIGHT } }, // renderArea
1491 1u, // clearValueCount
1492 &clearValue, // pClearValues
1495 vkd.cmdBeginRenderPass(*m_cmdBuffer, &passBeginInfo, vk::VK_SUBPASS_CONTENTS_INLINE);
1498 vkd.cmdBindPipeline (*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1499 vkd.cmdBindDescriptorSets (*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, DE_NULL);
1502 const vk::VkBuffer buffers[] = { *m_posNdxBuffer, *m_inputBuffer };
1503 const vk::VkDeviceSize offsets[] = { POSITIONS_OFFSET, 0u };
1504 const deUint32 numBuffers = buffers[1] != 0 ? 2u : 1u;
1505 vkd.cmdBindVertexBuffers(*m_cmdBuffer, 0u, numBuffers, buffers, offsets);
1508 vkd.cmdBindIndexBuffer (*m_cmdBuffer, *m_posNdxBuffer, (vk::VkDeviceSize)INDICES_OFFSET, vk::VK_INDEX_TYPE_UINT16);
1509 vkd.cmdDrawIndexed (*m_cmdBuffer, 6u, 1u, 0u, 0u, 0u);
1510 vkd.cmdEndRenderPass (*m_cmdBuffer);
1513 const vk::VkImageMemoryBarrier renderFinishBarrier =
1515 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
1517 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask
1518 vk::VK_ACCESS_TRANSFER_READ_BIT, // dstAccessMask
1519 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // oldLayout
1520 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout
1521 queueFamilyIndex, // srcQueueFamilyIndex
1522 queueFamilyIndex, // destQueueFamilyIndex
1523 *m_rtImage, // image
1525 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
1528 0u, // baseArraySlice
1530 } // subresourceRange
1533 vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0,
1534 0, (const vk::VkMemoryBarrier*)DE_NULL,
1535 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1536 1, &renderFinishBarrier);
1540 const vk::VkBufferImageCopy copyParams =
1542 (vk::VkDeviceSize)0u, // bufferOffset
1543 (deUint32)RENDER_WIDTH, // bufferRowLength
1544 (deUint32)RENDER_HEIGHT, // bufferImageHeight
1546 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspect
1550 }, // imageSubresource
1551 { 0u, 0u, 0u }, // imageOffset
1552 { RENDER_WIDTH, RENDER_HEIGHT, 1u } // imageExtent
1555 vkd.cmdCopyImageToBuffer(*m_cmdBuffer, *m_rtImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_readImageBuffer, 1u, ©Params);
1559 const vk::VkBufferMemoryBarrier copyFinishBarrier =
1561 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
1563 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask
1564 vk::VK_ACCESS_HOST_READ_BIT, // dstAccessMask
1565 queueFamilyIndex, // srcQueueFamilyIndex
1566 queueFamilyIndex, // destQueueFamilyIndex
1567 *m_readImageBuffer, // buffer
1569 (vk::VkDeviceSize)(RENDER_WIDTH*RENDER_HEIGHT*4) // size
1572 vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0,
1573 0, (const vk::VkMemoryBarrier*)DE_NULL,
1574 1, ©FinishBarrier,
1575 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
1578 VK_CHECK(vkd.endCommandBuffer(*m_cmdBuffer));
1581 ShaderCaseInstance::~ShaderCaseInstance (void)
1585 int getNumSubCases (const ValueBlock& values)
1587 if (!values.outputs.empty())
1588 return int(values.outputs[0].elements.size() / values.outputs[0].type.getScalarSize());
1590 return 1; // Always run at least one iteration even if no output values are specified
1593 bool checkResultImage (const ConstPixelBufferAccess& result)
1595 const tcu::IVec4 refPix (255, 255, 255, 255);
1597 for (int y = 0; y < result.getHeight(); y++)
1599 for (int x = 0; x < result.getWidth(); x++)
1601 const tcu::IVec4 resPix = result.getPixelInt(x, y);
1603 if (boolAny(notEqual(resPix, refPix)))
1611 TestStatus ShaderCaseInstance::iterate (void)
1613 const vk::DeviceInterface& vkd = m_context.getDeviceInterface();
1614 const vk::VkDevice device = m_context.getDevice();
1615 const vk::VkQueue queue = m_context.getUniversalQueue();
1617 if (!m_spec.values.inputs.empty())
1618 writeValuesToMem(m_context, *m_inputMem, m_inputLayout, m_spec.values.inputs, m_subCaseNdx);
1620 if (!m_spec.values.outputs.empty())
1621 writeValuesToMem(m_context, *m_referenceMem, m_referenceLayout, m_spec.values.outputs, m_subCaseNdx);
1623 if (!m_spec.values.uniforms.empty())
1624 writeValuesToMem(m_context, *m_uniformMem, m_uniformLayout, m_spec.values.uniforms, m_subCaseNdx);
1627 const vk::VkSubmitInfo submitInfo =
1629 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1631 0u, // waitSemaphoreCount
1632 (const vk::VkSemaphore*)0, // pWaitSemaphores
1633 (const vk::VkPipelineStageFlags*)DE_NULL,
1636 0u, // signalSemaphoreCount
1637 (const vk::VkSemaphore*)0, // pSignalSemaphores
1639 const vk::VkFenceCreateInfo fenceParams =
1641 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // sType
1645 const Unique<vk::VkFence> fence (vk::createFence(vkd, device, &fenceParams));
1647 VK_CHECK(vkd.queueSubmit (queue, 1u, &submitInfo, *fence));
1648 VK_CHECK(vkd.waitForFences (device, 1u, &fence.get(), DE_TRUE, ~0ull));
1652 const ConstPixelBufferAccess imgAccess (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), RENDER_WIDTH, RENDER_HEIGHT, 1, m_readImageMem->getHostPtr());
1654 invalidateMappedMemoryRange(vkd, device, m_readImageMem->getMemory(), m_readImageMem->getOffset(), (vk::VkDeviceSize)(RENDER_WIDTH*RENDER_HEIGHT*4));
1656 if (!checkResultImage(imgAccess))
1658 TestLog& log = m_context.getTestContext().getLog();
1660 log << TestLog::Message << "ERROR: Got non-white pixels on sub-case " << m_subCaseNdx << TestLog::EndMessage
1661 << TestLog::Image("Result", "Result", imgAccess);
1663 dumpValues(log, m_spec.values, m_subCaseNdx);
1665 return TestStatus::fail(string("Got invalid pixels at sub-case ") + de::toString(m_subCaseNdx));
1669 if (++m_subCaseNdx < getNumSubCases(m_spec.values))
1670 return TestStatus::incomplete();
1672 return TestStatus::pass("All sub-cases passed");
1675 class ShaderCase : public TestCase
1678 ShaderCase (tcu::TestContext& testCtx, const string& name, const string& description, const ShaderCaseSpecification& spec);
1681 void initPrograms (SourceCollections& programCollection) const;
1682 TestInstance* createInstance (Context& context) const;
1685 const ShaderCaseSpecification m_spec;
1688 ShaderCase::ShaderCase (tcu::TestContext& testCtx, const string& name, const string& description, const ShaderCaseSpecification& spec)
1689 : TestCase (testCtx, name, description)
1694 void ShaderCase::initPrograms (SourceCollections& sourceCollection) const
1696 vector<ProgramSources> specializedSources (m_spec.programs.size());
1698 DE_ASSERT(isValid(m_spec));
1700 if (m_spec.expectResult != glu::sl::EXPECT_PASS)
1701 TCU_THROW(InternalError, "Only EXPECT_PASS is supported");
1703 if (m_spec.caseType == glu::sl::CASETYPE_VERTEX_ONLY)
1705 DE_ASSERT(m_spec.programs.size() == 1 && m_spec.programs[0].sources.sources[glu::SHADERTYPE_VERTEX].size() == 1);
1706 specializedSources[0] << glu::VertexSource(specializeVertexShader(m_spec, m_spec.programs[0].sources.sources[glu::SHADERTYPE_VERTEX][0]))
1707 << glu::FragmentSource(genFragmentShader(m_spec));
1709 else if (m_spec.caseType == glu::sl::CASETYPE_FRAGMENT_ONLY)
1711 DE_ASSERT(m_spec.programs.size() == 1 && m_spec.programs[0].sources.sources[glu::SHADERTYPE_FRAGMENT].size() == 1);
1712 specializedSources[0] << glu::VertexSource(genVertexShader(m_spec))
1713 << glu::FragmentSource(specializeFragmentShader(m_spec, m_spec.programs[0].sources.sources[glu::SHADERTYPE_FRAGMENT][0]));
1717 DE_ASSERT(m_spec.caseType == glu::sl::CASETYPE_COMPLETE);
1719 const int maxPatchVertices = 4; // \todo [2015-08-05 pyry] Query
1721 for (size_t progNdx = 0; progNdx < m_spec.programs.size(); progNdx++)
1723 const ProgramSpecializationParams progSpecParams (m_spec, m_spec.programs[progNdx].requiredExtensions, maxPatchVertices);
1725 specializeProgramSources(specializedSources[progNdx], m_spec.programs[progNdx].sources, progSpecParams);
1729 for (size_t progNdx = 0; progNdx < specializedSources.size(); progNdx++)
1731 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
1733 if (!specializedSources[progNdx].sources[shaderType].empty())
1735 glu::ProgramSources& curSrc = sourceCollection.glslSources.add(getShaderName((glu::ShaderType)shaderType, progNdx));
1736 curSrc.sources[shaderType] = specializedSources[progNdx].sources[shaderType];
1742 TestInstance* ShaderCase::createInstance (Context& context) const
1744 return new ShaderCaseInstance(context, m_spec);
1747 class ShaderCaseFactory : public glu::sl::ShaderCaseFactory
1750 ShaderCaseFactory (tcu::TestContext& testCtx)
1751 : m_testCtx(testCtx)
1755 tcu::TestCaseGroup* createGroup (const string& name, const string& description, const vector<tcu::TestNode*>& children)
1757 return new tcu::TestCaseGroup(m_testCtx, name.c_str(), description.c_str(), children);
1760 tcu::TestCase* createCase (const string& name, const string& description, const ShaderCaseSpecification& spec)
1762 return new ShaderCase(m_testCtx, name, description, spec);
1766 tcu::TestContext& m_testCtx;
1769 class ShaderLibraryGroup : public tcu::TestCaseGroup
1772 ShaderLibraryGroup (tcu::TestContext& testCtx, const string& name, const string& description, const string& filename)
1773 : tcu::TestCaseGroup (testCtx, name.c_str(), description.c_str())
1774 , m_filename (filename)
1780 ShaderCaseFactory caseFactory (m_testCtx);
1781 const vector<tcu::TestNode*> children = glu::sl::parseFile(m_testCtx.getArchive(), m_filename, &caseFactory);
1783 for (size_t ndx = 0; ndx < children.size(); ndx++)
1787 addChild(children[ndx]);
1791 for (; ndx < children.size(); ndx++)
1792 delete children[ndx];
1799 const string m_filename;
1804 MovePtr<tcu::TestCaseGroup> createShaderLibraryGroup (tcu::TestContext& testCtx, const string& name, const string& description, const string& filename)
1806 return MovePtr<tcu::TestCaseGroup>(new ShaderLibraryGroup(testCtx, name, description, filename));