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"
35 #include "gluShaderLibrary.hpp"
36 #include "gluShaderUtil.hpp"
38 #include "tcuStringTemplate.hpp"
39 #include "tcuTexture.hpp"
40 #include "tcuTestLog.hpp"
41 #include "tcuVector.hpp"
42 #include "tcuVectorUtil.hpp"
44 #include "deStringUtil.hpp"
45 #include "deArrayUtil.hpp"
58 using std::ostringstream;
63 using glu::ShaderType;
64 using glu::ProgramSources;
67 using glu::sl::ShaderCaseSpecification;
68 using glu::sl::ProgramSpecializationParams;
69 using glu::sl::RequiredExtension;
71 using glu::sl::ValueBlock;
73 using tcu::TestStatus;
74 using tcu::StringTemplate;
76 using tcu::ConstPixelBufferAccess;
77 using tcu::TextureFormat;
80 using vk::SourceCollections;
89 REFERENCE_UNIFORM_BINDING = 0,
90 USER_UNIFORM_BINDING = 1
93 string getShaderName (ShaderType shaderType, size_t progNdx)
96 str << glu::getShaderTypeName(shaderType);
98 str << "_" << progNdx;
102 void genUniformBlock (ostringstream& out, const string& blockName, const string& instanceName, int setNdx, int bindingNdx, const vector<Value>& uniforms)
107 out << "set = " << setNdx << ", ";
109 out << "binding = " << bindingNdx << ", std140) uniform " << blockName << "\n"
112 for (vector<Value>::const_iterator val = uniforms.begin(); val != uniforms.end(); ++val)
113 out << "\t" << glu::declare(val->type, val->name, 1) << ";\n";
117 if (!instanceName.empty())
118 out << " " << instanceName;
123 void declareReferenceBlock (ostringstream& out, const ValueBlock& valueBlock)
125 if (!valueBlock.outputs.empty())
126 genUniformBlock(out, "Reference", "ref", 0, REFERENCE_UNIFORM_BINDING, valueBlock.outputs);
129 void declareUniforms (ostringstream& out, const ValueBlock& valueBlock)
131 if (!valueBlock.uniforms.empty())
132 genUniformBlock(out, "Uniforms", "", 0, USER_UNIFORM_BINDING, valueBlock.uniforms);
135 DataType getTransportType (DataType valueType)
137 if (isDataTypeBoolOrBVec(valueType))
138 return glu::getDataTypeUintVec(getDataTypeScalarSize(valueType));
143 int getNumTransportLocations (DataType valueType)
145 return isDataTypeMatrix(valueType) ? getDataTypeMatrixNumColumns(valueType) : 1;
148 // This functions builds a matching vertex shader for a 'both' case, when
149 // the fragment shader is being tested.
150 // We need to build attributes and varyings for each 'input'.
151 string genVertexShader (const ShaderCaseSpecification& spec)
155 int curOutputLoc = 0;
157 res << glu::getGLSLVersionDeclaration(spec.targetVersion) << "\n";
159 // Declarations (position + attribute/varying for each input).
160 res << "precision highp float;\n";
161 res << "precision highp int;\n";
163 res << "layout(location = 0) in highp vec4 dEQP_Position;\n";
166 for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
168 const Value& val = spec.values.inputs[ndx];
169 const DataType valueType = val.type.getBasicType();
170 const DataType transportType = getTransportType(valueType);
171 const char* const transportTypeStr = getDataTypeName(transportType);
172 const int numLocs = getNumTransportLocations(valueType);
174 res << "layout(location = " << curInputLoc << ") in " << transportTypeStr << " a_" << val.name << ";\n";
175 res << "layout(location = " << curOutputLoc << ") flat out " << transportTypeStr << " " << (transportType != valueType ? "v_" : "") << val.name << ";\n";
177 curInputLoc += numLocs;
178 curOutputLoc += numLocs;
183 // - gl_Position = dEQP_Position;
184 // - for each input: write attribute directly to varying
185 res << "void main()\n";
187 res << " gl_Position = dEQP_Position;\n";
188 for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
190 const Value& val = spec.values.inputs[ndx];
191 const string& name = val.name;
193 res << " " << (getTransportType(val.type.getBasicType()) != val.type.getBasicType() ? "v_" : "")
194 << name << " = a_" << name << ";\n";
201 void genCompareOp (ostringstream& output, const char* dstVec4Var, const ValueBlock& valueBlock, const char* checkVarName)
203 bool isFirstOutput = true;
205 for (size_t ndx = 0; ndx < valueBlock.outputs.size(); ndx++)
207 const Value& val = valueBlock.outputs[ndx];
209 // Check if we're only interested in one variable (then skip if not the right one).
210 if (checkVarName && val.name != checkVarName)
216 output << "bool RES = ";
217 isFirstOutput = false;
220 output << "RES = RES && ";
222 // Generate actual comparison.
223 if (getDataTypeScalarType(val.type.getBasicType()) == glu::TYPE_FLOAT)
224 output << "isOk(" << val.name << ", ref." << val.name << ", 0.05);\n";
226 output << "isOk(" << val.name << ", ref." << val.name << ");\n";
230 output << dstVec4Var << " = vec4(1.0);\n";
232 output << dstVec4Var << " = vec4(RES, RES, RES, 1.0);\n";
235 string genFragmentShader (const ShaderCaseSpecification& spec)
237 ostringstream shader;
241 shader << glu::getGLSLVersionDeclaration(spec.targetVersion) << "\n";
243 shader << "precision highp float;\n";
244 shader << "precision highp int;\n";
247 shader << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
250 genCompareFunctions(shader, spec.values, false);
253 // Declarations (varying, reference for each output).
254 for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++)
256 const Value& val = spec.values.outputs[ndx];
257 const DataType valueType = val.type.getBasicType();
258 const char* const valueTypeStr = getDataTypeName(valueType);
259 const DataType transportType = getTransportType(valueType);
260 const char* const transportTypeStr = getDataTypeName(transportType);
261 const int numLocs = getNumTransportLocations(valueType);
263 shader << "layout(location = " << curInLoc << ") flat in " << transportTypeStr << " " << (valueType != transportType ? "v_" : "") << val.name << ";\n";
265 if (valueType != transportType)
266 setup << " " << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(v_" << val.name << ");\n";
271 declareReferenceBlock(shader, spec.values);
274 shader << "void main()\n";
277 shader << setup.str();
280 genCompareOp(shader, "dEQP_FragColor", spec.values, DE_NULL);
286 // Specialize a shader for the vertex shader test case.
287 string specializeVertexShader (const ShaderCaseSpecification& spec, const string& src)
291 ostringstream output;
293 int curOutputLoc = 0;
295 // generated from "both" case
296 DE_ASSERT(spec.caseType == glu::sl::CASETYPE_VERTEX_ONLY);
298 // Output (write out position).
299 output << "gl_Position = dEQP_Position;\n";
301 // Declarations (position + attribute for each input, varying for each output).
302 decl << "layout(location = 0) in highp vec4 dEQP_Position;\n";
305 for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
307 const Value& val = spec.values.inputs[ndx];
308 const DataType valueType = val.type.getBasicType();
309 const char* const valueTypeStr = getDataTypeName(valueType);
310 const DataType transportType = getTransportType(valueType);
311 const char* const transportTypeStr = getDataTypeName(transportType);
312 const int numLocs = getNumTransportLocations(valueType);
314 decl << "layout(location = " << curInputLoc << ") in ";
316 curInputLoc += numLocs;
318 if (valueType == transportType)
319 decl << transportTypeStr << " " << val.name << ";\n";
322 decl << transportTypeStr << " a_" << val.name << ";\n";
323 setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(a_" << val.name << ");\n";
327 declareUniforms(decl, spec.values);
329 for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++)
331 const Value& val = spec.values.outputs[ndx];
332 const DataType valueType = val.type.getBasicType();
333 const char* const valueTypeStr = getDataTypeName(valueType);
334 const DataType transportType = getTransportType(valueType);
335 const char* const transportTypeStr = getDataTypeName(transportType);
336 const int numLocs = getNumTransportLocations(valueType);
338 decl << "layout(location = " << curOutputLoc << ") flat out ";
340 curOutputLoc += numLocs;
342 if (valueType == transportType)
343 decl << transportTypeStr << " " << val.name << ";\n";
346 decl << transportTypeStr << " v_" << val.name << ";\n";
347 decl << valueTypeStr << " " << val.name << ";\n";
349 output << "v_" << val.name << " = " << transportTypeStr << "(" << val.name << ");\n";
353 // Shader specialization.
354 map<string, string> params;
355 params.insert(pair<string, string>("DECLARATIONS", decl.str()));
356 params.insert(pair<string, string>("SETUP", setup.str()));
357 params.insert(pair<string, string>("OUTPUT", output.str()));
358 params.insert(pair<string, string>("POSITION_FRAG_COLOR", "gl_Position"));
360 StringTemplate tmpl (src);
361 const string baseSrc = tmpl.specialize(params);
362 const string withExt = injectExtensionRequirements(baseSrc, spec.programs[0].requiredExtensions, glu::SHADERTYPE_VERTEX);
367 // Specialize a shader for the fragment shader test case.
368 string specializeFragmentShader (const ShaderCaseSpecification& spec, const string& src)
372 ostringstream output;
375 // generated from "both" case
376 DE_ASSERT(spec.caseType == glu::sl::CASETYPE_FRAGMENT_ONLY);
378 genCompareFunctions(decl, spec.values, false);
379 genCompareOp(output, "dEQP_FragColor", spec.values, DE_NULL);
381 decl << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
383 for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
385 const Value& val = spec.values.inputs[ndx];
386 const DataType valueType = val.type.getBasicType();
387 const char* const valueTypeStr = getDataTypeName(valueType);
388 const DataType transportType = getTransportType(valueType);
389 const char* const transportTypeStr = getDataTypeName(transportType);
390 const int numLocs = getNumTransportLocations(valueType);
392 decl << "layout(location = " << curInputLoc << ") flat in ";
394 curInputLoc += numLocs;
396 if (valueType == transportType)
397 decl << transportTypeStr << " " << val.name << ";\n";
400 decl << transportTypeStr << " v_" << val.name << ";\n";
401 setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(v_" << val.name << ");\n";
405 declareUniforms(decl, spec.values);
406 declareReferenceBlock(decl, spec.values);
408 for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++)
410 const Value& val = spec.values.outputs[ndx];
411 const DataType basicType = val.type.getBasicType();
412 const char* const refTypeStr = getDataTypeName(basicType);
414 decl << refTypeStr << " " << val.name << ";\n";
417 // Shader specialization.
418 map<string, string> params;
419 params.insert(pair<string, string>("DECLARATIONS", decl.str()));
420 params.insert(pair<string, string>("SETUP", setup.str()));
421 params.insert(pair<string, string>("OUTPUT", output.str()));
422 params.insert(pair<string, string>("POSITION_FRAG_COLOR", "dEQP_FragColor"));
424 StringTemplate tmpl (src);
425 const string baseSrc = tmpl.specialize(params);
426 const string withExt = injectExtensionRequirements(baseSrc, spec.programs[0].requiredExtensions, glu::SHADERTYPE_FRAGMENT);
431 map<string, string> generateVertexSpecialization (const ProgramSpecializationParams& specParams)
435 map<string, string> params;
438 decl << "layout(location = 0) in highp vec4 dEQP_Position;\n";
441 for (size_t ndx = 0; ndx < specParams.caseSpec.values.inputs.size(); ndx++)
443 const Value& val = specParams.caseSpec.values.inputs[ndx];
444 const DataType valueType = val.type.getBasicType();
445 const char* const valueTypeStr = getDataTypeName(valueType);
446 const DataType transportType = getTransportType(valueType);
447 const char* const transportTypeStr = getDataTypeName(transportType);
448 const int numLocs = getNumTransportLocations(valueType);
450 decl << "layout(location = " << curInputLoc << ") in ";
452 curInputLoc += numLocs;
454 if (valueType == transportType)
455 decl << transportTypeStr << " " << val.name << ";\n";
458 decl << transportTypeStr << " a_" << val.name << ";\n";
459 setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(a_" << val.name << ");\n";
463 declareUniforms(decl, specParams.caseSpec.values);
465 params.insert(pair<string, string>("VERTEX_DECLARATIONS", decl.str()));
466 params.insert(pair<string, string>("VERTEX_SETUP", setup.str()));
467 params.insert(pair<string, string>("VERTEX_OUTPUT", string("gl_Position = dEQP_Position;\n")));
472 map<string, string> generateFragmentSpecialization (const ProgramSpecializationParams& specParams)
475 ostringstream output;
476 map<string, string> params;
478 genCompareFunctions(decl, specParams.caseSpec.values, false);
479 genCompareOp(output, "dEQP_FragColor", specParams.caseSpec.values, DE_NULL);
481 decl << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
483 for (size_t ndx = 0; ndx < specParams.caseSpec.values.outputs.size(); ndx++)
485 const Value& val = specParams.caseSpec.values.outputs[ndx];
486 const char* const refTypeStr = getDataTypeName(val.type.getBasicType());
488 decl << refTypeStr << " " << val.name << ";\n";
491 declareReferenceBlock(decl, specParams.caseSpec.values);
492 declareUniforms(decl, specParams.caseSpec.values);
494 params.insert(pair<string, string>("FRAGMENT_DECLARATIONS", decl.str()));
495 params.insert(pair<string, string>("FRAGMENT_OUTPUT", output.str()));
496 params.insert(pair<string, string>("FRAG_COLOR", "dEQP_FragColor"));
501 map<string, string> generateGeometrySpecialization (const ProgramSpecializationParams& specParams)
504 map<string, string> params;
506 decl << "layout (triangles) in;\n";
507 decl << "layout (triangle_strip, max_vertices=3) out;\n";
510 declareUniforms(decl, specParams.caseSpec.values);
512 params.insert(pair<string, string>("GEOMETRY_DECLARATIONS", decl.str()));
517 map<string, string> generateTessControlSpecialization (const ProgramSpecializationParams& specParams)
520 ostringstream output;
521 map<string, string> params;
523 decl << "layout (vertices=3) out;\n";
526 declareUniforms(decl, specParams.caseSpec.values);
528 output << "gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
529 "gl_TessLevelInner[0] = 2.0;\n"
530 "gl_TessLevelInner[1] = 2.0;\n"
531 "gl_TessLevelOuter[0] = 2.0;\n"
532 "gl_TessLevelOuter[1] = 2.0;\n"
533 "gl_TessLevelOuter[2] = 2.0;\n"
534 "gl_TessLevelOuter[3] = 2.0;";
536 params.insert(pair<string, string>("TESSELLATION_CONTROL_DECLARATIONS", decl.str()));
537 params.insert(pair<string, string>("TESSELLATION_CONTROL_OUTPUT", output.str()));
538 params.insert(pair<string, string>("GL_MAX_PATCH_VERTICES", de::toString(specParams.maxPatchVertices)));
543 map<string, string> generateTessEvalSpecialization (const ProgramSpecializationParams& specParams)
546 ostringstream output;
547 map<string, string> params;
549 decl << "layout (triangles) in;\n";
552 declareUniforms(decl, specParams.caseSpec.values);
554 output << "gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position + gl_TessCoord[1] * gl_in[1].gl_Position + gl_TessCoord[2] * gl_in[2].gl_Position;\n";
556 params.insert(pair<string, string>("TESSELLATION_EVALUATION_DECLARATIONS", decl.str()));
557 params.insert(pair<string, string>("TESSELLATION_EVALUATION_OUTPUT", output.str()));
558 params.insert(pair<string, string>("GL_MAX_PATCH_VERTICES", de::toString(specParams.maxPatchVertices)));
563 void specializeShaderSources (ProgramSources& dst,
564 const ProgramSources& src,
565 const ProgramSpecializationParams& specParams,
566 glu::ShaderType shaderType,
567 map<string, string> (*specializationGenerator) (const ProgramSpecializationParams& specParams))
569 if (!src.sources[shaderType].empty())
571 const map<string, string> tmplParams = specializationGenerator(specParams);
573 for (size_t ndx = 0; ndx < src.sources[shaderType].size(); ++ndx)
575 const StringTemplate tmpl (src.sources[shaderType][ndx]);
576 const string baseGLSLCode = tmpl.specialize(tmplParams);
577 const string sourceWithExts = injectExtensionRequirements(baseGLSLCode, specParams.requiredExtensions, shaderType);
579 dst << glu::ShaderSource(shaderType, sourceWithExts);
584 void specializeProgramSources (glu::ProgramSources& dst,
585 const glu::ProgramSources& src,
586 const ProgramSpecializationParams& specParams)
588 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_VERTEX, generateVertexSpecialization);
589 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_FRAGMENT, generateFragmentSpecialization);
590 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_GEOMETRY, generateGeometrySpecialization);
591 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_TESSELLATION_CONTROL, generateTessControlSpecialization);
592 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_TESSELLATION_EVALUATION, generateTessEvalSpecialization);
594 dst << glu::ProgramSeparable(src.separable);
597 struct ValueBufferLayout
602 int vecStride; //! Applies to matrices only
604 Entry (void) : offset(0), vecStride(0) {}
605 Entry (int offset_, int vecStride_) : offset(offset_), vecStride(vecStride_) {}
608 vector<Entry> entries;
611 ValueBufferLayout (void) : size(0) {}
614 ValueBufferLayout computeStd140Layout (const vector<Value>& values)
616 ValueBufferLayout layout;
618 layout.entries.resize(values.size());
620 for (size_t ndx = 0; ndx < values.size(); ++ndx)
622 const DataType basicType = values[ndx].type.getBasicType();
623 const bool isMatrix = isDataTypeMatrix(basicType);
624 const int numVecs = isMatrix ? getDataTypeMatrixNumColumns(basicType) : 1;
625 const DataType vecType = isMatrix ? glu::getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType)) : basicType;
626 const int vecSize = getDataTypeScalarSize(vecType);
627 const int alignment = ((isMatrix || vecSize == 3) ? 4 : vecSize)*int(sizeof(deUint32));
629 layout.size = deAlign32(layout.size, alignment);
630 layout.entries[ndx] = ValueBufferLayout::Entry(layout.size, alignment);
631 layout.size += alignment*(numVecs-1) + vecSize*int(sizeof(deUint32));
637 ValueBufferLayout computeStd430Layout (const vector<Value>& values)
639 ValueBufferLayout layout;
641 layout.entries.resize(values.size());
643 for (size_t ndx = 0; ndx < values.size(); ++ndx)
645 const DataType basicType = values[ndx].type.getBasicType();
646 const int numVecs = isDataTypeMatrix(basicType) ? getDataTypeMatrixNumColumns(basicType) : 1;
647 const DataType vecType = isDataTypeMatrix(basicType) ? glu::getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType)) : basicType;
648 const int vecSize = getDataTypeScalarSize(vecType);
649 const int alignment = (vecSize == 3 ? 4 : vecSize)*int(sizeof(deUint32));
651 layout.size = deAlign32(layout.size, alignment);
652 layout.entries[ndx] = ValueBufferLayout::Entry(layout.size, alignment);
653 layout.size += alignment*(numVecs-1) + vecSize*int(sizeof(deUint32));
659 void copyToLayout (void* dst, const ValueBufferLayout::Entry& entryLayout, const Value& value, int arrayNdx)
661 const DataType basicType = value.type.getBasicType();
662 const int scalarSize = getDataTypeScalarSize(basicType);
663 const int numVecs = isDataTypeMatrix(basicType) ? getDataTypeMatrixNumColumns(basicType) : 1;
664 const int numComps = isDataTypeMatrix(basicType) ? getDataTypeMatrixNumRows(basicType) : scalarSize;
666 DE_ASSERT(size_t((arrayNdx+1)*scalarSize) <= value.elements.size());
668 if (isDataTypeBoolOrBVec(basicType))
670 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
672 for (int compNdx = 0; compNdx < numComps; compNdx++)
674 const deUint32 data = value.elements[arrayNdx*scalarSize + vecNdx*numComps + compNdx].bool32 ? ~0u : 0u;
676 deMemcpy((deUint8*)dst + entryLayout.offset + vecNdx*entryLayout.vecStride + compNdx * sizeof(deUint32),
684 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
685 deMemcpy((deUint8*)dst + entryLayout.offset + vecNdx*entryLayout.vecStride,
686 &value.elements[arrayNdx*scalarSize + vecNdx*numComps],
687 numComps*sizeof(deUint32));
691 void copyToLayout (void* dst, const ValueBufferLayout& layout, const vector<Value>& values, int arrayNdx)
693 DE_ASSERT(layout.entries.size() == values.size());
695 for (size_t ndx = 0; ndx < values.size(); ndx++)
696 copyToLayout(dst, layout.entries[ndx], values[ndx], arrayNdx);
699 deUint32 getShaderStages (const ShaderCaseSpecification& spec)
701 if (spec.caseType == glu::sl::CASETYPE_COMPLETE)
703 deUint32 stages = 0u;
705 for (size_t progNdx = 0; progNdx < spec.programs.size(); progNdx++)
707 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
709 if (!spec.programs[progNdx].sources.sources[shaderType].empty())
710 stages |= (1u << shaderType);
717 return (1u << glu::SHADERTYPE_VERTEX) | (1u << glu::SHADERTYPE_FRAGMENT);
720 class PipelineProgram
723 PipelineProgram (Context& context, const ShaderCaseSpecification& spec);
725 deUint32 getStages (void) const { return m_stages; }
727 bool hasShader (glu::ShaderType type) const { return (m_stages & (1u << type)) != 0; }
728 vk::VkShaderModule getShader (glu::ShaderType type) const { return *m_shaderModules[type]; }
731 const deUint32 m_stages;
732 Move<vk::VkShaderModule> m_shaderModules[glu::SHADERTYPE_LAST];
735 PipelineProgram::PipelineProgram (Context& context, const ShaderCaseSpecification& spec)
736 : m_stages(getShaderStages(spec))
738 // \note Currently only a single source program is supported as framework lacks SPIR-V linking capability
739 TCU_CHECK_INTERNAL(spec.programs.size() == 1);
741 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
743 if ((m_stages & (1u << shaderType)) != 0)
745 m_shaderModules[shaderType] = vk::createShaderModule(context.getDeviceInterface(), context.getDevice(),
746 context.getBinaryCollection().get(getShaderName((glu::ShaderType)shaderType, 0)), 0u);
751 vector<vk::VkPipelineShaderStageCreateInfo> getPipelineShaderStageCreateInfo (const PipelineProgram& program)
753 vector<vk::VkPipelineShaderStageCreateInfo> infos;
755 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
757 if (program.hasShader((glu::ShaderType)shaderType))
759 const vk::VkPipelineShaderStageCreateInfo info =
761 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType
763 (vk::VkPipelineShaderStageCreateFlags)0,
764 vk::getVkShaderStage((glu::ShaderType)shaderType), // stage
765 program.getShader((glu::ShaderType)shaderType), // module
767 DE_NULL, // pSpecializationInfo
770 infos.push_back(info);
777 Move<vk::VkBuffer> createBuffer (Context& context, vk::VkDeviceSize size, vk::VkBufferUsageFlags usageFlags)
779 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
780 const vk::VkBufferCreateInfo params =
782 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
787 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
788 1u, // queueFamilyCount
789 &queueFamilyIndex, // pQueueFamilyIndices
792 return vk::createBuffer(context.getDeviceInterface(), context.getDevice(), ¶ms);
795 Move<vk::VkImage> createImage2D (Context& context, deUint32 width, deUint32 height, vk::VkFormat format, vk::VkImageTiling tiling, vk::VkImageUsageFlags usageFlags)
797 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
798 const vk::VkImageCreateInfo params =
800 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
803 vk::VK_IMAGE_TYPE_2D, // imageType
805 { width, height, 1u }, // extent
808 vk::VK_SAMPLE_COUNT_1_BIT, // samples
811 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
812 1u, // queueFamilyCount
813 &queueFamilyIndex, // pQueueFamilyIndices
814 vk::VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
817 return vk::createImage(context.getDeviceInterface(), context.getDevice(), ¶ms);
820 Move<vk::VkImageView> createAttachmentView (Context& context, vk::VkImage image, vk::VkFormat format)
822 const vk::VkImageViewCreateInfo params =
824 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType
828 vk::VK_IMAGE_VIEW_TYPE_2D, // viewType
830 vk::makeComponentMappingRGBA(), // channels
832 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
835 0u, // baseArrayLayer
837 }, // subresourceRange
840 return vk::createImageView(context.getDeviceInterface(), context.getDevice(), ¶ms);
843 Move<vk::VkRenderPass> createRenderPass (Context& context, vk::VkFormat colorAttFormat)
845 const vk::VkAttachmentDescription colorAttDesc =
848 colorAttFormat, // format
849 vk::VK_SAMPLE_COUNT_1_BIT, // samples
850 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // loadOp
851 vk::VK_ATTACHMENT_STORE_OP_STORE, // storeOp
852 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
853 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
854 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // initialLayout
855 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // finalLayout
857 const vk::VkAttachmentReference colorAttRef =
860 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // layout
862 const vk::VkAttachmentReference dsAttRef =
864 VK_ATTACHMENT_UNUSED, // attachment
865 vk::VK_IMAGE_LAYOUT_GENERAL, // layout
867 const vk::VkSubpassDescription subpassDesc =
869 (vk::VkSubpassDescriptionFlags)0,
870 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
872 DE_NULL, // pInputAttachments
874 &colorAttRef, // pColorAttachments
875 DE_NULL, // pResolveAttachments
876 &dsAttRef, // depthStencilAttachment
878 DE_NULL, // pPreserveAttachments
881 const vk::VkRenderPassCreateInfo renderPassParams =
883 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // sType
885 (vk::VkRenderPassCreateFlags)0,
886 1u, // attachmentCount
887 &colorAttDesc, // pAttachments
889 &subpassDesc, // pSubpasses
890 0u, // dependencyCount
891 DE_NULL, // pDependencies
894 return vk::createRenderPass(context.getDeviceInterface(), context.getDevice(), &renderPassParams);
897 vk::VkShaderStageFlags getVkStageFlags (deUint32 stages)
899 vk::VkShaderStageFlags vkStages = 0u;
901 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
903 if ((stages & (1u << shaderType)) != 0)
904 vkStages |= vk::getVkShaderStage((glu::ShaderType)shaderType);
910 Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (Context& context, deUint32 shaderStages)
912 DE_STATIC_ASSERT(REFERENCE_UNIFORM_BINDING == 0);
913 DE_STATIC_ASSERT(USER_UNIFORM_BINDING == 1);
915 return vk::DescriptorSetLayoutBuilder()
916 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT)
917 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, getVkStageFlags(shaderStages))
918 .build(context.getDeviceInterface(), context.getDevice());
921 Move<vk::VkPipelineLayout> createPipelineLayout (Context& context, vk::VkDescriptorSetLayout descriptorSetLayout)
923 const vk::VkPipelineLayoutCreateInfo params =
925 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
927 (vk::VkPipelineLayoutCreateFlags)0,
928 1u, // descriptorSetCount
929 &descriptorSetLayout, // pSetLayouts
930 0u, // pushConstantRangeCount
931 DE_NULL, // pPushConstantRanges
934 return vk::createPipelineLayout(context.getDeviceInterface(), context.getDevice(), ¶ms);
937 vk::VkFormat getVecFormat (DataType scalarType, int scalarSize)
941 case glu::TYPE_FLOAT:
943 const vk::VkFormat vecFmts[] =
945 vk::VK_FORMAT_R32_SFLOAT,
946 vk::VK_FORMAT_R32G32_SFLOAT,
947 vk::VK_FORMAT_R32G32B32_SFLOAT,
948 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
950 return de::getSizedArrayElement<4>(vecFmts, scalarSize-1);
955 const vk::VkFormat vecFmts[] =
957 vk::VK_FORMAT_R32_SINT,
958 vk::VK_FORMAT_R32G32_SINT,
959 vk::VK_FORMAT_R32G32B32_SINT,
960 vk::VK_FORMAT_R32G32B32A32_SINT,
962 return de::getSizedArrayElement<4>(vecFmts, scalarSize-1);
967 const vk::VkFormat vecFmts[] =
969 vk::VK_FORMAT_R32_UINT,
970 vk::VK_FORMAT_R32G32_UINT,
971 vk::VK_FORMAT_R32G32B32_UINT,
972 vk::VK_FORMAT_R32G32B32A32_UINT,
974 return de::getSizedArrayElement<4>(vecFmts, scalarSize-1);
979 const vk::VkFormat vecFmts[] =
981 vk::VK_FORMAT_R32_UINT,
982 vk::VK_FORMAT_R32G32_UINT,
983 vk::VK_FORMAT_R32G32B32_UINT,
984 vk::VK_FORMAT_R32G32B32A32_UINT,
986 return de::getSizedArrayElement<4>(vecFmts, scalarSize-1);
990 DE_FATAL("Unknown scalar type");
991 return vk::VK_FORMAT_R8G8B8A8_UINT;
995 vector<vk::VkVertexInputAttributeDescription> getVertexAttributeDescriptions (const vector<Value>& inputValues, const ValueBufferLayout& layout)
997 vector<vk::VkVertexInputAttributeDescription> attribs;
1001 const vk::VkVertexInputAttributeDescription posDesc =
1005 vk::VK_FORMAT_R32G32_SFLOAT, // format
1009 attribs.push_back(posDesc);
1013 for (size_t inputNdx = 0; inputNdx < inputValues.size(); inputNdx++)
1015 const Value& input = inputValues[inputNdx];
1016 const ValueBufferLayout::Entry& layoutEntry = layout.entries[inputNdx];
1017 const DataType basicType = input.type.getBasicType();
1018 const int numVecs = isDataTypeMatrix(basicType)
1019 ? getDataTypeMatrixNumColumns(basicType)
1021 const int vecSize = isDataTypeMatrix(basicType)
1022 ? getDataTypeMatrixNumRows(basicType)
1023 : getDataTypeScalarSize(basicType);
1024 const DataType scalarType = getDataTypeScalarType(basicType);
1025 const vk::VkFormat vecFmt = getVecFormat(scalarType, vecSize);
1027 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
1029 const deUint32 curLoc = (deUint32)attribs.size();
1030 const deUint32 offset = (deUint32)(layoutEntry.offset + layoutEntry.vecStride*vecNdx);
1031 const vk::VkVertexInputAttributeDescription desc =
1039 attribs.push_back(desc);
1046 Move<vk::VkPipeline> createPipeline (Context& context,
1047 const vector<Value>& inputValues,
1048 const ValueBufferLayout& inputLayout,
1049 const PipelineProgram& program,
1050 vk::VkRenderPass renderPass,
1051 vk::VkPipelineLayout pipelineLayout,
1052 tcu::UVec2 renderSize)
1054 const vector<vk::VkPipelineShaderStageCreateInfo> shaderStageParams (getPipelineShaderStageCreateInfo(program));
1055 const vector<vk::VkVertexInputAttributeDescription> vertexAttribParams (getVertexAttributeDescriptions(inputValues, inputLayout));
1056 const vk::VkPipelineDepthStencilStateCreateInfo depthStencilParams =
1058 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // sType
1060 (vk::VkPipelineDepthStencilStateCreateFlags)0,
1061 VK_FALSE, // depthTestEnable
1062 VK_FALSE, // depthWriteEnable
1063 vk::VK_COMPARE_OP_ALWAYS, // depthCompareOp
1064 VK_FALSE, // depthBoundsTestEnable
1065 VK_FALSE, // stencilTestEnable
1067 vk::VK_STENCIL_OP_KEEP, // stencilFailOp;
1068 vk::VK_STENCIL_OP_KEEP, // stencilPassOp;
1069 vk::VK_STENCIL_OP_KEEP, // stencilDepthFailOp;
1070 vk::VK_COMPARE_OP_ALWAYS, // stencilCompareOp;
1071 0u, // stencilCompareMask
1072 0u, // stencilWriteMask
1073 0u, // stencilReference
1076 vk::VK_STENCIL_OP_KEEP, // stencilFailOp;
1077 vk::VK_STENCIL_OP_KEEP, // stencilPassOp;
1078 vk::VK_STENCIL_OP_KEEP, // stencilDepthFailOp;
1079 vk::VK_COMPARE_OP_ALWAYS, // stencilCompareOp;
1080 0u, // stencilCompareMask
1081 0u, // stencilWriteMask
1082 0u, // stencilReference
1084 -1.0f, // minDepthBounds
1085 +1.0f, // maxDepthBounds
1087 const vk::VkViewport viewport0 =
1091 (float)renderSize.x(), // width
1092 (float)renderSize.y(), // height
1096 const vk::VkRect2D scissor0 =
1098 { 0u, 0u }, // offset
1099 { renderSize.x(), renderSize.y() } // extent
1101 const vk::VkPipelineViewportStateCreateInfo viewportParams =
1103 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // sType
1105 (vk::VkPipelineViewportStateCreateFlags)0,
1106 1u, // viewportCount
1107 &viewport0, // pViewports
1109 &scissor0, // pScissors
1111 const vk::VkPipelineMultisampleStateCreateInfo multisampleParams =
1113 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // sType
1115 (vk::VkPipelineMultisampleStateCreateFlags)0,
1116 vk::VK_SAMPLE_COUNT_1_BIT, // rasterSamples
1117 DE_FALSE, // sampleShadingEnable
1118 0.0f, // minSampleShading
1119 DE_NULL, // pSampleMask
1120 VK_FALSE, // alphaToCoverageEnable
1121 VK_FALSE, // alphaToOneEnable
1123 const vk::VkPipelineRasterizationStateCreateInfo rasterParams =
1125 vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // sType
1127 (vk::VkPipelineRasterizationStateCreateFlags)0,
1128 DE_TRUE, // depthClipEnable
1129 DE_FALSE, // rasterizerDiscardEnable
1130 vk::VK_POLYGON_MODE_FILL, // fillMode
1131 vk::VK_CULL_MODE_NONE, // cullMode;
1132 vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace;
1133 VK_FALSE, // depthBiasEnable
1134 0.0f, // depthBiasConstantFactor
1135 0.0f, // depthBiasClamp
1136 0.0f, // depthBiasSlopeFactor
1139 const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyParams =
1141 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // sType
1143 (vk::VkPipelineInputAssemblyStateCreateFlags)0,
1144 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // topology
1145 DE_FALSE, // primitiveRestartEnable
1147 const vk::VkVertexInputBindingDescription vertexBindings[] =
1151 (deUint32)sizeof(tcu::Vec2), // stride
1152 vk::VK_VERTEX_INPUT_RATE_VERTEX, // stepRate
1157 vk::VK_VERTEX_INPUT_RATE_INSTANCE, // stepRate
1160 const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
1162 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // sType
1164 (vk::VkPipelineVertexInputStateCreateFlags)0,
1165 (inputValues.empty() ? 1u : 2u), // bindingCount
1166 vertexBindings, // pVertexBindingDescriptions
1167 (deUint32)vertexAttribParams.size(), // attributeCount
1168 &vertexAttribParams[0], // pVertexAttributeDescriptions
1170 const vk::VkColorComponentFlags allCompMask = vk::VK_COLOR_COMPONENT_R_BIT
1171 | vk::VK_COLOR_COMPONENT_G_BIT
1172 | vk::VK_COLOR_COMPONENT_B_BIT
1173 | vk::VK_COLOR_COMPONENT_A_BIT;
1174 const vk::VkPipelineColorBlendAttachmentState attBlendParams =
1176 VK_FALSE, // blendEnable
1177 vk::VK_BLEND_FACTOR_ONE, // srcBlendColor
1178 vk::VK_BLEND_FACTOR_ZERO, // destBlendColor
1179 vk::VK_BLEND_OP_ADD, // blendOpColor
1180 vk::VK_BLEND_FACTOR_ONE, // srcBlendAlpha
1181 vk::VK_BLEND_FACTOR_ZERO, // destBlendAlpha
1182 vk::VK_BLEND_OP_ADD, // blendOpAlpha
1183 allCompMask, // componentWriteMask
1185 const vk::VkPipelineColorBlendStateCreateInfo blendParams =
1187 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // sType
1189 (vk::VkPipelineColorBlendStateCreateFlags)0,
1190 VK_FALSE, // logicOpEnable
1191 vk::VK_LOGIC_OP_COPY, // logicOp
1192 1u, // attachmentCount
1193 &attBlendParams, // pAttachments
1194 { 0.0f, 0.0f, 0.0f, 0.0f }, // blendConstants
1196 const vk::VkGraphicsPipelineCreateInfo pipelineParams =
1198 vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // sType
1201 (deUint32)shaderStageParams.size(), // stageCount
1202 &shaderStageParams[0], // pStages
1203 &vertexInputStateParams, // pVertexInputState
1204 &inputAssemblyParams, // pInputAssemblyState
1205 DE_NULL, // pTessellationState
1206 &viewportParams, // pViewportState
1207 &rasterParams, // pRasterState
1208 &multisampleParams, // pMultisampleState
1209 &depthStencilParams, // pDepthStencilState
1210 &blendParams, // pColorBlendState
1211 (const vk::VkPipelineDynamicStateCreateInfo*)DE_NULL, // pDynamicState
1212 pipelineLayout, // layout
1213 renderPass, // renderPass
1215 DE_NULL, // basePipelineHandle
1216 0u, // basePipelineIndex
1219 return vk::createGraphicsPipeline(context.getDeviceInterface(), context.getDevice(), DE_NULL, &pipelineParams);
1222 Move<vk::VkFramebuffer> createFramebuffer (Context& context, vk::VkRenderPass renderPass, vk::VkImageView colorAttView, int width, int height)
1224 const vk::VkFramebufferCreateInfo framebufferParams =
1226 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // sType
1228 (vk::VkFramebufferCreateFlags)0,
1229 renderPass, // renderPass
1230 1u, // attachmentCount
1231 &colorAttView, // pAttachments
1232 (deUint32)width, // width
1233 (deUint32)height, // height
1237 return vk::createFramebuffer(context.getDeviceInterface(), context.getDevice(), &framebufferParams);
1240 Move<vk::VkCommandPool> createCommandPool (Context& context)
1242 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1244 return vk::createCommandPool(context.getDeviceInterface(), context.getDevice(), (vk::VkCommandPoolCreateFlags)0u, queueFamilyIndex);
1247 Move<vk::VkDescriptorPool> createDescriptorPool (Context& context)
1249 return vk::DescriptorPoolBuilder()
1250 .addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u)
1251 .build(context.getDeviceInterface(), context.getDevice(), vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1254 Move<vk::VkDescriptorSet> allocateDescriptorSet (Context& context, vk::VkDescriptorPool descriptorPool, vk::VkDescriptorSetLayout setLayout)
1256 const vk::VkDescriptorSetAllocateInfo params =
1258 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1265 return vk::allocateDescriptorSet(context.getDeviceInterface(), context.getDevice(), ¶ms);
1268 Move<vk::VkCommandBuffer> allocateCommandBuffer (Context& context, vk::VkCommandPool cmdPool)
1270 return vk::allocateCommandBuffer(context.getDeviceInterface(), context.getDevice(), cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1273 MovePtr<vk::Allocation> allocateAndBindMemory (Context& context, vk::VkBuffer buffer, vk::MemoryRequirement memReqs)
1275 const vk::DeviceInterface& vkd = context.getDeviceInterface();
1276 const vk::VkMemoryRequirements bufReqs = vk::getBufferMemoryRequirements(vkd, context.getDevice(), buffer);
1277 MovePtr<vk::Allocation> memory = context.getDefaultAllocator().allocate(bufReqs, memReqs);
1279 vkd.bindBufferMemory(context.getDevice(), buffer, memory->getMemory(), memory->getOffset());
1284 MovePtr<vk::Allocation> allocateAndBindMemory (Context& context, vk::VkImage image, vk::MemoryRequirement memReqs)
1286 const vk::DeviceInterface& vkd = context.getDeviceInterface();
1287 const vk::VkMemoryRequirements imgReqs = vk::getImageMemoryRequirements(vkd, context.getDevice(), image);
1288 MovePtr<vk::Allocation> memory = context.getDefaultAllocator().allocate(imgReqs, memReqs);
1290 vkd.bindImageMemory(context.getDevice(), image, memory->getMemory(), memory->getOffset());
1295 void writeValuesToMem (Context& context, const vk::Allocation& dst, const ValueBufferLayout& layout, const vector<Value>& values, int arrayNdx)
1297 copyToLayout(dst.getHostPtr(), layout, values, arrayNdx);
1299 // \note Buffers are not allocated with coherency / uncached requirement so we need to manually flush CPU write caches
1300 flushMappedMemoryRange(context.getDeviceInterface(), context.getDevice(), dst.getMemory(), dst.getOffset(), (vk::VkDeviceSize)layout.size);
1303 class ShaderCaseInstance : public TestInstance
1306 ShaderCaseInstance (Context& context, const ShaderCaseSpecification& spec);
1307 ~ShaderCaseInstance (void);
1309 TestStatus iterate (void);
1317 POSITIONS_OFFSET = 0,
1318 POSITIONS_SIZE = (int)sizeof(Vec2)*4,
1320 INDICES_OFFSET = POSITIONS_SIZE,
1321 INDICES_SIZE = (int)sizeof(deUint16)*6,
1323 TOTAL_POS_NDX_SIZE = POSITIONS_SIZE+INDICES_SIZE
1326 const ShaderCaseSpecification& m_spec;
1328 const Unique<vk::VkBuffer> m_posNdxBuffer;
1329 const UniquePtr<vk::Allocation> m_posNdxMem;
1331 const ValueBufferLayout m_inputLayout;
1332 const Unique<vk::VkBuffer> m_inputBuffer; // Input values (attributes). Can be NULL if no inputs present
1333 const UniquePtr<vk::Allocation> m_inputMem; // Input memory, can be NULL if no input buffer exists
1335 const ValueBufferLayout m_referenceLayout;
1336 const Unique<vk::VkBuffer> m_referenceBuffer; // Output (reference) values. Can be NULL if no outputs present
1337 const UniquePtr<vk::Allocation> m_referenceMem; // Output (reference) memory, can be NULL if no reference buffer exists
1339 const ValueBufferLayout m_uniformLayout;
1340 const Unique<vk::VkBuffer> m_uniformBuffer; // Uniform values. Can be NULL if no uniforms present
1341 const UniquePtr<vk::Allocation> m_uniformMem; // Uniform memory, can be NULL if no uniform buffer exists
1343 const Unique<vk::VkBuffer> m_readImageBuffer;
1344 const UniquePtr<vk::Allocation> m_readImageMem;
1346 const Unique<vk::VkImage> m_rtImage;
1347 const UniquePtr<vk::Allocation> m_rtMem;
1348 const Unique<vk::VkImageView> m_rtView;
1350 const Unique<vk::VkRenderPass> m_renderPass;
1351 const Unique<vk::VkFramebuffer> m_framebuffer;
1352 const PipelineProgram m_program;
1353 const Unique<vk::VkDescriptorSetLayout> m_descriptorSetLayout;
1354 const Unique<vk::VkPipelineLayout> m_pipelineLayout;
1355 const Unique<vk::VkPipeline> m_pipeline;
1357 const Unique<vk::VkDescriptorPool> m_descriptorPool;
1358 const Unique<vk::VkDescriptorSet> m_descriptorSet;
1360 const Unique<vk::VkCommandPool> m_cmdPool;
1361 const Unique<vk::VkCommandBuffer> m_cmdBuffer;
1366 ShaderCaseInstance::ShaderCaseInstance (Context& context, const ShaderCaseSpecification& spec)
1367 : TestInstance (context)
1370 , m_posNdxBuffer (createBuffer(context, (vk::VkDeviceSize)TOTAL_POS_NDX_SIZE, vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT|vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))
1371 , m_posNdxMem (allocateAndBindMemory(context, *m_posNdxBuffer, vk::MemoryRequirement::HostVisible))
1373 , m_inputLayout (computeStd430Layout(spec.values.inputs))
1374 , m_inputBuffer (m_inputLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_inputLayout.size, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) : Move<vk::VkBuffer>())
1375 , m_inputMem (m_inputLayout.size > 0 ? allocateAndBindMemory(context, *m_inputBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>())
1377 , m_referenceLayout (computeStd140Layout(spec.values.outputs))
1378 , m_referenceBuffer (m_referenceLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_referenceLayout.size, vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : Move<vk::VkBuffer>())
1379 , m_referenceMem (m_referenceLayout.size > 0 ? allocateAndBindMemory(context, *m_referenceBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>())
1381 , m_uniformLayout (computeStd140Layout(spec.values.uniforms))
1382 , m_uniformBuffer (m_uniformLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_uniformLayout.size, vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : Move<vk::VkBuffer>())
1383 , m_uniformMem (m_uniformLayout.size > 0 ? allocateAndBindMemory(context, *m_uniformBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>())
1385 , m_readImageBuffer (createBuffer(context, (vk::VkDeviceSize)(RENDER_WIDTH*RENDER_HEIGHT*4), vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT))
1386 , m_readImageMem (allocateAndBindMemory(context, *m_readImageBuffer, vk::MemoryRequirement::HostVisible))
1388 , m_rtImage (createImage2D(context, RENDER_WIDTH, RENDER_HEIGHT, vk::VK_FORMAT_R8G8B8A8_UNORM, vk::VK_IMAGE_TILING_OPTIMAL, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT))
1389 , m_rtMem (allocateAndBindMemory(context, *m_rtImage, vk::MemoryRequirement::Any))
1390 , m_rtView (createAttachmentView(context, *m_rtImage, vk::VK_FORMAT_R8G8B8A8_UNORM))
1392 , m_renderPass (createRenderPass(context, vk::VK_FORMAT_R8G8B8A8_UNORM))
1393 , m_framebuffer (createFramebuffer(context, *m_renderPass, *m_rtView, RENDER_WIDTH, RENDER_HEIGHT))
1394 , m_program (context, spec)
1395 , m_descriptorSetLayout (createDescriptorSetLayout(context, m_program.getStages()))
1396 , m_pipelineLayout (createPipelineLayout(context, *m_descriptorSetLayout))
1397 , m_pipeline (createPipeline(context, spec.values.inputs, m_inputLayout, m_program, *m_renderPass, *m_pipelineLayout, tcu::UVec2(RENDER_WIDTH, RENDER_HEIGHT)))
1399 , m_descriptorPool (createDescriptorPool(context))
1400 , m_descriptorSet (allocateDescriptorSet(context, *m_descriptorPool, *m_descriptorSetLayout))
1402 , m_cmdPool (createCommandPool(context))
1403 , m_cmdBuffer (allocateCommandBuffer(context, *m_cmdPool))
1407 const vk::DeviceInterface& vkd = context.getDeviceInterface();
1408 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1411 const Vec2 s_positions[] =
1418 const deUint16 s_indices[] =
1424 DE_STATIC_ASSERT(sizeof(s_positions) == POSITIONS_SIZE);
1425 DE_STATIC_ASSERT(sizeof(s_indices) == INDICES_SIZE);
1427 deMemcpy((deUint8*)m_posNdxMem->getHostPtr() + POSITIONS_OFFSET, &s_positions[0], sizeof(s_positions));
1428 deMemcpy((deUint8*)m_posNdxMem->getHostPtr() + INDICES_OFFSET, &s_indices[0], sizeof(s_indices));
1430 flushMappedMemoryRange(m_context.getDeviceInterface(), context.getDevice(), m_posNdxMem->getMemory(), m_posNdxMem->getOffset(), sizeof(s_positions)+sizeof(s_indices));
1433 if (!m_spec.values.uniforms.empty())
1435 const vk::VkDescriptorBufferInfo bufInfo =
1438 (vk::VkDeviceSize)0, // offset
1439 (vk::VkDeviceSize)m_uniformLayout.size
1442 vk::DescriptorSetUpdateBuilder()
1443 .writeSingle(*m_descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(USER_UNIFORM_BINDING),
1444 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufInfo)
1445 .update(vkd, m_context.getDevice());
1448 if (!m_spec.values.outputs.empty())
1450 const vk::VkDescriptorBufferInfo bufInfo =
1453 (vk::VkDeviceSize)0, // offset
1454 (vk::VkDeviceSize)m_referenceLayout.size
1457 vk::DescriptorSetUpdateBuilder()
1458 .writeSingle(*m_descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(REFERENCE_UNIFORM_BINDING),
1459 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufInfo)
1460 .update(vkd, m_context.getDevice());
1463 // Record command buffer
1466 const vk::VkCommandBufferBeginInfo beginInfo =
1468 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
1471 (const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
1474 VK_CHECK(vkd.beginCommandBuffer(*m_cmdBuffer, &beginInfo));
1478 const vk::VkMemoryBarrier vertFlushBarrier =
1480 vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER, // sType
1482 vk::VK_ACCESS_HOST_WRITE_BIT, // srcAccessMask
1483 vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT|vk::VK_ACCESS_UNIFORM_READ_BIT, // dstAccessMask
1485 const vk::VkImageMemoryBarrier colorAttBarrier =
1487 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
1489 0u, // srcAccessMask
1490 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // dstAccessMask
1491 vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
1492 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
1493 queueFamilyIndex, // srcQueueFamilyIndex
1494 queueFamilyIndex, // destQueueFamilyIndex
1495 *m_rtImage, // image
1497 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
1500 0u, // baseArraySlice
1502 } // subresourceRange
1505 vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (vk::VkDependencyFlags)0,
1506 1, &vertFlushBarrier,
1507 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1508 1, &colorAttBarrier);
1512 const vk::VkClearValue clearValue = vk::makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
1513 const vk::VkRenderPassBeginInfo passBeginInfo =
1515 vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // sType
1517 *m_renderPass, // renderPass
1518 *m_framebuffer, // framebuffer
1519 { { 0, 0 }, { RENDER_WIDTH, RENDER_HEIGHT } }, // renderArea
1520 1u, // clearValueCount
1521 &clearValue, // pClearValues
1524 vkd.cmdBeginRenderPass(*m_cmdBuffer, &passBeginInfo, vk::VK_SUBPASS_CONTENTS_INLINE);
1527 vkd.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1529 if (!m_spec.values.uniforms.empty() || !m_spec.values.outputs.empty())
1530 vkd.cmdBindDescriptorSets(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, DE_NULL);
1533 const vk::VkBuffer buffers[] = { *m_posNdxBuffer, *m_inputBuffer };
1534 const vk::VkDeviceSize offsets[] = { POSITIONS_OFFSET, 0u };
1535 const deUint32 numBuffers = buffers[1] != 0 ? 2u : 1u;
1536 vkd.cmdBindVertexBuffers(*m_cmdBuffer, 0u, numBuffers, buffers, offsets);
1539 vkd.cmdBindIndexBuffer (*m_cmdBuffer, *m_posNdxBuffer, (vk::VkDeviceSize)INDICES_OFFSET, vk::VK_INDEX_TYPE_UINT16);
1540 vkd.cmdDrawIndexed (*m_cmdBuffer, 6u, 1u, 0u, 0u, 0u);
1541 vkd.cmdEndRenderPass (*m_cmdBuffer);
1544 const vk::VkImageMemoryBarrier renderFinishBarrier =
1546 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
1548 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask
1549 vk::VK_ACCESS_TRANSFER_READ_BIT, // dstAccessMask
1550 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // oldLayout
1551 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout
1552 queueFamilyIndex, // srcQueueFamilyIndex
1553 queueFamilyIndex, // destQueueFamilyIndex
1554 *m_rtImage, // image
1556 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
1559 0u, // baseArraySlice
1561 } // subresourceRange
1564 vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0,
1565 0, (const vk::VkMemoryBarrier*)DE_NULL,
1566 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1567 1, &renderFinishBarrier);
1571 const vk::VkBufferImageCopy copyParams =
1573 (vk::VkDeviceSize)0u, // bufferOffset
1574 (deUint32)RENDER_WIDTH, // bufferRowLength
1575 (deUint32)RENDER_HEIGHT, // bufferImageHeight
1577 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspect
1581 }, // imageSubresource
1582 { 0u, 0u, 0u }, // imageOffset
1583 { RENDER_WIDTH, RENDER_HEIGHT, 1u } // imageExtent
1586 vkd.cmdCopyImageToBuffer(*m_cmdBuffer, *m_rtImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_readImageBuffer, 1u, ©Params);
1590 const vk::VkBufferMemoryBarrier copyFinishBarrier =
1592 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
1594 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask
1595 vk::VK_ACCESS_HOST_READ_BIT, // dstAccessMask
1596 queueFamilyIndex, // srcQueueFamilyIndex
1597 queueFamilyIndex, // destQueueFamilyIndex
1598 *m_readImageBuffer, // buffer
1600 (vk::VkDeviceSize)(RENDER_WIDTH*RENDER_HEIGHT*4) // size
1603 vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0,
1604 0, (const vk::VkMemoryBarrier*)DE_NULL,
1605 1, ©FinishBarrier,
1606 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
1609 VK_CHECK(vkd.endCommandBuffer(*m_cmdBuffer));
1612 ShaderCaseInstance::~ShaderCaseInstance (void)
1616 int getNumSubCases (const ValueBlock& values)
1618 if (!values.outputs.empty())
1619 return int(values.outputs[0].elements.size() / values.outputs[0].type.getScalarSize());
1621 return 1; // Always run at least one iteration even if no output values are specified
1624 bool checkResultImage (const ConstPixelBufferAccess& result)
1626 const tcu::IVec4 refPix (255, 255, 255, 255);
1628 for (int y = 0; y < result.getHeight(); y++)
1630 for (int x = 0; x < result.getWidth(); x++)
1632 const tcu::IVec4 resPix = result.getPixelInt(x, y);
1634 if (boolAny(notEqual(resPix, refPix)))
1642 TestStatus ShaderCaseInstance::iterate (void)
1644 const vk::DeviceInterface& vkd = m_context.getDeviceInterface();
1645 const vk::VkDevice device = m_context.getDevice();
1646 const vk::VkQueue queue = m_context.getUniversalQueue();
1648 if (!m_spec.values.inputs.empty())
1649 writeValuesToMem(m_context, *m_inputMem, m_inputLayout, m_spec.values.inputs, m_subCaseNdx);
1651 if (!m_spec.values.outputs.empty())
1652 writeValuesToMem(m_context, *m_referenceMem, m_referenceLayout, m_spec.values.outputs, m_subCaseNdx);
1654 if (!m_spec.values.uniforms.empty())
1655 writeValuesToMem(m_context, *m_uniformMem, m_uniformLayout, m_spec.values.uniforms, m_subCaseNdx);
1658 const vk::VkSubmitInfo submitInfo =
1660 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1662 0u, // waitSemaphoreCount
1663 (const vk::VkSemaphore*)0, // pWaitSemaphores
1664 (const vk::VkPipelineStageFlags*)DE_NULL,
1667 0u, // signalSemaphoreCount
1668 (const vk::VkSemaphore*)0, // pSignalSemaphores
1670 const Unique<vk::VkFence> fence (vk::createFence(vkd, device));
1672 VK_CHECK(vkd.queueSubmit (queue, 1u, &submitInfo, *fence));
1673 VK_CHECK(vkd.waitForFences (device, 1u, &fence.get(), DE_TRUE, ~0ull));
1677 const ConstPixelBufferAccess imgAccess (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), RENDER_WIDTH, RENDER_HEIGHT, 1, m_readImageMem->getHostPtr());
1679 invalidateMappedMemoryRange(vkd, device, m_readImageMem->getMemory(), m_readImageMem->getOffset(), (vk::VkDeviceSize)(RENDER_WIDTH*RENDER_HEIGHT*4));
1681 if (!checkResultImage(imgAccess))
1683 TestLog& log = m_context.getTestContext().getLog();
1685 log << TestLog::Message << "ERROR: Got non-white pixels on sub-case " << m_subCaseNdx << TestLog::EndMessage
1686 << TestLog::Image("Result", "Result", imgAccess);
1688 dumpValues(log, m_spec.values, m_subCaseNdx);
1690 return TestStatus::fail(string("Got invalid pixels at sub-case ") + de::toString(m_subCaseNdx));
1694 if (++m_subCaseNdx < getNumSubCases(m_spec.values))
1695 return TestStatus::incomplete();
1697 return TestStatus::pass("All sub-cases passed");
1700 class ShaderCase : public TestCase
1703 ShaderCase (tcu::TestContext& testCtx, const string& name, const string& description, const ShaderCaseSpecification& spec);
1706 void initPrograms (SourceCollections& programCollection) const;
1707 TestInstance* createInstance (Context& context) const;
1710 const ShaderCaseSpecification m_spec;
1713 ShaderCase::ShaderCase (tcu::TestContext& testCtx, const string& name, const string& description, const ShaderCaseSpecification& spec)
1714 : TestCase (testCtx, name, description)
1719 void ShaderCase::initPrograms (SourceCollections& sourceCollection) const
1721 vector<ProgramSources> specializedSources (m_spec.programs.size());
1723 DE_ASSERT(isValid(m_spec));
1725 if (m_spec.expectResult != glu::sl::EXPECT_PASS)
1726 TCU_THROW(InternalError, "Only EXPECT_PASS is supported");
1728 if (m_spec.caseType == glu::sl::CASETYPE_VERTEX_ONLY)
1730 DE_ASSERT(m_spec.programs.size() == 1 && m_spec.programs[0].sources.sources[glu::SHADERTYPE_VERTEX].size() == 1);
1731 specializedSources[0] << glu::VertexSource(specializeVertexShader(m_spec, m_spec.programs[0].sources.sources[glu::SHADERTYPE_VERTEX][0]))
1732 << glu::FragmentSource(genFragmentShader(m_spec));
1734 else if (m_spec.caseType == glu::sl::CASETYPE_FRAGMENT_ONLY)
1736 DE_ASSERT(m_spec.programs.size() == 1 && m_spec.programs[0].sources.sources[glu::SHADERTYPE_FRAGMENT].size() == 1);
1737 specializedSources[0] << glu::VertexSource(genVertexShader(m_spec))
1738 << glu::FragmentSource(specializeFragmentShader(m_spec, m_spec.programs[0].sources.sources[glu::SHADERTYPE_FRAGMENT][0]));
1742 DE_ASSERT(m_spec.caseType == glu::sl::CASETYPE_COMPLETE);
1744 const int maxPatchVertices = 4; // \todo [2015-08-05 pyry] Query
1746 for (size_t progNdx = 0; progNdx < m_spec.programs.size(); progNdx++)
1748 const ProgramSpecializationParams progSpecParams (m_spec, m_spec.programs[progNdx].requiredExtensions, maxPatchVertices);
1750 specializeProgramSources(specializedSources[progNdx], m_spec.programs[progNdx].sources, progSpecParams);
1754 for (size_t progNdx = 0; progNdx < specializedSources.size(); progNdx++)
1756 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
1758 if (!specializedSources[progNdx].sources[shaderType].empty())
1760 vk::GlslSource& curSrc = sourceCollection.glslSources.add(getShaderName((glu::ShaderType)shaderType, progNdx));
1761 curSrc.sources[shaderType] = specializedSources[progNdx].sources[shaderType];
1767 TestInstance* ShaderCase::createInstance (Context& context) const
1769 return new ShaderCaseInstance(context, m_spec);
1772 class ShaderCaseFactory : public glu::sl::ShaderCaseFactory
1775 ShaderCaseFactory (tcu::TestContext& testCtx)
1776 : m_testCtx(testCtx)
1780 tcu::TestCaseGroup* createGroup (const string& name, const string& description, const vector<tcu::TestNode*>& children)
1782 return new tcu::TestCaseGroup(m_testCtx, name.c_str(), description.c_str(), children);
1785 tcu::TestCase* createCase (const string& name, const string& description, const ShaderCaseSpecification& spec)
1787 return new ShaderCase(m_testCtx, name, description, spec);
1791 tcu::TestContext& m_testCtx;
1794 class ShaderLibraryGroup : public tcu::TestCaseGroup
1797 ShaderLibraryGroup (tcu::TestContext& testCtx, const string& name, const string& description, const string& filename)
1798 : tcu::TestCaseGroup (testCtx, name.c_str(), description.c_str())
1799 , m_filename (filename)
1805 ShaderCaseFactory caseFactory (m_testCtx);
1806 const vector<tcu::TestNode*> children = glu::sl::parseFile(m_testCtx.getArchive(), m_filename, &caseFactory);
1808 for (size_t ndx = 0; ndx < children.size(); ndx++)
1812 addChild(children[ndx]);
1816 for (; ndx < children.size(); ndx++)
1817 delete children[ndx];
1824 const string m_filename;
1829 MovePtr<tcu::TestCaseGroup> createShaderLibraryGroup (tcu::TestContext& testCtx, const string& name, const string& description, const string& filename)
1831 return MovePtr<tcu::TestCaseGroup>(new ShaderLibraryGroup(testCtx, name, description, filename));