1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 Google Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief ShaderLibrary Vulkan implementation
22 *//*--------------------------------------------------------------------*/
24 #include "vktShaderLibrary.hpp"
25 #include "vktTestCase.hpp"
27 #include "vkPrograms.hpp"
29 #include "vkRefUtil.hpp"
30 #include "vkMemUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkCmdUtil.hpp"
36 #include "vkObjUtil.hpp"
38 #include "gluShaderLibrary.hpp"
39 #include "gluShaderUtil.hpp"
41 #include "tcuStringTemplate.hpp"
42 #include "tcuTexture.hpp"
43 #include "tcuTestLog.hpp"
44 #include "tcuVector.hpp"
45 #include "tcuVectorUtil.hpp"
47 #include "deStringUtil.hpp"
48 #include "deArrayUtil.hpp"
61 using std::ostringstream;
66 using glu::ShaderType;
67 using glu::ProgramSources;
70 using glu::sl::ShaderCaseSpecification;
71 using glu::sl::ProgramSpecializationParams;
72 using glu::sl::RequiredExtension;
74 using glu::sl::ValueBlock;
76 using tcu::TestStatus;
77 using tcu::StringTemplate;
79 using tcu::ConstPixelBufferAccess;
80 using tcu::TextureFormat;
83 using vk::SourceCollections;
92 REFERENCE_UNIFORM_BINDING = 0,
93 USER_UNIFORM_BINDING = 1
96 string getShaderName (ShaderType shaderType, size_t progNdx)
99 str << glu::getShaderTypeName(shaderType);
101 str << "_" << progNdx;
105 void genUniformBlock (ostringstream& out, const string& blockName, const string& instanceName, int setNdx, int bindingNdx, const vector<Value>& uniforms)
110 out << "set = " << setNdx << ", ";
112 out << "binding = " << bindingNdx << ", std140) uniform " << blockName << "\n"
115 for (vector<Value>::const_iterator val = uniforms.begin(); val != uniforms.end(); ++val)
116 out << "\t" << glu::declare(val->type, val->name, 1) << ";\n";
120 if (!instanceName.empty())
121 out << " " << instanceName;
126 void declareReferenceBlock (ostringstream& out, const ValueBlock& valueBlock)
128 if (!valueBlock.outputs.empty())
129 genUniformBlock(out, "Reference", "ref", 0, REFERENCE_UNIFORM_BINDING, valueBlock.outputs);
132 void declareUniforms (ostringstream& out, const ValueBlock& valueBlock)
134 if (!valueBlock.uniforms.empty())
135 genUniformBlock(out, "Uniforms", "", 0, USER_UNIFORM_BINDING, valueBlock.uniforms);
138 DataType getTransportType (DataType valueType)
140 if (isDataTypeBoolOrBVec(valueType))
141 return glu::getDataTypeUintVec(getDataTypeScalarSize(valueType));
146 int getNumTransportLocations (DataType valueType)
148 return isDataTypeMatrix(valueType) ? getDataTypeMatrixNumColumns(valueType) : 1;
151 // This functions builds a matching vertex shader for a 'both' case, when
152 // the fragment shader is being tested.
153 // We need to build attributes and varyings for each 'input'.
154 string genVertexShader (const ShaderCaseSpecification& spec)
158 int curOutputLoc = 0;
160 res << glu::getGLSLVersionDeclaration(spec.targetVersion) << "\n";
162 // Declarations (position + attribute/varying for each input).
163 res << "precision highp float;\n";
164 res << "precision highp int;\n";
166 res << "layout(location = 0) in highp vec4 dEQP_Position;\n";
169 for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
171 const Value& val = spec.values.inputs[ndx];
172 const DataType valueType = val.type.getBasicType();
173 const DataType transportType = getTransportType(valueType);
174 const char* const transportTypeStr = getDataTypeName(transportType);
175 const int numLocs = getNumTransportLocations(valueType);
177 res << "layout(location = " << curInputLoc << ") in " << transportTypeStr << " a_" << val.name << ";\n";
178 res << "layout(location = " << curOutputLoc << ") flat out " << transportTypeStr << " " << (transportType != valueType ? "v_" : "") << val.name << ";\n";
180 curInputLoc += numLocs;
181 curOutputLoc += numLocs;
186 // - gl_Position = dEQP_Position;
187 // - for each input: write attribute directly to varying
188 res << "void main()\n";
190 res << " gl_Position = dEQP_Position;\n";
191 for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
193 const Value& val = spec.values.inputs[ndx];
194 const string& name = val.name;
196 res << " " << (getTransportType(val.type.getBasicType()) != val.type.getBasicType() ? "v_" : "")
197 << name << " = a_" << name << ";\n";
204 void genCompareOp (ostringstream& output, const char* dstVec4Var, const ValueBlock& valueBlock, const char* checkVarName)
206 bool isFirstOutput = true;
208 for (size_t ndx = 0; ndx < valueBlock.outputs.size(); ndx++)
210 const Value& val = valueBlock.outputs[ndx];
212 // Check if we're only interested in one variable (then skip if not the right one).
213 if (checkVarName && val.name != checkVarName)
219 output << "bool RES = ";
220 isFirstOutput = false;
223 output << "RES = RES && ";
225 // Generate actual comparison.
226 if (getDataTypeScalarType(val.type.getBasicType()) == glu::TYPE_FLOAT)
227 output << "isOk(" << val.name << ", ref." << val.name << ", 0.05);\n";
229 output << "isOk(" << val.name << ", ref." << val.name << ");\n";
233 output << dstVec4Var << " = vec4(1.0);\n";
235 output << dstVec4Var << " = vec4(RES, RES, RES, 1.0);\n";
238 string genFragmentShader (const ShaderCaseSpecification& spec)
240 ostringstream shader;
244 shader << glu::getGLSLVersionDeclaration(spec.targetVersion) << "\n";
246 shader << "precision highp float;\n";
247 shader << "precision highp int;\n";
250 shader << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
253 genCompareFunctions(shader, spec.values, false);
256 // Declarations (varying, reference for each output).
257 for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++)
259 const Value& val = spec.values.outputs[ndx];
260 const DataType valueType = val.type.getBasicType();
261 const char* const valueTypeStr = getDataTypeName(valueType);
262 const DataType transportType = getTransportType(valueType);
263 const char* const transportTypeStr = getDataTypeName(transportType);
264 const int numLocs = getNumTransportLocations(valueType);
266 shader << "layout(location = " << curInLoc << ") flat in " << transportTypeStr << " " << (valueType != transportType ? "v_" : "") << val.name << ";\n";
268 if (valueType != transportType)
269 setup << " " << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(v_" << val.name << ");\n";
274 declareReferenceBlock(shader, spec.values);
277 shader << "void main()\n";
280 shader << setup.str();
283 genCompareOp(shader, "dEQP_FragColor", spec.values, DE_NULL);
289 // Specialize a shader for the vertex shader test case.
290 string specializeVertexShader (const ShaderCaseSpecification& spec, const string& src)
294 ostringstream output;
296 int curOutputLoc = 0;
298 // generated from "both" case
299 DE_ASSERT(spec.caseType == glu::sl::CASETYPE_VERTEX_ONLY);
301 // Output (write out position).
302 output << "gl_Position = dEQP_Position;\n";
304 // Declarations (position + attribute for each input, varying for each output).
305 decl << "layout(location = 0) in highp vec4 dEQP_Position;\n";
308 for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
310 const Value& val = spec.values.inputs[ndx];
311 const DataType valueType = val.type.getBasicType();
312 const char* const valueTypeStr = getDataTypeName(valueType);
313 const DataType transportType = getTransportType(valueType);
314 const char* const transportTypeStr = getDataTypeName(transportType);
315 const int numLocs = getNumTransportLocations(valueType);
317 decl << "layout(location = " << curInputLoc << ") in ";
319 curInputLoc += numLocs;
321 if (valueType == transportType)
322 decl << transportTypeStr << " " << val.name << ";\n";
325 decl << transportTypeStr << " a_" << val.name << ";\n";
326 setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(a_" << val.name << ");\n";
330 declareUniforms(decl, spec.values);
332 for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++)
334 const Value& val = spec.values.outputs[ndx];
335 const DataType valueType = val.type.getBasicType();
336 const char* const valueTypeStr = getDataTypeName(valueType);
337 const DataType transportType = getTransportType(valueType);
338 const char* const transportTypeStr = getDataTypeName(transportType);
339 const int numLocs = getNumTransportLocations(valueType);
341 decl << "layout(location = " << curOutputLoc << ") flat out ";
343 curOutputLoc += numLocs;
345 if (valueType == transportType)
346 decl << transportTypeStr << " " << val.name << ";\n";
349 decl << transportTypeStr << " v_" << val.name << ";\n";
350 decl << valueTypeStr << " " << val.name << ";\n";
352 output << "v_" << val.name << " = " << transportTypeStr << "(" << val.name << ");\n";
356 // Shader specialization.
357 map<string, string> params;
358 params.insert(pair<string, string>("DECLARATIONS", decl.str()));
359 params.insert(pair<string, string>("SETUP", setup.str()));
360 params.insert(pair<string, string>("OUTPUT", output.str()));
361 params.insert(pair<string, string>("POSITION_FRAG_COLOR", "gl_Position"));
363 StringTemplate tmpl (src);
364 const string baseSrc = tmpl.specialize(params);
365 const string withExt = injectExtensionRequirements(baseSrc, spec.programs[0].requiredExtensions, glu::SHADERTYPE_VERTEX);
370 // Specialize a shader for the fragment shader test case.
371 string specializeFragmentShader (const ShaderCaseSpecification& spec, const string& src)
375 ostringstream output;
378 // generated from "both" case
379 DE_ASSERT(spec.caseType == glu::sl::CASETYPE_FRAGMENT_ONLY);
381 genCompareFunctions(decl, spec.values, false);
382 genCompareOp(output, "dEQP_FragColor", spec.values, DE_NULL);
384 decl << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
386 for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
388 const Value& val = spec.values.inputs[ndx];
389 const DataType valueType = val.type.getBasicType();
390 const char* const valueTypeStr = getDataTypeName(valueType);
391 const DataType transportType = getTransportType(valueType);
392 const char* const transportTypeStr = getDataTypeName(transportType);
393 const int numLocs = getNumTransportLocations(valueType);
395 decl << "layout(location = " << curInputLoc << ") flat in ";
397 curInputLoc += numLocs;
399 if (valueType == transportType)
400 decl << transportTypeStr << " " << val.name << ";\n";
403 decl << transportTypeStr << " v_" << val.name << ";\n";
404 setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(v_" << val.name << ");\n";
408 declareUniforms(decl, spec.values);
409 declareReferenceBlock(decl, spec.values);
411 for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++)
413 const Value& val = spec.values.outputs[ndx];
414 const DataType basicType = val.type.getBasicType();
415 const char* const refTypeStr = getDataTypeName(basicType);
417 decl << refTypeStr << " " << val.name << ";\n";
420 // Shader specialization.
421 map<string, string> params;
422 params.insert(pair<string, string>("DECLARATIONS", decl.str()));
423 params.insert(pair<string, string>("SETUP", setup.str()));
424 params.insert(pair<string, string>("OUTPUT", output.str()));
425 params.insert(pair<string, string>("POSITION_FRAG_COLOR", "dEQP_FragColor"));
427 StringTemplate tmpl (src);
428 const string baseSrc = tmpl.specialize(params);
429 const string withExt = injectExtensionRequirements(baseSrc, spec.programs[0].requiredExtensions, glu::SHADERTYPE_FRAGMENT);
434 map<string, string> generateVertexSpecialization (const ProgramSpecializationParams& specParams)
438 map<string, string> params;
441 decl << "layout(location = 0) in highp vec4 dEQP_Position;\n";
444 for (size_t ndx = 0; ndx < specParams.caseSpec.values.inputs.size(); ndx++)
446 const Value& val = specParams.caseSpec.values.inputs[ndx];
447 const DataType valueType = val.type.getBasicType();
448 const char* const valueTypeStr = getDataTypeName(valueType);
449 const DataType transportType = getTransportType(valueType);
450 const char* const transportTypeStr = getDataTypeName(transportType);
451 const int numLocs = getNumTransportLocations(valueType);
453 decl << "layout(location = " << curInputLoc << ") in ";
455 curInputLoc += numLocs;
457 if (valueType == transportType)
458 decl << transportTypeStr << " " << val.name << ";\n";
461 decl << transportTypeStr << " a_" << val.name << ";\n";
462 setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(a_" << val.name << ");\n";
466 declareUniforms(decl, specParams.caseSpec.values);
468 params.insert(pair<string, string>("VERTEX_DECLARATIONS", decl.str()));
469 params.insert(pair<string, string>("VERTEX_SETUP", setup.str()));
470 params.insert(pair<string, string>("VERTEX_OUTPUT", string("gl_Position = dEQP_Position;\n")));
475 map<string, string> generateFragmentSpecialization (const ProgramSpecializationParams& specParams)
478 ostringstream output;
479 map<string, string> params;
481 genCompareFunctions(decl, specParams.caseSpec.values, false);
482 genCompareOp(output, "dEQP_FragColor", specParams.caseSpec.values, DE_NULL);
484 decl << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
486 for (size_t ndx = 0; ndx < specParams.caseSpec.values.outputs.size(); ndx++)
488 const Value& val = specParams.caseSpec.values.outputs[ndx];
489 const char* const refTypeStr = getDataTypeName(val.type.getBasicType());
491 decl << refTypeStr << " " << val.name << ";\n";
494 declareReferenceBlock(decl, specParams.caseSpec.values);
495 declareUniforms(decl, specParams.caseSpec.values);
497 params.insert(pair<string, string>("FRAGMENT_DECLARATIONS", decl.str()));
498 params.insert(pair<string, string>("FRAGMENT_OUTPUT", output.str()));
499 params.insert(pair<string, string>("FRAG_COLOR", "dEQP_FragColor"));
504 map<string, string> generateGeometrySpecialization (const ProgramSpecializationParams& specParams)
507 map<string, string> params;
509 decl << "layout (triangles) in;\n";
510 decl << "layout (triangle_strip, max_vertices=3) out;\n";
513 declareUniforms(decl, specParams.caseSpec.values);
515 params.insert(pair<string, string>("GEOMETRY_DECLARATIONS", decl.str()));
520 map<string, string> generateTessControlSpecialization (const ProgramSpecializationParams& specParams)
523 ostringstream output;
524 map<string, string> params;
526 decl << "layout (vertices=3) out;\n";
529 declareUniforms(decl, specParams.caseSpec.values);
531 output << "gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
532 "gl_TessLevelInner[0] = 2.0;\n"
533 "gl_TessLevelInner[1] = 2.0;\n"
534 "gl_TessLevelOuter[0] = 2.0;\n"
535 "gl_TessLevelOuter[1] = 2.0;\n"
536 "gl_TessLevelOuter[2] = 2.0;\n"
537 "gl_TessLevelOuter[3] = 2.0;";
539 params.insert(pair<string, string>("TESSELLATION_CONTROL_DECLARATIONS", decl.str()));
540 params.insert(pair<string, string>("TESSELLATION_CONTROL_OUTPUT", output.str()));
541 params.insert(pair<string, string>("GL_MAX_PATCH_VERTICES", de::toString(specParams.maxPatchVertices)));
546 map<string, string> generateTessEvalSpecialization (const ProgramSpecializationParams& specParams)
549 ostringstream output;
550 map<string, string> params;
552 decl << "layout (triangles) in;\n";
555 declareUniforms(decl, specParams.caseSpec.values);
557 output << "gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position + gl_TessCoord[1] * gl_in[1].gl_Position + gl_TessCoord[2] * gl_in[2].gl_Position;\n";
559 params.insert(pair<string, string>("TESSELLATION_EVALUATION_DECLARATIONS", decl.str()));
560 params.insert(pair<string, string>("TESSELLATION_EVALUATION_OUTPUT", output.str()));
561 params.insert(pair<string, string>("GL_MAX_PATCH_VERTICES", de::toString(specParams.maxPatchVertices)));
566 void specializeShaderSources (ProgramSources& dst,
567 const ProgramSources& src,
568 const ProgramSpecializationParams& specParams,
569 glu::ShaderType shaderType,
570 map<string, string> (*specializationGenerator) (const ProgramSpecializationParams& specParams))
572 if (!src.sources[shaderType].empty())
574 const map<string, string> tmplParams = specializationGenerator(specParams);
576 for (size_t ndx = 0; ndx < src.sources[shaderType].size(); ++ndx)
578 const StringTemplate tmpl (src.sources[shaderType][ndx]);
579 const string baseGLSLCode = tmpl.specialize(tmplParams);
580 const string sourceWithExts = injectExtensionRequirements(baseGLSLCode, specParams.requiredExtensions, shaderType);
582 dst << glu::ShaderSource(shaderType, sourceWithExts);
587 void specializeProgramSources (glu::ProgramSources& dst,
588 const glu::ProgramSources& src,
589 const ProgramSpecializationParams& specParams)
591 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_VERTEX, generateVertexSpecialization);
592 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_FRAGMENT, generateFragmentSpecialization);
593 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_GEOMETRY, generateGeometrySpecialization);
594 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_TESSELLATION_CONTROL, generateTessControlSpecialization);
595 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_TESSELLATION_EVALUATION, generateTessEvalSpecialization);
597 dst << glu::ProgramSeparable(src.separable);
600 struct ValueBufferLayout
605 int vecStride; //! Applies to matrices only
607 Entry (void) : offset(0), vecStride(0) {}
608 Entry (int offset_, int vecStride_) : offset(offset_), vecStride(vecStride_) {}
611 vector<Entry> entries;
614 ValueBufferLayout (void) : size(0) {}
617 ValueBufferLayout computeStd140Layout (const vector<Value>& values)
619 ValueBufferLayout layout;
621 layout.entries.resize(values.size());
623 for (size_t ndx = 0; ndx < values.size(); ++ndx)
625 const DataType basicType = values[ndx].type.getBasicType();
626 const bool isMatrix = isDataTypeMatrix(basicType);
627 const int numVecs = isMatrix ? getDataTypeMatrixNumColumns(basicType) : 1;
628 const DataType vecType = isMatrix ? glu::getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType)) : basicType;
629 const int vecSize = getDataTypeScalarSize(vecType);
630 const int alignment = ((isMatrix || vecSize == 3) ? 4 : vecSize)*int(sizeof(deUint32));
632 layout.size = deAlign32(layout.size, alignment);
633 layout.entries[ndx] = ValueBufferLayout::Entry(layout.size, alignment);
634 layout.size += alignment*(numVecs-1) + vecSize*int(sizeof(deUint32));
640 ValueBufferLayout computeStd430Layout (const vector<Value>& values)
642 ValueBufferLayout layout;
644 layout.entries.resize(values.size());
646 for (size_t ndx = 0; ndx < values.size(); ++ndx)
648 const DataType basicType = values[ndx].type.getBasicType();
649 const int numVecs = isDataTypeMatrix(basicType) ? getDataTypeMatrixNumColumns(basicType) : 1;
650 const DataType vecType = isDataTypeMatrix(basicType) ? glu::getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType)) : basicType;
651 const int vecSize = getDataTypeScalarSize(vecType);
652 const int alignment = (vecSize == 3 ? 4 : vecSize)*int(sizeof(deUint32));
654 layout.size = deAlign32(layout.size, alignment);
655 layout.entries[ndx] = ValueBufferLayout::Entry(layout.size, alignment);
656 layout.size += alignment*(numVecs-1) + vecSize*int(sizeof(deUint32));
662 void copyToLayout (void* dst, const ValueBufferLayout::Entry& entryLayout, const Value& value, int arrayNdx)
664 const DataType basicType = value.type.getBasicType();
665 const int scalarSize = getDataTypeScalarSize(basicType);
666 const int numVecs = isDataTypeMatrix(basicType) ? getDataTypeMatrixNumColumns(basicType) : 1;
667 const int numComps = isDataTypeMatrix(basicType) ? getDataTypeMatrixNumRows(basicType) : scalarSize;
669 DE_ASSERT(size_t((arrayNdx+1)*scalarSize) <= value.elements.size());
671 if (isDataTypeBoolOrBVec(basicType))
673 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
675 for (int compNdx = 0; compNdx < numComps; compNdx++)
677 const deUint32 data = value.elements[arrayNdx*scalarSize + vecNdx*numComps + compNdx].bool32 ? ~0u : 0u;
679 deMemcpy((deUint8*)dst + entryLayout.offset + vecNdx*entryLayout.vecStride + compNdx * sizeof(deUint32),
687 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
688 deMemcpy((deUint8*)dst + entryLayout.offset + vecNdx*entryLayout.vecStride,
689 &value.elements[arrayNdx*scalarSize + vecNdx*numComps],
690 numComps*sizeof(deUint32));
694 void copyToLayout (void* dst, const ValueBufferLayout& layout, const vector<Value>& values, int arrayNdx)
696 DE_ASSERT(layout.entries.size() == values.size());
698 for (size_t ndx = 0; ndx < values.size(); ndx++)
699 copyToLayout(dst, layout.entries[ndx], values[ndx], arrayNdx);
702 deUint32 getShaderStages (const ShaderCaseSpecification& spec)
704 if (spec.caseType == glu::sl::CASETYPE_COMPLETE)
706 deUint32 stages = 0u;
708 for (size_t progNdx = 0; progNdx < spec.programs.size(); progNdx++)
710 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
712 if (!spec.programs[progNdx].sources.sources[shaderType].empty())
713 stages |= (1u << shaderType);
720 return (1u << glu::SHADERTYPE_VERTEX) | (1u << glu::SHADERTYPE_FRAGMENT);
723 class PipelineProgram
726 PipelineProgram (Context& context, const ShaderCaseSpecification& spec);
728 deUint32 getStages (void) const { return m_stages; }
730 bool hasShader (glu::ShaderType type) const { return (m_stages & (1u << type)) != 0; }
731 vk::VkShaderModule getShader (glu::ShaderType type) const { return *m_shaderModules[type]; }
734 const deUint32 m_stages;
735 Move<vk::VkShaderModule> m_shaderModules[glu::SHADERTYPE_LAST];
738 PipelineProgram::PipelineProgram (Context& context, const ShaderCaseSpecification& spec)
739 : m_stages(getShaderStages(spec))
741 // \note Currently only a single source program is supported as framework lacks SPIR-V linking capability
742 TCU_CHECK_INTERNAL(spec.programs.size() == 1);
744 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
746 if ((m_stages & (1u << shaderType)) != 0)
748 m_shaderModules[shaderType] = vk::createShaderModule(context.getDeviceInterface(), context.getDevice(),
749 context.getBinaryCollection().get(getShaderName((glu::ShaderType)shaderType, 0)), 0u);
754 Move<vk::VkBuffer> createBuffer (Context& context, vk::VkDeviceSize size, vk::VkBufferUsageFlags usageFlags)
756 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
757 const vk::VkBufferCreateInfo params =
759 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
764 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
765 1u, // queueFamilyCount
766 &queueFamilyIndex, // pQueueFamilyIndices
769 return vk::createBuffer(context.getDeviceInterface(), context.getDevice(), ¶ms);
772 Move<vk::VkImage> createImage2D (Context& context, deUint32 width, deUint32 height, vk::VkFormat format, vk::VkImageTiling tiling, vk::VkImageUsageFlags usageFlags)
774 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
775 const vk::VkImageCreateInfo params =
777 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
780 vk::VK_IMAGE_TYPE_2D, // imageType
782 { width, height, 1u }, // extent
785 vk::VK_SAMPLE_COUNT_1_BIT, // samples
788 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
789 1u, // queueFamilyCount
790 &queueFamilyIndex, // pQueueFamilyIndices
791 vk::VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
794 return vk::createImage(context.getDeviceInterface(), context.getDevice(), ¶ms);
797 Move<vk::VkImageView> createAttachmentView (Context& context, vk::VkImage image, vk::VkFormat format)
799 const vk::VkImageViewCreateInfo params =
801 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType
805 vk::VK_IMAGE_VIEW_TYPE_2D, // viewType
807 vk::makeComponentMappingRGBA(), // channels
809 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
812 0u, // baseArrayLayer
814 }, // subresourceRange
817 return vk::createImageView(context.getDeviceInterface(), context.getDevice(), ¶ms);
820 Move<vk::VkRenderPass> createRenderPass (Context& context, vk::VkFormat colorAttFormat, deUint32 size)
822 vk::VkAttachmentDescription colorAttDesc[4];
823 vk::VkAttachmentReference colorAttRef[4];
825 for (deUint32 i = 0; i < size; i++)
827 vk::VkAttachmentDescription desc =
830 colorAttFormat, // format
831 vk::VK_SAMPLE_COUNT_1_BIT, // samples
832 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // loadOp
833 vk::VK_ATTACHMENT_STORE_OP_STORE, // storeOp
834 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
835 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
836 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // initialLayout
837 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // finalLayout
839 colorAttDesc[i] = desc;
841 vk::VkAttachmentReference ref =
844 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // layout
846 colorAttRef[i] = ref;
849 const vk::VkAttachmentReference dsAttRef =
851 VK_ATTACHMENT_UNUSED, // attachment
852 vk::VK_IMAGE_LAYOUT_GENERAL, // layout
854 const vk::VkSubpassDescription subpassDesc =
856 (vk::VkSubpassDescriptionFlags)0,
857 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
859 DE_NULL, // pInputAttachments
861 &colorAttRef[0], // pColorAttachments
862 DE_NULL, // pResolveAttachments
863 &dsAttRef, // depthStencilAttachment
865 DE_NULL, // pPreserveAttachments
868 const vk::VkRenderPassCreateInfo renderPassParams =
870 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // sType
872 (vk::VkRenderPassCreateFlags)0,
873 size, // attachmentCount
874 &colorAttDesc[0], // pAttachments
876 &subpassDesc, // pSubpasses
877 0u, // dependencyCount
878 DE_NULL, // pDependencies
881 return vk::createRenderPass(context.getDeviceInterface(), context.getDevice(), &renderPassParams);
884 vk::VkShaderStageFlags getVkStageFlags (deUint32 stages)
886 vk::VkShaderStageFlags vkStages = 0u;
888 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
890 if ((stages & (1u << shaderType)) != 0)
891 vkStages |= vk::getVkShaderStage((glu::ShaderType)shaderType);
897 Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (Context& context, deUint32 shaderStages)
899 DE_STATIC_ASSERT(REFERENCE_UNIFORM_BINDING == 0);
900 DE_STATIC_ASSERT(USER_UNIFORM_BINDING == 1);
902 return vk::DescriptorSetLayoutBuilder()
903 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT)
904 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, getVkStageFlags(shaderStages))
905 .build(context.getDeviceInterface(), context.getDevice());
908 Move<vk::VkPipelineLayout> createPipelineLayout (Context& context, vk::VkDescriptorSetLayout descriptorSetLayout)
910 const vk::VkPipelineLayoutCreateInfo params =
912 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
914 (vk::VkPipelineLayoutCreateFlags)0,
915 1u, // descriptorSetCount
916 &descriptorSetLayout, // pSetLayouts
917 0u, // pushConstantRangeCount
918 DE_NULL, // pPushConstantRanges
921 return vk::createPipelineLayout(context.getDeviceInterface(), context.getDevice(), ¶ms);
924 vk::VkFormat getVecFormat (DataType scalarType, int scalarSize)
928 case glu::TYPE_FLOAT:
930 const vk::VkFormat vecFmts[] =
932 vk::VK_FORMAT_R32_SFLOAT,
933 vk::VK_FORMAT_R32G32_SFLOAT,
934 vk::VK_FORMAT_R32G32B32_SFLOAT,
935 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
937 return de::getSizedArrayElement<4>(vecFmts, scalarSize-1);
942 const vk::VkFormat vecFmts[] =
944 vk::VK_FORMAT_R32_SINT,
945 vk::VK_FORMAT_R32G32_SINT,
946 vk::VK_FORMAT_R32G32B32_SINT,
947 vk::VK_FORMAT_R32G32B32A32_SINT,
949 return de::getSizedArrayElement<4>(vecFmts, scalarSize-1);
954 const vk::VkFormat vecFmts[] =
956 vk::VK_FORMAT_R32_UINT,
957 vk::VK_FORMAT_R32G32_UINT,
958 vk::VK_FORMAT_R32G32B32_UINT,
959 vk::VK_FORMAT_R32G32B32A32_UINT,
961 return de::getSizedArrayElement<4>(vecFmts, scalarSize-1);
966 const vk::VkFormat vecFmts[] =
968 vk::VK_FORMAT_R32_UINT,
969 vk::VK_FORMAT_R32G32_UINT,
970 vk::VK_FORMAT_R32G32B32_UINT,
971 vk::VK_FORMAT_R32G32B32A32_UINT,
973 return de::getSizedArrayElement<4>(vecFmts, scalarSize-1);
977 DE_FATAL("Unknown scalar type");
978 return vk::VK_FORMAT_R8G8B8A8_UINT;
982 vector<vk::VkVertexInputAttributeDescription> getVertexAttributeDescriptions (const vector<Value>& inputValues, const ValueBufferLayout& layout)
984 vector<vk::VkVertexInputAttributeDescription> attribs;
988 const vk::VkVertexInputAttributeDescription posDesc =
992 vk::VK_FORMAT_R32G32_SFLOAT, // format
996 attribs.push_back(posDesc);
1000 for (size_t inputNdx = 0; inputNdx < inputValues.size(); inputNdx++)
1002 const Value& input = inputValues[inputNdx];
1003 const ValueBufferLayout::Entry& layoutEntry = layout.entries[inputNdx];
1004 const DataType basicType = input.type.getBasicType();
1005 const int numVecs = isDataTypeMatrix(basicType)
1006 ? getDataTypeMatrixNumColumns(basicType)
1008 const int vecSize = isDataTypeMatrix(basicType)
1009 ? getDataTypeMatrixNumRows(basicType)
1010 : getDataTypeScalarSize(basicType);
1011 const DataType scalarType = getDataTypeScalarType(basicType);
1012 const vk::VkFormat vecFmt = getVecFormat(scalarType, vecSize);
1014 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
1016 const deUint32 curLoc = (deUint32)attribs.size();
1017 const deUint32 offset = (deUint32)(layoutEntry.offset + layoutEntry.vecStride*vecNdx);
1018 const vk::VkVertexInputAttributeDescription desc =
1026 attribs.push_back(desc);
1033 Move<vk::VkPipeline> createPipeline (Context& context,
1034 const vector<Value>& inputValues,
1035 const ValueBufferLayout& inputLayout,
1036 const PipelineProgram& program,
1037 vk::VkRenderPass renderPass,
1038 vk::VkPipelineLayout pipelineLayout,
1039 tcu::UVec2 renderSize,
1042 const vk::VkShaderModule vertShader = program.hasShader(glu::SHADERTYPE_VERTEX) ? program.getShader(glu::SHADERTYPE_VERTEX) : DE_NULL;
1043 const vk::VkShaderModule tessControlShader = program.hasShader(glu::SHADERTYPE_TESSELLATION_CONTROL) ? program.getShader(glu::SHADERTYPE_TESSELLATION_CONTROL) : DE_NULL;
1044 const vk::VkShaderModule tessEvalShader = program.hasShader(glu::SHADERTYPE_TESSELLATION_EVALUATION) ? program.getShader(glu::SHADERTYPE_TESSELLATION_EVALUATION) : DE_NULL;
1045 const vk::VkShaderModule geomShader = program.hasShader(glu::SHADERTYPE_GEOMETRY) ? program.getShader(glu::SHADERTYPE_GEOMETRY) : DE_NULL;
1046 const vk::VkShaderModule fragShader = program.hasShader(glu::SHADERTYPE_FRAGMENT) ? program.getShader(glu::SHADERTYPE_FRAGMENT) : DE_NULL;
1047 const vector<vk::VkVertexInputAttributeDescription> vertexAttribParams (getVertexAttributeDescriptions(inputValues, inputLayout));
1048 const vector<vk::VkViewport> viewports (1, vk::makeViewport(renderSize));
1049 const vector<vk::VkRect2D> scissors (1, vk::makeRect2D(renderSize));
1050 const vk::VkVertexInputBindingDescription vertexBindings[] =
1054 (deUint32)sizeof(tcu::Vec2), // stride
1055 vk::VK_VERTEX_INPUT_RATE_VERTEX, // stepRate
1060 vk::VK_VERTEX_INPUT_RATE_INSTANCE, // stepRate
1063 const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
1065 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // sType
1067 (vk::VkPipelineVertexInputStateCreateFlags)0,
1068 (inputValues.empty() ? 1u : 2u), // bindingCount
1069 vertexBindings, // pVertexBindingDescriptions
1070 (deUint32)vertexAttribParams.size(), // attributeCount
1071 &vertexAttribParams[0], // pVertexAttributeDescriptions
1073 const vk::VkColorComponentFlags allCompMask = vk::VK_COLOR_COMPONENT_R_BIT
1074 | vk::VK_COLOR_COMPONENT_G_BIT
1075 | vk::VK_COLOR_COMPONENT_B_BIT
1076 | vk::VK_COLOR_COMPONENT_A_BIT;
1077 vk::VkPipelineColorBlendAttachmentState attBlendParams[4];
1078 for (deUint32 i = 0; i < size; i++)
1080 vk::VkPipelineColorBlendAttachmentState blend =
1082 VK_FALSE, // blendEnable
1083 vk::VK_BLEND_FACTOR_ONE, // srcBlendColor
1084 vk::VK_BLEND_FACTOR_ZERO, // destBlendColor
1085 vk::VK_BLEND_OP_ADD, // blendOpColor
1086 vk::VK_BLEND_FACTOR_ONE, // srcBlendAlpha
1087 vk::VK_BLEND_FACTOR_ZERO, // destBlendAlpha
1088 vk::VK_BLEND_OP_ADD, // blendOpAlpha
1089 allCompMask, // componentWriteMask
1091 attBlendParams[i] = blend;
1094 const vk::VkPipelineColorBlendStateCreateInfo blendParams =
1096 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // sType
1098 (vk::VkPipelineColorBlendStateCreateFlags)0,
1099 VK_FALSE, // logicOpEnable
1100 vk::VK_LOGIC_OP_COPY, // logicOp
1101 size, // attachmentCount
1102 &attBlendParams[0], // pAttachments
1103 { 0.0f, 0.0f, 0.0f, 0.0f }, // blendConstants
1106 return vk::makeGraphicsPipeline(context.getDeviceInterface(), // const DeviceInterface& vk
1107 context.getDevice(), // const VkDevice device
1108 pipelineLayout, // const VkPipelineLayout pipelineLayout
1109 vertShader, // const VkShaderModule vertexShaderModule
1110 tessControlShader, // const VkShaderModule tessellationControlShaderModule
1111 tessEvalShader, // const VkShaderModule tessellationEvalShaderModule
1112 geomShader, // const VkShaderModule geometryShaderModule
1113 fragShader, // const VkShaderModule fragmentShaderModule
1114 renderPass, // const VkRenderPass renderPass
1115 viewports, // const std::vector<VkViewport>& viewports
1116 scissors, // const std::vector<VkRect2D>& scissors
1117 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
1118 0u, // const deUint32 subpass
1119 0u, // const deUint32 patchControlPoints
1120 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
1121 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1122 DE_NULL, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
1123 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
1124 &blendParams); // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo
1127 Move<vk::VkFramebuffer> createFramebuffer (Context& context, vk::VkRenderPass renderPass, Move<vk::VkImageView> colorAttView[4], deUint32 size, int width, int height)
1129 vk::VkImageView att[4];
1130 for (deUint32 i = 0; i < size; i++)
1132 att[i] = *colorAttView[i];
1134 const vk::VkFramebufferCreateInfo framebufferParams =
1136 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // sType
1138 (vk::VkFramebufferCreateFlags)0,
1139 renderPass, // renderPass
1140 size, // attachmentCount
1141 &att[0], // pAttachments
1142 (deUint32)width, // width
1143 (deUint32)height, // height
1147 return vk::createFramebuffer(context.getDeviceInterface(), context.getDevice(), &framebufferParams);
1150 Move<vk::VkCommandPool> createCommandPool (Context& context)
1152 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1154 return vk::createCommandPool(context.getDeviceInterface(), context.getDevice(), (vk::VkCommandPoolCreateFlags)0u, queueFamilyIndex);
1157 Move<vk::VkDescriptorPool> createDescriptorPool (Context& context)
1159 return vk::DescriptorPoolBuilder()
1160 .addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u)
1161 .build(context.getDeviceInterface(), context.getDevice(), vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1164 Move<vk::VkDescriptorSet> allocateDescriptorSet (Context& context, vk::VkDescriptorPool descriptorPool, vk::VkDescriptorSetLayout setLayout)
1166 const vk::VkDescriptorSetAllocateInfo params =
1168 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1175 return vk::allocateDescriptorSet(context.getDeviceInterface(), context.getDevice(), ¶ms);
1178 Move<vk::VkCommandBuffer> allocateCommandBuffer (Context& context, vk::VkCommandPool cmdPool)
1180 return vk::allocateCommandBuffer(context.getDeviceInterface(), context.getDevice(), cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1183 vk::VkFormat getRenderTargetFormat (DataType dataType)
1187 case glu::TYPE_FLOAT_VEC2:
1188 return vk::VK_FORMAT_R8G8_UNORM;
1189 case glu::TYPE_FLOAT_VEC3:
1190 return vk::VK_FORMAT_R5G6B5_UNORM_PACK16;
1191 case glu::TYPE_FLOAT_VEC4:
1192 return vk::VK_FORMAT_R8G8B8A8_UNORM;
1193 case glu::TYPE_INT_VEC2:
1194 return vk::VK_FORMAT_R8G8_SINT;
1195 case glu::TYPE_INT_VEC4:
1196 return vk::VK_FORMAT_R8G8B8A8_SINT;
1198 return vk::VK_FORMAT_R8G8B8A8_UNORM;
1202 MovePtr<vk::Allocation> allocateAndBindMemory (Context& context, vk::VkImage image, vk::MemoryRequirement memReqs)
1204 const vk::DeviceInterface& vkd = context.getDeviceInterface();
1205 const vk::VkMemoryRequirements imgReqs = vk::getImageMemoryRequirements(vkd, context.getDevice(), image);
1206 MovePtr<vk::Allocation> memory = context.getDefaultAllocator().allocate(imgReqs, memReqs);
1208 vkd.bindImageMemory(context.getDevice(), image, memory->getMemory(), memory->getOffset());
1213 void writeValuesToMem (Context& context, const vk::Allocation& dst, const ValueBufferLayout& layout, const vector<Value>& values, int arrayNdx)
1215 copyToLayout(dst.getHostPtr(), layout, values, arrayNdx);
1217 // \note Buffers are not allocated with coherency / uncached requirement so we need to manually flush CPU write caches
1218 flushAlloc(context.getDeviceInterface(), context.getDevice(), dst);
1221 class ShaderCaseInstance : public TestInstance
1224 ShaderCaseInstance (Context& context, const ShaderCaseSpecification& spec);
1225 ~ShaderCaseInstance (void);
1227 TestStatus iterate (void);
1235 POSITIONS_OFFSET = 0,
1236 POSITIONS_SIZE = (int)sizeof(Vec2)*4,
1238 INDICES_OFFSET = POSITIONS_SIZE,
1239 INDICES_SIZE = (int)sizeof(deUint16)*6,
1241 TOTAL_POS_NDX_SIZE = POSITIONS_SIZE+INDICES_SIZE
1244 const ShaderCaseSpecification& m_spec;
1246 const Unique<vk::VkBuffer> m_posNdxBuffer;
1247 const UniquePtr<vk::Allocation> m_posNdxMem;
1249 const ValueBufferLayout m_inputLayout;
1250 const Unique<vk::VkBuffer> m_inputBuffer; // Input values (attributes). Can be NULL if no inputs present
1251 const UniquePtr<vk::Allocation> m_inputMem; // Input memory, can be NULL if no input buffer exists
1253 const ValueBufferLayout m_referenceLayout;
1254 const Unique<vk::VkBuffer> m_referenceBuffer; // Output (reference) values. Can be NULL if no outputs present
1255 const UniquePtr<vk::Allocation> m_referenceMem; // Output (reference) memory, can be NULL if no reference buffer exists
1257 const ValueBufferLayout m_uniformLayout;
1258 const Unique<vk::VkBuffer> m_uniformBuffer; // Uniform values. Can be NULL if no uniforms present
1259 const UniquePtr<vk::Allocation> m_uniformMem; // Uniform memory, can be NULL if no uniform buffer exists
1261 const vk::VkFormat m_rtFormat;
1262 deUint32 m_outputCount;
1263 Move<vk::VkImage> m_rtImage [4];
1264 MovePtr<vk::Allocation> m_rtMem[4];
1265 Move<vk::VkImageView> m_rtView[4];
1267 Move<vk::VkBuffer> m_readImageBuffer[4];
1268 MovePtr<vk::Allocation> m_readImageMem[4];
1270 const Unique<vk::VkRenderPass> m_renderPass;
1271 Move<vk::VkFramebuffer> m_framebuffer;
1272 const PipelineProgram m_program;
1273 const Unique<vk::VkDescriptorSetLayout> m_descriptorSetLayout;
1274 const Unique<vk::VkPipelineLayout> m_pipelineLayout;
1275 const Unique<vk::VkPipeline> m_pipeline;
1277 const Unique<vk::VkDescriptorPool> m_descriptorPool;
1278 const Unique<vk::VkDescriptorSet> m_descriptorSet;
1280 const Unique<vk::VkCommandPool> m_cmdPool;
1281 const Unique<vk::VkCommandBuffer> m_cmdBuffer;
1286 ShaderCaseInstance::ShaderCaseInstance (Context& context, const ShaderCaseSpecification& spec)
1287 : TestInstance (context)
1290 , m_posNdxBuffer (createBuffer(context, (vk::VkDeviceSize)TOTAL_POS_NDX_SIZE, vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT|vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))
1291 , m_posNdxMem (vk::bindBuffer (context.getDeviceInterface(), context.getDevice(),m_context.getDefaultAllocator(), *m_posNdxBuffer, vk::MemoryRequirement::HostVisible))
1293 , m_inputLayout (computeStd430Layout(spec.values.inputs))
1294 , m_inputBuffer (m_inputLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_inputLayout.size, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) : Move<vk::VkBuffer>())
1295 , m_inputMem (m_inputLayout.size > 0 ? vk::bindBuffer (context.getDeviceInterface(), context.getDevice(),m_context.getDefaultAllocator(), *m_inputBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>())
1297 , m_referenceLayout (computeStd140Layout(spec.values.outputs))
1298 , m_referenceBuffer (m_referenceLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_referenceLayout.size, vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : Move<vk::VkBuffer>())
1299 , m_referenceMem (m_referenceLayout.size > 0 ? vk::bindBuffer (context.getDeviceInterface(), context.getDevice(),m_context.getDefaultAllocator(), *m_referenceBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>())
1301 , m_uniformLayout (computeStd140Layout(spec.values.uniforms))
1302 , m_uniformBuffer (m_uniformLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_uniformLayout.size, vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : Move<vk::VkBuffer>())
1303 , m_uniformMem (m_uniformLayout.size > 0 ? vk::bindBuffer (context.getDeviceInterface(), context.getDevice(),m_context.getDefaultAllocator(), *m_uniformBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>())
1305 , m_rtFormat (getRenderTargetFormat(spec.outputFormat))
1306 , m_outputCount (((deUint32)m_spec.values.outputs.size() == 0 || m_spec.outputType == glu::sl::OUTPUT_RESULT) ? 1 : (deUint32)m_spec.values.outputs.size())
1311 , m_readImageBuffer ()
1314 , m_renderPass (createRenderPass(context, m_rtFormat, m_outputCount))
1316 , m_program (context, spec)
1317 , m_descriptorSetLayout (createDescriptorSetLayout(context, m_program.getStages()))
1318 , m_pipelineLayout (createPipelineLayout(context, *m_descriptorSetLayout))
1319 , m_pipeline (createPipeline(context, spec.values.inputs, m_inputLayout, m_program, *m_renderPass, *m_pipelineLayout, tcu::UVec2(RENDER_WIDTH, RENDER_HEIGHT), m_outputCount))
1321 , m_descriptorPool (createDescriptorPool(context))
1322 , m_descriptorSet (allocateDescriptorSet(context, *m_descriptorPool, *m_descriptorSetLayout))
1324 , m_cmdPool (createCommandPool(context))
1325 , m_cmdBuffer (allocateCommandBuffer(context, *m_cmdPool))
1330 // Initialize the resources for each color attachment needed by the shader
1331 for (deUint32 outNdx = 0; outNdx < m_outputCount; outNdx++)
1333 m_rtImage[outNdx] = createImage2D(context, RENDER_WIDTH, RENDER_HEIGHT, m_rtFormat, vk::VK_IMAGE_TILING_OPTIMAL, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT| vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1334 m_rtMem[outNdx] = allocateAndBindMemory(context, *m_rtImage[outNdx], vk::MemoryRequirement::Any);
1335 m_rtView[outNdx] = createAttachmentView(context, *m_rtImage[outNdx], m_rtFormat);
1337 m_readImageBuffer[outNdx] = createBuffer(context, (vk::VkDeviceSize)(RENDER_WIDTH * RENDER_HEIGHT * tcu::getPixelSize(vk::mapVkFormat(m_rtFormat))), vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1338 m_readImageMem[outNdx] = vk::bindBuffer (context.getDeviceInterface(), context.getDevice(),m_context.getDefaultAllocator(), *m_readImageBuffer[outNdx], vk::MemoryRequirement::HostVisible);
1340 m_framebuffer = createFramebuffer(context, *m_renderPass, m_rtView, m_outputCount, RENDER_WIDTH, RENDER_HEIGHT);
1343 const vk::DeviceInterface& vkd = context.getDeviceInterface();
1344 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1347 const Vec2 s_positions[] =
1354 const deUint16 s_indices[] =
1360 DE_STATIC_ASSERT(sizeof(s_positions) == POSITIONS_SIZE);
1361 DE_STATIC_ASSERT(sizeof(s_indices) == INDICES_SIZE);
1363 deMemcpy((deUint8*)m_posNdxMem->getHostPtr() + POSITIONS_OFFSET, &s_positions[0], sizeof(s_positions));
1364 deMemcpy((deUint8*)m_posNdxMem->getHostPtr() + INDICES_OFFSET, &s_indices[0], sizeof(s_indices));
1366 flushAlloc(m_context.getDeviceInterface(), context.getDevice(), *m_posNdxMem);
1369 if (!m_spec.values.uniforms.empty())
1371 const vk::VkDescriptorBufferInfo bufInfo =
1374 (vk::VkDeviceSize)0, // offset
1375 (vk::VkDeviceSize)m_uniformLayout.size
1378 vk::DescriptorSetUpdateBuilder()
1379 .writeSingle(*m_descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(USER_UNIFORM_BINDING),
1380 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufInfo)
1381 .update(vkd, m_context.getDevice());
1384 if (!m_spec.values.outputs.empty())
1386 const vk::VkDescriptorBufferInfo bufInfo =
1389 (vk::VkDeviceSize)0, // offset
1390 (vk::VkDeviceSize)m_referenceLayout.size
1393 vk::DescriptorSetUpdateBuilder()
1394 .writeSingle(*m_descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(REFERENCE_UNIFORM_BINDING),
1395 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufInfo)
1396 .update(vkd, m_context.getDevice());
1399 // Record command buffer
1401 beginCommandBuffer(vkd, *m_cmdBuffer, 0u);
1404 const vk::VkMemoryBarrier vertFlushBarrier =
1406 vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER, // sType
1408 vk::VK_ACCESS_HOST_WRITE_BIT, // srcAccessMask
1409 vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT|vk::VK_ACCESS_UNIFORM_READ_BIT, // dstAccessMask
1411 vk::VkImageMemoryBarrier colorAttBarrier [4];
1412 for (deUint32 outNdx = 0; outNdx < m_outputCount; outNdx++)
1414 vk::VkImageMemoryBarrier barrier =
1416 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
1418 0u, // srcAccessMask
1419 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // dstAccessMask
1420 vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
1421 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
1422 queueFamilyIndex, // srcQueueFamilyIndex
1423 queueFamilyIndex, // destQueueFamilyIndex
1424 *m_rtImage[outNdx], // image
1426 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
1429 0u, // baseArraySlice
1431 } // subresourceRange
1433 colorAttBarrier[outNdx] = barrier;
1435 vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (vk::VkDependencyFlags)0,
1436 1, &vertFlushBarrier,
1437 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1438 m_outputCount, &colorAttBarrier[0]);
1442 vk::VkClearValue clearValue[4];
1443 for (deUint32 outNdx = 0; outNdx < m_outputCount; outNdx++)
1445 vk::VkClearValue value = vk::makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
1446 clearValue[outNdx] = value;
1448 beginRenderPass(vkd, *m_cmdBuffer, *m_renderPass, *m_framebuffer, vk::makeRect2D(0, 0, RENDER_WIDTH, RENDER_HEIGHT), m_outputCount, clearValue);
1451 vkd.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1453 if (!m_spec.values.uniforms.empty() || !m_spec.values.outputs.empty())
1454 vkd.cmdBindDescriptorSets(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, DE_NULL);
1457 const vk::VkBuffer buffers[] = { *m_posNdxBuffer, *m_inputBuffer };
1458 const vk::VkDeviceSize offsets[] = { POSITIONS_OFFSET, 0u };
1459 const deUint32 numBuffers = buffers[1] != 0 ? 2u : 1u;
1460 vkd.cmdBindVertexBuffers(*m_cmdBuffer, 0u, numBuffers, buffers, offsets);
1463 vkd.cmdBindIndexBuffer (*m_cmdBuffer, *m_posNdxBuffer, (vk::VkDeviceSize)INDICES_OFFSET, vk::VK_INDEX_TYPE_UINT16);
1464 vkd.cmdDrawIndexed (*m_cmdBuffer, 6u, 1u, 0u, 0u, 0u);
1465 endRenderPass (vkd, *m_cmdBuffer);
1468 vk::VkImageMemoryBarrier renderFinishBarrier[4];
1469 for (deUint32 outNdx = 0; outNdx < m_outputCount; outNdx++)
1471 vk::VkImageMemoryBarrier barrier =
1473 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
1475 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask
1476 vk::VK_ACCESS_TRANSFER_READ_BIT, // dstAccessMask
1477 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // oldLayout
1478 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout
1479 queueFamilyIndex, // srcQueueFamilyIndex
1480 queueFamilyIndex, // destQueueFamilyIndex
1481 *m_rtImage[outNdx], // image
1483 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
1486 0u, // baseArraySlice
1488 } // subresourceRange
1490 renderFinishBarrier[outNdx] = barrier;
1493 vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0,
1494 0, (const vk::VkMemoryBarrier*)DE_NULL,
1495 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1496 m_outputCount, &renderFinishBarrier[0]);
1500 for (deUint32 outNdx = 0; outNdx < m_outputCount; outNdx++)
1502 const vk::VkBufferImageCopy copyParams =
1504 (vk::VkDeviceSize)0u, // bufferOffset
1505 (deUint32)RENDER_WIDTH, // bufferRowLength
1506 (deUint32)RENDER_HEIGHT, // bufferImageHeight
1508 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspect
1512 }, // imageSubresource
1513 { 0u, 0u, 0u }, // imageOffset
1514 { RENDER_WIDTH, RENDER_HEIGHT, 1u } // imageExtent
1517 vkd.cmdCopyImageToBuffer(*m_cmdBuffer, *m_rtImage[outNdx], vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_readImageBuffer[outNdx], 1u, ©Params);
1522 const vk::VkDeviceSize size = (vk::VkDeviceSize)(RENDER_WIDTH * RENDER_HEIGHT * tcu::getPixelSize(vk::mapVkFormat(m_rtFormat)));
1523 vk::VkBufferMemoryBarrier copyFinishBarrier[4];
1524 for (deUint32 outNdx = 0; outNdx < m_outputCount; outNdx++)
1526 vk::VkBufferMemoryBarrier barrier =
1528 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
1530 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask
1531 vk::VK_ACCESS_HOST_READ_BIT, // dstAccessMask
1532 queueFamilyIndex, // srcQueueFamilyIndex
1533 queueFamilyIndex, // destQueueFamilyIndex
1534 *m_readImageBuffer[outNdx], // buffer
1538 copyFinishBarrier[outNdx] = barrier;
1540 vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0,
1541 0, (const vk::VkMemoryBarrier*)DE_NULL,
1542 m_outputCount, ©FinishBarrier[0],
1543 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
1546 endCommandBuffer(vkd, *m_cmdBuffer);
1549 ShaderCaseInstance::~ShaderCaseInstance (void)
1553 int getNumSubCases (const ValueBlock& values)
1555 if (!values.outputs.empty())
1556 return int(values.outputs[0].elements.size() / values.outputs[0].type.getScalarSize());
1558 return 1; // Always run at least one iteration even if no output values are specified
1561 bool checkResultImage (const ConstPixelBufferAccess& result)
1563 const tcu::IVec4 refPix (255, 255, 255, 255);
1565 for (int y = 0; y < result.getHeight(); y++)
1567 for (int x = 0; x < result.getWidth(); x++)
1569 const tcu::IVec4 resPix = result.getPixelInt(x, y);
1571 if (boolAny(notEqual(resPix, refPix)))
1579 bool checkResultImageWithReference (const ConstPixelBufferAccess& result, tcu::IVec4 refPix)
1581 for (int y = 0; y < result.getHeight(); y++)
1583 for (int x = 0; x < result.getWidth(); x++)
1585 const tcu::IVec4 resPix = result.getPixelInt(x, y);
1587 if (boolAny(notEqual(resPix, refPix)))
1594 TestStatus ShaderCaseInstance::iterate (void)
1596 const vk::DeviceInterface& vkd = m_context.getDeviceInterface();
1597 const vk::VkDevice device = m_context.getDevice();
1598 const vk::VkQueue queue = m_context.getUniversalQueue();
1600 if (!m_spec.values.inputs.empty())
1601 writeValuesToMem(m_context, *m_inputMem, m_inputLayout, m_spec.values.inputs, m_subCaseNdx);
1603 if (!m_spec.values.outputs.empty())
1604 writeValuesToMem(m_context, *m_referenceMem, m_referenceLayout, m_spec.values.outputs, m_subCaseNdx);
1606 if (!m_spec.values.uniforms.empty())
1607 writeValuesToMem(m_context, *m_uniformMem, m_uniformLayout, m_spec.values.uniforms, m_subCaseNdx);
1609 submitCommandsAndWait(vkd, device, queue, m_cmdBuffer.get());
1611 // Result was checked in fragment shader
1612 if (m_spec.outputType == glu::sl::OUTPUT_RESULT)
1614 const ConstPixelBufferAccess imgAccess (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), RENDER_WIDTH, RENDER_HEIGHT, 1, m_readImageMem[0]->getHostPtr());
1616 invalidateAlloc(vkd, device, *m_readImageMem[0]);
1618 if (!checkResultImage(imgAccess))
1620 TestLog& log = m_context.getTestContext().getLog();
1622 log << TestLog::Message << "ERROR: Got non-white pixels on sub-case " << m_subCaseNdx << TestLog::EndMessage
1623 << TestLog::Image("Result", "Result", imgAccess);
1625 dumpValues(log, m_spec.values, m_subCaseNdx);
1627 return TestStatus::fail(string("Got invalid pixels at sub-case ") + de::toString(m_subCaseNdx));
1630 // Result was written to color buffer
1633 for (deUint32 outNdx = 0; outNdx < m_outputCount; outNdx++)
1635 const ConstPixelBufferAccess imgAccess (vk::mapVkFormat(m_rtFormat), RENDER_WIDTH, RENDER_HEIGHT, 1, m_readImageMem[outNdx]->getHostPtr());
1636 const DataType dataType = m_spec.values.outputs[outNdx].type.getBasicType();
1637 const int numComponents = getDataTypeScalarSize(dataType);
1638 tcu::IVec4 reference (0, 0, 0, 1);
1640 for (int refNdx = 0; refNdx < numComponents; refNdx++)
1642 if (isDataTypeFloatOrVec(dataType))
1643 reference[refNdx] = (int)m_spec.values.outputs[outNdx].elements[m_subCaseNdx * numComponents + refNdx].float32;
1644 else if (isDataTypeIntOrIVec(dataType))
1645 reference[refNdx] = m_spec.values.outputs[outNdx].elements[m_subCaseNdx * numComponents + refNdx].int32;
1647 DE_FATAL("Unknown data type");
1650 invalidateAlloc(vkd, device, *m_readImageMem[outNdx]);
1652 if (!checkResultImageWithReference(imgAccess, reference))
1654 TestLog& log = m_context.getTestContext().getLog();
1656 log << TestLog::Message << "ERROR: Got nonmatching pixels on sub-case " << m_subCaseNdx << " output " << outNdx << TestLog::EndMessage
1657 << TestLog::Image("Result", "Result", imgAccess);
1659 dumpValues(log, m_spec.values, m_subCaseNdx);
1661 return TestStatus::fail(string("Got invalid pixels at sub-case ") + de::toString(m_subCaseNdx));
1666 if (++m_subCaseNdx < getNumSubCases(m_spec.values))
1667 return TestStatus::incomplete();
1669 return TestStatus::pass("All sub-cases passed");
1672 class ShaderCase : public TestCase
1675 ShaderCase (tcu::TestContext& testCtx, const string& name, const string& description, const ShaderCaseSpecification& spec);
1678 void initPrograms (SourceCollections& programCollection) const;
1679 TestInstance* createInstance (Context& context) const;
1682 const ShaderCaseSpecification m_spec;
1685 ShaderCase::ShaderCase (tcu::TestContext& testCtx, const string& name, const string& description, const ShaderCaseSpecification& spec)
1686 : TestCase (testCtx, name, description)
1691 void ShaderCase::initPrograms (SourceCollections& sourceCollection) const
1693 vector<ProgramSources> specializedSources (m_spec.programs.size());
1695 DE_ASSERT(isValid(m_spec));
1697 if (m_spec.expectResult != glu::sl::EXPECT_PASS)
1698 TCU_THROW(InternalError, "Only EXPECT_PASS is supported");
1700 if (m_spec.caseType == glu::sl::CASETYPE_VERTEX_ONLY)
1702 DE_ASSERT(m_spec.programs.size() == 1 && m_spec.programs[0].sources.sources[glu::SHADERTYPE_VERTEX].size() == 1);
1703 specializedSources[0] << glu::VertexSource(specializeVertexShader(m_spec, m_spec.programs[0].sources.sources[glu::SHADERTYPE_VERTEX][0]))
1704 << glu::FragmentSource(genFragmentShader(m_spec));
1706 else if (m_spec.caseType == glu::sl::CASETYPE_FRAGMENT_ONLY)
1708 DE_ASSERT(m_spec.programs.size() == 1 && m_spec.programs[0].sources.sources[glu::SHADERTYPE_FRAGMENT].size() == 1);
1709 specializedSources[0] << glu::VertexSource(genVertexShader(m_spec))
1710 << glu::FragmentSource(specializeFragmentShader(m_spec, m_spec.programs[0].sources.sources[glu::SHADERTYPE_FRAGMENT][0]));
1714 DE_ASSERT(m_spec.caseType == glu::sl::CASETYPE_COMPLETE);
1716 const int maxPatchVertices = 4; // \todo [2015-08-05 pyry] Query
1718 for (size_t progNdx = 0; progNdx < m_spec.programs.size(); progNdx++)
1720 const ProgramSpecializationParams progSpecParams (m_spec, m_spec.programs[progNdx].requiredExtensions, maxPatchVertices);
1722 specializeProgramSources(specializedSources[progNdx], m_spec.programs[progNdx].sources, progSpecParams);
1726 for (size_t progNdx = 0; progNdx < specializedSources.size(); progNdx++)
1728 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
1730 if (!specializedSources[progNdx].sources[shaderType].empty())
1732 vk::GlslSource& curSrc = sourceCollection.glslSources.add(getShaderName((glu::ShaderType)shaderType, progNdx));
1733 curSrc.sources[shaderType] = specializedSources[progNdx].sources[shaderType];
1739 TestInstance* ShaderCase::createInstance (Context& context) const
1741 return new ShaderCaseInstance(context, m_spec);
1744 class ShaderCaseFactory : public glu::sl::ShaderCaseFactory
1747 ShaderCaseFactory (tcu::TestContext& testCtx)
1748 : m_testCtx(testCtx)
1752 tcu::TestCaseGroup* createGroup (const string& name, const string& description, const vector<tcu::TestNode*>& children)
1754 return new tcu::TestCaseGroup(m_testCtx, name.c_str(), description.c_str(), children);
1757 tcu::TestCase* createCase (const string& name, const string& description, const ShaderCaseSpecification& spec)
1759 return new ShaderCase(m_testCtx, name, description, spec);
1763 tcu::TestContext& m_testCtx;
1766 class ShaderLibraryGroup : public tcu::TestCaseGroup
1769 ShaderLibraryGroup (tcu::TestContext& testCtx, const string& name, const string& description, const string& filename)
1770 : tcu::TestCaseGroup (testCtx, name.c_str(), description.c_str())
1771 , m_filename (filename)
1777 ShaderCaseFactory caseFactory (m_testCtx);
1778 const vector<tcu::TestNode*> children = glu::sl::parseFile(m_testCtx.getArchive(), m_filename, &caseFactory);
1780 for (size_t ndx = 0; ndx < children.size(); ndx++)
1784 addChild(children[ndx]);
1788 for (; ndx < children.size(); ndx++)
1789 delete children[ndx];
1796 const string m_filename;
1801 MovePtr<tcu::TestCaseGroup> createShaderLibraryGroup (tcu::TestContext& testCtx, const string& name, const string& description, const string& filename)
1803 return MovePtr<tcu::TestCaseGroup>(new ShaderLibraryGroup(testCtx, name, description, filename));