1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2023 LunarG, Inc.
7 * Copyright (c) 2023 Nintendo
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Pipeline specialization constants tests
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktPipelineSpecConstantTests.hpp"
27 #include "vktTestCase.hpp"
28 #include "vktPipelineSpecConstantUtil.hpp"
29 #include "vktPipelineMakeUtil.hpp"
30
31 #include "tcuTestLog.hpp"
32 #include "tcuTexture.hpp"
33 #include "tcuFormatUtil.hpp"
34 #include "tcuFloat.hpp"
35
36 #include "gluShaderUtil.hpp"
37
38 #include "vkBuilderUtil.hpp"
39 #include "vkPrograms.hpp"
40 #include "vkRefUtil.hpp"
41 #include "vkTypeUtil.hpp"
42 #include "vkImageUtil.hpp"
43 #include "vkBarrierUtil.hpp"
44 #include "vkCmdUtil.hpp"
45 #include "vkObjUtil.hpp"
46 #include "vkBufferWithMemory.hpp"
47 #include "vkImageWithMemory.hpp"
48 #include "vkComputePipelineConstructionUtil.hpp"
49
50 #include "deUniquePtr.hpp"
51 #include "deStringUtil.hpp"
52
53 #include <limits>
54
55 namespace vkt
56 {
57 namespace pipeline
58 {
59
60 using namespace vk;
61
62 namespace
63 {
64
65 static const char *const s_perVertexBlock = "gl_PerVertex {\n"
66 " vec4 gl_Position;\n"
67 "}";
68
69 //! Raw memory storage for values used in test cases.
70 //! We use it to simplify test case definitions where different types are expected in the result.
71 class GenericValue
72 {
73 public:
GenericValue(void)74 GenericValue(void)
75 {
76 clear();
77 }
78
79 //! Copy up to 'size' bytes of 'data'.
GenericValue(const void * data,const uint32_t size)80 GenericValue(const void *data, const uint32_t size)
81 {
82 DE_ASSERT(size <= sizeof(m_data));
83 clear();
84 deMemcpy(&m_data, data, size);
85 }
86
87 private:
88 uint64_t m_data;
89
clear(void)90 void clear(void)
91 {
92 m_data = 0;
93 }
94 };
95
makeValueBool32(const bool a)96 inline GenericValue makeValueBool32(const bool a)
97 {
98 return GenericValue(&a, sizeof(a));
99 }
makeValueInt8(const int8_t a)100 inline GenericValue makeValueInt8(const int8_t a)
101 {
102 return GenericValue(&a, sizeof(a));
103 }
makeValueUint8(const uint8_t a)104 inline GenericValue makeValueUint8(const uint8_t a)
105 {
106 return GenericValue(&a, sizeof(a));
107 }
makeValueInt16(const int16_t a)108 inline GenericValue makeValueInt16(const int16_t a)
109 {
110 return GenericValue(&a, sizeof(a));
111 }
makeValueUint16(const uint16_t a)112 inline GenericValue makeValueUint16(const uint16_t a)
113 {
114 return GenericValue(&a, sizeof(a));
115 }
makeValueInt32(const int32_t a)116 inline GenericValue makeValueInt32(const int32_t a)
117 {
118 return GenericValue(&a, sizeof(a));
119 }
makeValueUint32(const uint32_t a)120 inline GenericValue makeValueUint32(const uint32_t a)
121 {
122 return GenericValue(&a, sizeof(a));
123 }
makeValueInt64(const int64_t a)124 inline GenericValue makeValueInt64(const int64_t a)
125 {
126 return GenericValue(&a, sizeof(a));
127 }
makeValueUint64(const uint64_t a)128 inline GenericValue makeValueUint64(const uint64_t a)
129 {
130 return GenericValue(&a, sizeof(a));
131 }
makeValueFloat16(const tcu::Float16 a)132 inline GenericValue makeValueFloat16(const tcu::Float16 a)
133 {
134 return GenericValue(&a, sizeof(a));
135 }
makeValueFloat32(const float a)136 inline GenericValue makeValueFloat32(const float a)
137 {
138 return GenericValue(&a, sizeof(a));
139 }
makeValueFloat64(const double a)140 inline GenericValue makeValueFloat64(const double a)
141 {
142 return GenericValue(&a, sizeof(a));
143 }
144
145 struct SpecConstant
146 {
147 uint32_t specID; //!< specialization constant ID
148 std::string declarationCode; //!< syntax to declare the constant, use ${ID} as an ID placeholder
149 uint32_t size; //!< data size on the host, 0 = no specialized value
150 GenericValue specValue; //!< specialized value passed by the API
151 bool forceUse; //!< always include a VkSpecializationMapEntry for this spec constant
152
SpecConstantvkt::pipeline::__anon900a836d0111::SpecConstant153 SpecConstant(const uint32_t specID_, const std::string declarationCode_)
154 : specID(specID_)
155 , declarationCode(declarationCode_)
156 , size(0)
157 , specValue()
158 , forceUse(false)
159 {
160 }
161
SpecConstantvkt::pipeline::__anon900a836d0111::SpecConstant162 SpecConstant(const uint32_t specID_, const std::string declarationCode_, const uint32_t size_,
163 const GenericValue specValue_, bool forceUse_ = false)
164 : specID(specID_)
165 , declarationCode(declarationCode_)
166 , size(size_)
167 , specValue(specValue_)
168 , forceUse(forceUse_)
169 {
170 }
171 };
172
173 //! Useful when referring to a value in a buffer (i.e. check expected values in SSBO).
174 struct OffsetValue
175 {
176 uint32_t size; //!< data size in the buffer (up to sizeof(value))
177 uint32_t offset; //!< offset into the buffer
178 GenericValue value; //!< value expected to be there
179
OffsetValuevkt::pipeline::__anon900a836d0111::OffsetValue180 OffsetValue(const uint32_t size_, const uint32_t offset_, const GenericValue value_)
181 : size(size_)
182 , offset(offset_)
183 , value(value_)
184 {
185 }
186 };
187
188 //! Get the integer value of 'size' bytes at 'memory' location.
memoryAsInteger(const void * memory,const uint32_t size)189 uint64_t memoryAsInteger(const void *memory, const uint32_t size)
190 {
191 DE_ASSERT(size <= sizeof(uint64_t));
192 uint64_t value = 0;
193 deMemcpy(&value, memory, size);
194 return value;
195 }
196
memoryAsHexString(const void * memory,const uint32_t size)197 inline std::string memoryAsHexString(const void *memory, const uint32_t size)
198 {
199 const uint8_t *memoryBytePtr = static_cast<const uint8_t *>(memory);
200 return de::toString(tcu::formatArray(tcu::Format::HexIterator<uint8_t>(memoryBytePtr),
201 tcu::Format::HexIterator<uint8_t>(memoryBytePtr + size)));
202 }
203
logValueMismatch(tcu::TestLog & log,const void * expected,const void * actual,const uint32_t offset,const uint32_t size)204 void logValueMismatch(tcu::TestLog &log, const void *expected, const void *actual, const uint32_t offset,
205 const uint32_t size)
206 {
207 const bool canDisplayValue = (size <= sizeof(uint64_t));
208 log << tcu::TestLog::Message << "Comparison failed for value at offset " << de::toString(offset) << ": expected "
209 << (canDisplayValue ? de::toString(memoryAsInteger(expected, size)) + " " : "")
210 << memoryAsHexString(expected, size) << " but got "
211 << (canDisplayValue ? de::toString(memoryAsInteger(actual, size)) + " " : "") << memoryAsHexString(actual, size)
212 << tcu::TestLog::EndMessage;
213 }
214
215 //! Check if expected values exist in the memory.
verifyValues(tcu::TestLog & log,const void * memory,const std::vector<OffsetValue> & expectedValues)216 bool verifyValues(tcu::TestLog &log, const void *memory, const std::vector<OffsetValue> &expectedValues)
217 {
218 bool ok = true;
219 log << tcu::TestLog::Section("compare", "Verify result values");
220
221 for (std::vector<OffsetValue>::const_iterator it = expectedValues.begin(); it < expectedValues.end(); ++it)
222 {
223 const char *const valuePtr = static_cast<const char *>(memory) + it->offset;
224 if (deMemCmp(valuePtr, &it->value, it->size) != 0)
225 {
226 ok = false;
227 logValueMismatch(log, &it->value, valuePtr, it->offset, it->size);
228 }
229 }
230
231 if (ok)
232 log << tcu::TestLog::Message << "All OK" << tcu::TestLog::EndMessage;
233
234 log << tcu::TestLog::EndSection;
235 return ok;
236 }
237
238 //! Bundles together common test case parameters.
239 struct CaseDefinition
240 {
241 std::string name; //!< Test case name
242 std::vector<SpecConstant> specConstants; //!< list of specialization constants to declare
243 VkDeviceSize ssboSize; //!< required ssbo size in bytes
244 std::string ssboCode; //!< ssbo member definitions
245 std::string globalCode; //!< generic shader code outside the main function (e.g. declarations)
246 std::string mainCode; //!< generic shader code to execute in main (e.g. assignments)
247 std::vector<OffsetValue> expectedValues; //!< list of values to check inside the ssbo buffer
248 FeatureFlags requirements; //!< features the implementation must support to allow this test to run
249 bool packData; //!< whether to tightly pack specialization constant data or not
250 };
251
252 //! Manages Vulkan structures to pass specialization data.
253 class Specialization
254 {
255 public:
256 Specialization(const std::vector<SpecConstant> &specConstants, bool packData);
257
258 //! Can return NULL if nothing is specialized
getSpecializationInfo(void) const259 const VkSpecializationInfo *getSpecializationInfo(void) const
260 {
261 return m_entries.size() > 0 ? &m_specialization : DE_NULL;
262 }
263
264 private:
265 std::vector<uint8_t> m_data;
266 std::vector<VkSpecializationMapEntry> m_entries;
267 VkSpecializationInfo m_specialization;
268 };
269
Specialization(const std::vector<SpecConstant> & specConstants,bool packData)270 Specialization::Specialization(const std::vector<SpecConstant> &specConstants, bool packData)
271 {
272 const auto kGenericValueSize = static_cast<uint32_t>(sizeof(GenericValue));
273
274 // Reserve memory for the worst case in m_data.
275 m_data.resize(specConstants.size() * kGenericValueSize, std::numeric_limits<uint8_t>::max());
276 m_entries.reserve(specConstants.size());
277
278 uint32_t offset = 0u;
279 for (const auto &sc : specConstants)
280 {
281 if (sc.size != 0u || sc.forceUse)
282 {
283 if (sc.size > 0u)
284 deMemcpy(&m_data[offset], &sc.specValue, sc.size);
285 m_entries.push_back(makeSpecializationMapEntry(sc.specID, offset, sc.size));
286 offset += (packData ? sc.size : kGenericValueSize);
287 }
288 }
289
290 if (m_entries.size() > 0)
291 {
292 m_specialization.mapEntryCount = static_cast<uint32_t>(m_entries.size());
293 m_specialization.pMapEntries = m_entries.data();
294 m_specialization.dataSize = static_cast<uintptr_t>(offset);
295 m_specialization.pData = m_data.data();
296 }
297 else
298 deMemset(&m_specialization, 0, sizeof(m_specialization));
299 }
300
301 class SpecConstantTest : public TestCase
302 {
303 public:
304 SpecConstantTest(tcu::TestContext &testCtx,
305 const PipelineConstructionType pipelineType, //!< how pipeline is constructed
306 const VkShaderStageFlagBits stage, //!< which shader stage is tested
307 const CaseDefinition &caseDef);
308
309 void initPrograms(SourceCollections &programCollection) const;
310 TestInstance *createInstance(Context &context) const;
311 virtual void checkSupport(Context &context) const;
312
313 private:
314 const PipelineConstructionType m_pipelineConstructionType;
315 const VkShaderStageFlagBits m_stage;
316 const CaseDefinition m_caseDef;
317 };
318
SpecConstantTest(tcu::TestContext & testCtx,const PipelineConstructionType pipelineType,const VkShaderStageFlagBits stage,const CaseDefinition & caseDef)319 SpecConstantTest::SpecConstantTest(tcu::TestContext &testCtx, const PipelineConstructionType pipelineType,
320 const VkShaderStageFlagBits stage, const CaseDefinition &caseDef)
321 : TestCase(testCtx, caseDef.name)
322 , m_pipelineConstructionType(pipelineType)
323 , m_stage(stage)
324 , m_caseDef(caseDef)
325 {
326 }
327
328 //! Build a string that declares all specialization constants, replacing ${ID} with proper ID numbers.
generateSpecConstantCode(const std::vector<SpecConstant> & specConstants)329 std::string generateSpecConstantCode(const std::vector<SpecConstant> &specConstants)
330 {
331 std::ostringstream code;
332 for (std::vector<SpecConstant>::const_iterator it = specConstants.begin(); it != specConstants.end(); ++it)
333 {
334 std::string decl = it->declarationCode;
335 const std::string::size_type pos = decl.find("${ID}");
336 if (pos != std::string::npos)
337 decl.replace(pos, 5, de::toString(it->specID));
338 code << decl << "\n";
339 }
340 code << "\n";
341 return code.str();
342 }
343
generateSSBOCode(const std::string & memberDeclarations)344 std::string generateSSBOCode(const std::string &memberDeclarations)
345 {
346 std::ostringstream code;
347 code << "layout (set = 0, binding = 0, std430) writeonly buffer Output {\n"
348 << memberDeclarations << "} sb_out;\n"
349 << "\n";
350 return code.str();
351 }
352
initPrograms(SourceCollections & programCollection) const353 void SpecConstantTest::initPrograms(SourceCollections &programCollection) const
354 {
355 // Always add vertex and fragment to graphics stages
356 VkShaderStageFlags requiredStages = m_stage;
357
358 if (requiredStages & VK_SHADER_STAGE_ALL_GRAPHICS)
359 requiredStages |= VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
360
361 if (requiredStages & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
362 requiredStages |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
363
364 // Either graphics or compute must be defined, but not both
365 DE_ASSERT(((requiredStages & VK_SHADER_STAGE_ALL_GRAPHICS) != 0) !=
366 ((requiredStages & VK_SHADER_STAGE_COMPUTE_BIT) != 0));
367
368 // Extensions needed for some tests.
369 std::ostringstream extStream;
370 if (m_caseDef.requirements & FEATURE_SHADER_INT_64)
371 extStream << "#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require\n";
372 if (m_caseDef.requirements & FEATURE_SHADER_INT_16)
373 extStream << "#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require\n";
374 if (m_caseDef.requirements & FEATURE_SHADER_INT_8)
375 extStream << "#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require\n";
376 if (m_caseDef.requirements & FEATURE_SHADER_FLOAT_16)
377 extStream << "#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require\n";
378 const std::string extensions = extStream.str();
379
380 // This makes glslang avoid the UniformAndStorage* capabilities.
381 const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3, 0u);
382
383 if (requiredStages & VK_SHADER_STAGE_VERTEX_BIT)
384 {
385 const bool useSpecConst = (m_stage == VK_SHADER_STAGE_VERTEX_BIT);
386 std::ostringstream src;
387 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
388 << extensions << "layout(location = 0) in highp vec4 position;\n"
389 << "\n"
390 << "out " << s_perVertexBlock << ";\n"
391 << "\n"
392 << (useSpecConst ? generateSpecConstantCode(m_caseDef.specConstants) : "")
393 << (useSpecConst ? generateSSBOCode(m_caseDef.ssboCode) : "")
394 << (useSpecConst ? m_caseDef.globalCode + "\n" : "") << "void main (void)\n"
395 << "{\n"
396 << (useSpecConst ? m_caseDef.mainCode + "\n" : "") << " gl_Position = position;\n"
397 << "}\n";
398
399 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()) << buildOptions;
400 }
401
402 if (requiredStages & VK_SHADER_STAGE_FRAGMENT_BIT)
403 {
404 const bool useSpecConst = (m_stage == VK_SHADER_STAGE_FRAGMENT_BIT);
405 std::ostringstream src;
406 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
407 << extensions << "layout(location = 0) out highp vec4 fragColor;\n"
408 << "\n"
409 << (useSpecConst ? generateSpecConstantCode(m_caseDef.specConstants) : "")
410 << (useSpecConst ? generateSSBOCode(m_caseDef.ssboCode) : "")
411 << (useSpecConst ? m_caseDef.globalCode + "\n" : "") << "void main (void)\n"
412 << "{\n"
413 << (useSpecConst ? m_caseDef.mainCode + "\n" : "") << " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
414 << "}\n";
415
416 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()) << buildOptions;
417 }
418
419 if (requiredStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
420 {
421 const bool useSpecConst = (m_stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
422 std::ostringstream src;
423 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
424 << extensions << "layout(vertices = 3) out;\n"
425 << "\n"
426 << "in " << s_perVertexBlock << " gl_in[gl_MaxPatchVertices];\n"
427 << "\n"
428 << "out " << s_perVertexBlock << " gl_out[];\n"
429 << "\n"
430 << (useSpecConst ? generateSpecConstantCode(m_caseDef.specConstants) : "")
431 << (useSpecConst ? generateSSBOCode(m_caseDef.ssboCode) : "")
432 << (useSpecConst ? m_caseDef.globalCode + "\n" : "") << "void main (void)\n"
433 << "{\n"
434 << (useSpecConst ? m_caseDef.mainCode + "\n" : "")
435 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
436 << " if (gl_InvocationID == 0)\n"
437 << " {\n"
438 << " gl_TessLevelInner[0] = 3;\n"
439 << " gl_TessLevelOuter[0] = 2;\n"
440 << " gl_TessLevelOuter[1] = 2;\n"
441 << " gl_TessLevelOuter[2] = 2;\n"
442 << " }\n"
443 << "}\n";
444
445 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str()) << buildOptions;
446 }
447
448 if (requiredStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
449 {
450 const bool useSpecConst = (m_stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
451 std::ostringstream src;
452 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
453 << extensions << "layout(triangles, equal_spacing, ccw) in;\n"
454 << "\n"
455 << "in " << s_perVertexBlock << " gl_in[gl_MaxPatchVertices];\n"
456 << "\n"
457 << "out " << s_perVertexBlock << ";\n"
458 << "\n"
459 << (useSpecConst ? generateSpecConstantCode(m_caseDef.specConstants) : "")
460 << (useSpecConst ? generateSSBOCode(m_caseDef.ssboCode) : "")
461 << (useSpecConst ? m_caseDef.globalCode + "\n" : "") << "void main (void)\n"
462 << "{\n"
463 << (useSpecConst ? m_caseDef.mainCode + "\n" : "")
464 << " vec3 p0 = gl_TessCoord.x * gl_in[0].gl_Position.xyz;\n"
465 << " vec3 p1 = gl_TessCoord.y * gl_in[1].gl_Position.xyz;\n"
466 << " vec3 p2 = gl_TessCoord.z * gl_in[2].gl_Position.xyz;\n"
467 << " gl_Position = vec4(p0 + p1 + p2, 1.0);\n"
468 << "}\n";
469
470 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str()) << buildOptions;
471 }
472
473 if (requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT)
474 {
475 const bool useSpecConst = (m_stage == VK_SHADER_STAGE_GEOMETRY_BIT);
476 std::ostringstream src;
477 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
478 << extensions << "layout(triangles) in;\n"
479 << "layout(triangle_strip, max_vertices = 3) out;\n"
480 << "\n"
481 << "in " << s_perVertexBlock << " gl_in[];\n"
482 << "\n"
483 << "out " << s_perVertexBlock << ";\n"
484 << "\n"
485 << (useSpecConst ? generateSpecConstantCode(m_caseDef.specConstants) : "")
486 << (useSpecConst ? generateSSBOCode(m_caseDef.ssboCode) : "")
487 << (useSpecConst ? m_caseDef.globalCode + "\n" : "") << "void main (void)\n"
488 << "{\n"
489 << (useSpecConst ? m_caseDef.mainCode + "\n" : "") << " gl_Position = gl_in[0].gl_Position;\n"
490 << " EmitVertex();\n"
491 << "\n"
492 << " gl_Position = gl_in[1].gl_Position;\n"
493 << " EmitVertex();\n"
494 << "\n"
495 << " gl_Position = gl_in[2].gl_Position;\n"
496 << " EmitVertex();\n"
497 << "\n"
498 << " EndPrimitive();\n"
499 << "}\n";
500
501 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str()) << buildOptions;
502 }
503
504 if (requiredStages & VK_SHADER_STAGE_COMPUTE_BIT)
505 {
506 std::ostringstream src;
507 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
508 << extensions
509 // Don't define work group size, use the default or specialization constants
510 << "\n"
511 << generateSpecConstantCode(m_caseDef.specConstants) << generateSSBOCode(m_caseDef.ssboCode)
512 << m_caseDef.globalCode + "\n"
513 << "void main (void)\n"
514 << "{\n"
515 << m_caseDef.mainCode << "}\n";
516
517 programCollection.glslSources.add("comp") << glu::ComputeSource(src.str()) << buildOptions;
518 }
519 }
520
521 class ComputeTestInstance : public TestInstance
522 {
523 public:
524 ComputeTestInstance(Context &context, PipelineConstructionType pipelineConstructionType,
525 const VkDeviceSize ssboSize, const std::vector<SpecConstant> &specConstants,
526 const std::vector<OffsetValue> &expectedValues, bool packData);
527
528 tcu::TestStatus iterate(void);
529
530 private:
531 const PipelineConstructionType m_pipelineConstructionType;
532 const VkDeviceSize m_ssboSize;
533 const std::vector<SpecConstant> m_specConstants;
534 const std::vector<OffsetValue> m_expectedValues;
535 const bool m_packData;
536 };
537
ComputeTestInstance(Context & context,PipelineConstructionType pipelineConstructionType,const VkDeviceSize ssboSize,const std::vector<SpecConstant> & specConstants,const std::vector<OffsetValue> & expectedValues,bool packData)538 ComputeTestInstance::ComputeTestInstance(Context &context, PipelineConstructionType pipelineConstructionType,
539 const VkDeviceSize ssboSize, const std::vector<SpecConstant> &specConstants,
540 const std::vector<OffsetValue> &expectedValues, bool packData)
541 : TestInstance(context)
542 , m_pipelineConstructionType(pipelineConstructionType)
543 , m_ssboSize(ssboSize)
544 , m_specConstants(specConstants)
545 , m_expectedValues(expectedValues)
546 , m_packData(packData)
547 {
548 }
549
iterate(void)550 tcu::TestStatus ComputeTestInstance::iterate(void)
551 {
552 const DeviceInterface &vk = m_context.getDeviceInterface();
553 const VkDevice device = m_context.getDevice();
554 const VkQueue queue = m_context.getUniversalQueue();
555 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
556 Allocator &allocator = m_context.getDefaultAllocator();
557
558 // Descriptors
559
560 const BufferWithMemory resultBuffer(vk, device, allocator,
561 makeBufferCreateInfo(m_ssboSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
562 MemoryRequirement::HostVisible);
563
564 const Unique<VkDescriptorSetLayout> descriptorSetLayout(
565 DescriptorSetLayoutBuilder()
566 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
567 .build(vk, device));
568
569 const Unique<VkDescriptorPool> descriptorPool(
570 DescriptorPoolBuilder()
571 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
572 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
573
574 const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
575 const VkDescriptorBufferInfo descriptorBufferInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, m_ssboSize);
576
577 DescriptorSetUpdateBuilder()
578 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
579 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo)
580 .update(vk, device);
581
582 // Specialization
583
584 const Specialization specialization(m_specConstants, m_packData);
585 const VkSpecializationInfo *pSpecInfo = specialization.getSpecializationInfo();
586
587 // Pipeline
588
589 const PipelineLayoutWrapper pipelineLayout(m_pipelineConstructionType, vk, device, *descriptorSetLayout);
590 ComputePipelineWrapper pipeline(vk, device, graphicsToComputeConstructionType(m_pipelineConstructionType),
591 m_context.getBinaryCollection().get("comp"));
592 pipeline.setDescriptorSetLayout(*descriptorSetLayout);
593 if (pSpecInfo)
594 pipeline.setSpecializationInfo(*pSpecInfo);
595 pipeline.buildPipeline();
596 const Unique<VkCommandPool> cmdPool(
597 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
598 const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
599
600 beginCommandBuffer(vk, *cmdBuffer);
601
602 pipeline.bind(*cmdBuffer);
603 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(),
604 0u, DE_NULL);
605
606 vk.cmdDispatch(*cmdBuffer, 1u, 1u, 1u);
607
608 {
609 const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
610 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, m_ssboSize);
611
612 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u,
613 DE_NULL, 1u, &shaderWriteBarrier, 0u, DE_NULL);
614 }
615
616 endCommandBuffer(vk, *cmdBuffer);
617 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
618
619 // Verify results
620
621 const Allocation &resultAlloc = resultBuffer.getAllocation();
622 invalidateAlloc(vk, device, resultAlloc);
623
624 if (verifyValues(m_context.getTestContext().getLog(), resultAlloc.getHostPtr(), m_expectedValues))
625 return tcu::TestStatus::pass("Success");
626 else
627 return tcu::TestStatus::fail("Values did not match");
628 }
629
630 class GraphicsTestInstance : public TestInstance
631 {
632 public:
633 GraphicsTestInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
634 const VkDeviceSize ssboSize, const std::vector<SpecConstant> &specConstants,
635 const std::vector<OffsetValue> &expectedValues, const VkShaderStageFlagBits stage,
636 bool packData);
637
638 tcu::TestStatus iterate(void);
639
640 private:
641 const PipelineConstructionType m_pipelineConstructionType;
642 const VkDeviceSize m_ssboSize;
643 const std::vector<SpecConstant> m_specConstants;
644 const std::vector<OffsetValue> m_expectedValues;
645 const VkShaderStageFlagBits m_stage;
646 const bool m_packData;
647 };
648
GraphicsTestInstance(Context & context,const PipelineConstructionType pipelineConstructionType,const VkDeviceSize ssboSize,const std::vector<SpecConstant> & specConstants,const std::vector<OffsetValue> & expectedValues,const VkShaderStageFlagBits stage,bool packData)649 GraphicsTestInstance::GraphicsTestInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
650 const VkDeviceSize ssboSize, const std::vector<SpecConstant> &specConstants,
651 const std::vector<OffsetValue> &expectedValues,
652 const VkShaderStageFlagBits stage, bool packData)
653 : TestInstance(context)
654 , m_pipelineConstructionType(pipelineConstructionType)
655 , m_ssboSize(ssboSize)
656 , m_specConstants(specConstants)
657 , m_expectedValues(expectedValues)
658 , m_stage(stage)
659 , m_packData(packData)
660 {
661 }
662
iterate(void)663 tcu::TestStatus GraphicsTestInstance::iterate(void)
664 {
665 const InstanceInterface &vki = m_context.getInstanceInterface();
666 const DeviceInterface &vk = m_context.getDeviceInterface();
667 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
668 const VkDevice device = m_context.getDevice();
669 const VkQueue queue = m_context.getUniversalQueue();
670 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
671 Allocator &allocator = m_context.getDefaultAllocator();
672
673 // Color attachment
674
675 const tcu::IVec2 renderSize = tcu::IVec2(32, 32);
676 const VkFormat imageFormat = VK_FORMAT_R8G8B8A8_UNORM;
677 const ImageWithMemory colorImage(vk, device, allocator,
678 makeImageCreateInfo(renderSize, imageFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT),
679 MemoryRequirement::Any);
680 const Unique<VkImageView> colorImageView(
681 makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, imageFormat,
682 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)));
683
684 // Vertex buffer
685
686 const uint32_t numVertices = 3;
687 const VkDeviceSize vertexBufferSizeBytes = sizeof(tcu::Vec4) * numVertices;
688 const BufferWithMemory vertexBuffer(vk, device, allocator,
689 makeBufferCreateInfo(vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
690 MemoryRequirement::HostVisible);
691
692 {
693 const Allocation &alloc = vertexBuffer.getAllocation();
694 tcu::Vec4 *pVertices = reinterpret_cast<tcu::Vec4 *>(alloc.getHostPtr());
695
696 pVertices[0] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
697 pVertices[1] = tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f);
698 pVertices[2] = tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f);
699
700 flushAlloc(vk, device, alloc);
701 // No barrier needed, flushed memory is automatically visible
702 }
703
704 // Descriptors
705
706 const BufferWithMemory resultBuffer(vk, device, allocator,
707 makeBufferCreateInfo(m_ssboSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
708 MemoryRequirement::HostVisible);
709
710 const Unique<VkDescriptorSetLayout> descriptorSetLayout(
711 DescriptorSetLayoutBuilder()
712 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL_GRAPHICS)
713 .build(vk, device));
714
715 const Unique<VkDescriptorPool> descriptorPool(
716 DescriptorPoolBuilder()
717 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
718 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
719
720 const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
721 const VkDescriptorBufferInfo descriptorBufferInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, m_ssboSize);
722
723 DescriptorSetUpdateBuilder()
724 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
725 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo)
726 .update(vk, device);
727
728 // Specialization
729
730 const Specialization specialization(m_specConstants, m_packData);
731 const VkSpecializationInfo *pSpecInfo = specialization.getSpecializationInfo();
732
733 // Pipeline
734
735 RenderPassWrapper renderPass(m_pipelineConstructionType, vk, device, imageFormat);
736 renderPass.createFramebuffer(vk, device, colorImage.get(), colorImageView.get(),
737 static_cast<uint32_t>(renderSize.x()), static_cast<uint32_t>(renderSize.y()));
738 const PipelineLayoutWrapper pipelineLayout(m_pipelineConstructionType, vk, device, *descriptorSetLayout);
739 const Unique<VkCommandPool> cmdPool(
740 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
741 const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
742
743 vk::BinaryCollection &binaryCollection(m_context.getBinaryCollection());
744 VkPrimitiveTopology topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
745 const std::vector<VkViewport> viewport{makeViewport(renderSize)};
746 const std::vector<VkRect2D> scissor{makeRect2D(renderSize)};
747
748 ShaderWrapper vertShaderModule = ShaderWrapper(vk, device, binaryCollection.get("vert"), 0u);
749 ShaderWrapper tescShaderModule;
750 ShaderWrapper teseShaderModule;
751 ShaderWrapper geomShaderModule;
752 ShaderWrapper fragShaderModule = ShaderWrapper(vk, device, binaryCollection.get("frag"), 0u);
753
754 if ((m_stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ||
755 (m_stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
756 {
757 tescShaderModule = ShaderWrapper(vk, device, binaryCollection.get("tesc"), 0u);
758 teseShaderModule = ShaderWrapper(vk, device, binaryCollection.get("tese"), 0u);
759 topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
760 }
761 if (m_stage == VK_SHADER_STAGE_GEOMETRY_BIT)
762 geomShaderModule = ShaderWrapper(vk, device, binaryCollection.get("geom"), 0u);
763
764 GraphicsPipelineWrapper graphicsPipeline(vki, vk, physicalDevice, device, m_context.getDeviceExtensions(),
765 m_pipelineConstructionType);
766 graphicsPipeline.setDefaultRasterizationState()
767 .setDefaultDepthStencilState()
768 .setDefaultMultisampleState()
769 .setDefaultColorBlendState()
770 .setDefaultTopology(topology)
771 .setupVertexInputState()
772 .setupPreRasterizationShaderState(viewport, scissor, pipelineLayout, *renderPass, 0u, vertShaderModule, 0u,
773 tescShaderModule, teseShaderModule, geomShaderModule, pSpecInfo)
774 .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragShaderModule, DE_NULL, DE_NULL, pSpecInfo)
775 .setupFragmentOutputState(*renderPass)
776 .setMonolithicPipelineLayout(pipelineLayout)
777 .buildPipeline();
778
779 // Draw commands
780
781 const VkRect2D renderArea = makeRect2D(renderSize);
782 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
783 const VkDeviceSize vertexBufferOffset = 0ull;
784
785 beginCommandBuffer(vk, *cmdBuffer);
786
787 {
788 const VkImageSubresourceRange imageFullSubresourceRange =
789 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
790 const VkImageMemoryBarrier barrierColorAttachmentSetInitialLayout =
791 makeImageMemoryBarrier(0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
792 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, imageFullSubresourceRange);
793
794 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
795 0u, DE_NULL, 0u, DE_NULL, 1u, &barrierColorAttachmentSetInitialLayout);
796 }
797
798 renderPass.begin(vk, *cmdBuffer, renderArea, clearColor);
799
800 graphicsPipeline.bind(*cmdBuffer);
801 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(),
802 0u, DE_NULL);
803 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
804
805 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
806 renderPass.end(vk, *cmdBuffer);
807
808 {
809 const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
810 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, m_ssboSize);
811
812 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u,
813 DE_NULL, 1u, &shaderWriteBarrier, 0u, DE_NULL);
814 }
815
816 endCommandBuffer(vk, *cmdBuffer);
817 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
818
819 // Verify results
820
821 const Allocation &resultAlloc = resultBuffer.getAllocation();
822 invalidateAlloc(vk, device, resultAlloc);
823
824 if (verifyValues(m_context.getTestContext().getLog(), resultAlloc.getHostPtr(), m_expectedValues))
825 return tcu::TestStatus::pass("Success");
826 else
827 return tcu::TestStatus::fail("Values did not match");
828 }
829
getShaderStageRequirements(const VkShaderStageFlags stageFlags)830 FeatureFlags getShaderStageRequirements(const VkShaderStageFlags stageFlags)
831 {
832 FeatureFlags features = (FeatureFlags)0;
833
834 if (((stageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ||
835 ((stageFlags & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0))
836 features |= FEATURE_TESSELLATION_SHADER;
837
838 if ((stageFlags & VK_SHADER_STAGE_GEOMETRY_BIT) != 0)
839 features |= FEATURE_GEOMETRY_SHADER;
840
841 // All tests use SSBO writes to read back results.
842 if ((stageFlags & VK_SHADER_STAGE_ALL_GRAPHICS) != 0)
843 {
844 if ((stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) != 0)
845 features |= FEATURE_FRAGMENT_STORES_AND_ATOMICS;
846 else
847 features |= FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS;
848 }
849
850 return features;
851 }
852
checkSupport(Context & context) const853 void SpecConstantTest::checkSupport(Context &context) const
854 {
855 requireFeatures(context, m_caseDef.requirements | getShaderStageRequirements(m_stage));
856 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
857 m_pipelineConstructionType);
858 }
859
createInstance(Context & context) const860 TestInstance *SpecConstantTest::createInstance(Context &context) const
861 {
862 if (m_stage & VK_SHADER_STAGE_COMPUTE_BIT)
863 return new ComputeTestInstance(context, m_pipelineConstructionType, m_caseDef.ssboSize, m_caseDef.specConstants,
864 m_caseDef.expectedValues, m_caseDef.packData);
865 else
866 return new GraphicsTestInstance(context, m_pipelineConstructionType, m_caseDef.ssboSize,
867 m_caseDef.specConstants, m_caseDef.expectedValues, m_stage, m_caseDef.packData);
868 }
869
870 //! Declare specialization constants but use them with default values.
createDefaultValueTests(tcu::TestContext & testCtx,const PipelineConstructionType pipelineType,const VkShaderStageFlagBits shaderStage)871 tcu::TestCaseGroup *createDefaultValueTests(tcu::TestContext &testCtx, const PipelineConstructionType pipelineType,
872 const VkShaderStageFlagBits shaderStage)
873 {
874 // use default constant value
875 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "default_value"));
876
877 CaseDefinition defs[] = {
878 {
879 "bool",
880 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const bool sc0 = true;"),
881 SpecConstant(2u, "layout(constant_id = ${ID}) const bool sc1 = false;")),
882 8,
883 " bool r0;\n"
884 " bool r1;\n",
885 "",
886 " sb_out.r0 = sc0;\n"
887 " sb_out.r1 = sc1;\n",
888 makeVector(OffsetValue(4, 0, makeValueBool32(true)), OffsetValue(4, 4, makeValueBool32(false))),
889 (FeatureFlags)0,
890 false,
891 },
892 {
893 "int8",
894 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int8_t sc0 = int8_t(1);"),
895 SpecConstant(2u, "layout(constant_id = ${ID}) const int8_t sc1 = int8_t(-2);")),
896 2,
897 " int8_t r0;\n"
898 " int8_t r1;\n",
899 "",
900 " int8_t aux = sc0 + sc1;\n"
901 " sb_out.r0 = sc0;\n"
902 " sb_out.r1 = sc1;\n",
903 makeVector(OffsetValue(1, 0, makeValueInt8(1)), OffsetValue(1, 1, makeValueInt8(-2))),
904 FEATURE_SHADER_INT_8,
905 false,
906 },
907 {
908 "uint8",
909 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint8_t sc0 = int8_t(15);"),
910 SpecConstant(2u, "layout(constant_id = ${ID}) const uint8_t sc1 = int8_t(43);")),
911 2,
912 " uint8_t r0;\n"
913 " uint8_t r1;\n",
914 "",
915 " uint8_t aux = sc0 + sc1;\n"
916 " sb_out.r0 = sc0;\n"
917 " sb_out.r1 = sc1;\n",
918 makeVector(OffsetValue(1, 0, makeValueUint8(15)), OffsetValue(1, 1, makeValueUint8(43))),
919 FEATURE_SHADER_INT_8,
920 false,
921 },
922 {
923 "int16",
924 makeVector(
925 SpecConstant(1u, "layout(constant_id = ${ID}) const int16_t sc0 = 20000s;", 2, makeValueInt16(32000)),
926 SpecConstant(2u, "layout(constant_id = ${ID}) const int16_t sc1 = -20000s;")),
927 4,
928 " int16_t r0;\n"
929 " int16_t r1;\n",
930 "",
931 " int16_t aux = sc0 + sc1;\n"
932 " sb_out.r0 = sc0;\n"
933 " sb_out.r1 = sc1;\n",
934 makeVector(OffsetValue(2, 0, makeValueInt16(32000)), OffsetValue(2, 2, makeValueInt16(-20000))),
935 FEATURE_SHADER_INT_16,
936 false,
937 },
938 {
939 "uint16",
940 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint16_t sc0 = 64000us;"),
941 SpecConstant(2u, "layout(constant_id = ${ID}) const uint16_t sc1 = 51829us;")),
942 4,
943 " uint16_t r0;\n"
944 " uint16_t r1;\n",
945 "",
946 " uint16_t aux = sc0 + sc1;\n"
947 " sb_out.r0 = sc0;\n"
948 " sb_out.r1 = sc1;\n",
949 makeVector(OffsetValue(2, 0, makeValueUint16(64000)), OffsetValue(2, 2, makeValueUint16(51829))),
950 FEATURE_SHADER_INT_16,
951 false,
952 },
953 {
954 "int",
955 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = -3;"),
956 SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 17;")),
957 8,
958 " int r0;\n"
959 " int r1;\n",
960 "",
961 " sb_out.r0 = sc0;\n"
962 " sb_out.r1 = sc1;\n",
963 makeVector(OffsetValue(4, 0, makeValueInt32(-3)), OffsetValue(4, 4, makeValueInt32(17))),
964 (FeatureFlags)0,
965 false,
966 },
967 {
968 "uint",
969 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint sc0 = 42u;")),
970 4,
971 " uint r0;\n",
972 "",
973 " sb_out.r0 = sc0;\n",
974 makeVector(OffsetValue(4, 0, makeValueUint32(42u))),
975 (FeatureFlags)0,
976 false,
977 },
978 {
979 "int64",
980 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int64_t sc0 = 9141386509785772560l;"),
981 SpecConstant(2u, "layout(constant_id = ${ID}) const int64_t sc1 = -9141386509785772560l;")),
982 16,
983 " int64_t r0;\n"
984 " int64_t r1;\n",
985 "",
986 " sb_out.r0 = sc0;\n"
987 " sb_out.r1 = sc1;\n",
988 makeVector(OffsetValue(8, 0, makeValueInt64(9141386509785772560ll)),
989 OffsetValue(8, 8, makeValueInt64(-9141386509785772560ll))),
990 FEATURE_SHADER_INT_64,
991 false,
992 },
993 {
994 "uint64",
995 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint64_t sc0 = 18364758544493064720ul;"),
996 SpecConstant(2u, "layout(constant_id = ${ID}) const uint64_t sc1 = 17298946664678735070ul;")),
997 16,
998 " uint64_t r0;\n"
999 " uint64_t r1;\n",
1000 "",
1001 " sb_out.r0 = sc0;\n"
1002 " sb_out.r1 = sc1;\n",
1003 makeVector(OffsetValue(8, 0, makeValueUint64(18364758544493064720ull)),
1004 OffsetValue(8, 8, makeValueUint64(17298946664678735070ull))),
1005 FEATURE_SHADER_INT_64,
1006 false,
1007 },
1008 {
1009 "float16",
1010 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const float16_t sc0 = 7.5hf;"),
1011 SpecConstant(2u, "layout(constant_id = ${ID}) const float16_t sc1 = 1.125hf;")),
1012 4,
1013 " float16_t r0;\n"
1014 " float16_t r1;\n",
1015 "",
1016 " float16_t aux = sc0 + sc1;\n"
1017 " sb_out.r0 = sc0;\n"
1018 " sb_out.r1 = sc1;\n",
1019 makeVector(OffsetValue(2, 0, makeValueFloat16(tcu::Float16(7.5))),
1020 OffsetValue(2, 2, makeValueFloat16(tcu::Float16(1.125)))),
1021 FEATURE_SHADER_FLOAT_16,
1022 false,
1023 },
1024 {
1025 "float",
1026 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const float sc0 = 7.5;")),
1027 4,
1028 " float r0;\n",
1029 "",
1030 " sb_out.r0 = sc0;\n",
1031 makeVector(OffsetValue(4, 0, makeValueFloat32(7.5f))),
1032 (FeatureFlags)0,
1033 false,
1034 },
1035 {
1036 "double",
1037 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const double sc0 = 2.75LF;")),
1038 8,
1039 " double r0;\n",
1040 "",
1041 " sb_out.r0 = sc0;\n",
1042 makeVector(OffsetValue(8, 0, makeValueFloat64(2.75))),
1043 FEATURE_SHADER_FLOAT_64,
1044 false,
1045 },
1046 };
1047
1048 for (int i = 0; i < 2; ++i)
1049 {
1050 const bool packData = (i > 0);
1051 for (int defNdx = 0; defNdx < DE_LENGTH_OF_ARRAY(defs); ++defNdx)
1052 {
1053 auto &def = defs[defNdx];
1054 def.packData = packData;
1055 if (packData)
1056 def.name += "_packed";
1057 testGroup->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, def));
1058 }
1059 }
1060
1061 return testGroup.release();
1062 }
1063
1064 //! Declare specialization constants and specify their values through API.
createBasicSpecializationTests(tcu::TestContext & testCtx,const PipelineConstructionType pipelineType,const VkShaderStageFlagBits shaderStage)1065 tcu::TestCaseGroup *createBasicSpecializationTests(tcu::TestContext &testCtx,
1066 const PipelineConstructionType pipelineType,
1067 const VkShaderStageFlagBits shaderStage)
1068 {
1069 // specialize a constant
1070 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "basic"));
1071
1072 CaseDefinition defs[] = {
1073 {
1074 "bool",
1075 makeVector(
1076 SpecConstant(1u, "layout(constant_id = ${ID}) const bool sc0 = true;", 4, makeValueBool32(true)),
1077 SpecConstant(2u, "layout(constant_id = ${ID}) const bool sc1 = false;", 4, makeValueBool32(false)),
1078 SpecConstant(3u, "layout(constant_id = ${ID}) const bool sc2 = true;", 4, makeValueBool32(false)),
1079 SpecConstant(4u, "layout(constant_id = ${ID}) const bool sc3 = false;", 4, makeValueBool32(true))),
1080 16,
1081 " bool r0;\n"
1082 " bool r1;\n"
1083 " bool r2;\n"
1084 " bool r3;\n",
1085 "",
1086 " sb_out.r0 = sc0;\n"
1087 " sb_out.r1 = sc1;\n"
1088 " sb_out.r2 = sc2;\n"
1089 " sb_out.r3 = sc3;\n",
1090 makeVector(OffsetValue(4, 0, makeValueBool32(true)), OffsetValue(4, 4, makeValueBool32(false)),
1091 OffsetValue(4, 8, makeValueBool32(false)), OffsetValue(4, 12, makeValueBool32(true))),
1092 (FeatureFlags)0,
1093 false,
1094 },
1095 {
1096 "int8",
1097 makeVector(
1098 SpecConstant(1u, "layout(constant_id = ${ID}) const int8_t sc0 = int8_t(1);", 1, makeValueInt8(127)),
1099 SpecConstant(2u, "layout(constant_id = ${ID}) const int8_t sc1 = int8_t(-2);")),
1100 2,
1101 " int8_t r0;\n"
1102 " int8_t r1;\n",
1103 "",
1104 " int8_t aux = sc0 + sc1;\n"
1105 " sb_out.r0 = sc0;\n"
1106 " sb_out.r1 = sc1;\n",
1107 makeVector(OffsetValue(1, 0, makeValueInt8(127)), OffsetValue(1, 1, makeValueInt8(-2))),
1108 FEATURE_SHADER_INT_8,
1109 false,
1110 },
1111 {
1112 "int8_2",
1113 makeVector(
1114 SpecConstant(1u, "layout(constant_id = ${ID}) const int8_t sc0 = int8_t(123);", 1, makeValueInt8(65)),
1115 SpecConstant(2u, "layout(constant_id = ${ID}) const int8_t sc1 = int8_t(-33);", 1,
1116 makeValueInt8(-128))),
1117 2,
1118 " int8_t r0;\n"
1119 " int8_t r1;\n",
1120 "",
1121 " int8_t aux = sc0 + sc1;\n"
1122 " sb_out.r0 = sc0;\n"
1123 " sb_out.r1 = sc1;\n",
1124 makeVector(OffsetValue(1, 0, makeValueInt8(65)), OffsetValue(1, 1, makeValueInt8(-128))),
1125 FEATURE_SHADER_INT_8,
1126 false,
1127 },
1128 {
1129 "uint8",
1130 makeVector(
1131 SpecConstant(1u, "layout(constant_id = ${ID}) const uint8_t sc0 = int8_t(15);", 1, makeValueUint8(254)),
1132 SpecConstant(2u, "layout(constant_id = ${ID}) const uint8_t sc1 = int8_t(43);")),
1133 2,
1134 " uint8_t r0;\n"
1135 " uint8_t r1;\n",
1136 "",
1137 " uint8_t aux = sc0 + sc1;\n"
1138 " sb_out.r0 = sc0;\n"
1139 " sb_out.r1 = sc1;\n",
1140 makeVector(OffsetValue(1, 0, makeValueUint8(254)), OffsetValue(1, 1, makeValueUint8(43))),
1141 FEATURE_SHADER_INT_8,
1142 false,
1143 },
1144 {
1145 "uint8_2",
1146 makeVector(
1147 SpecConstant(1u, "layout(constant_id = ${ID}) const uint8_t sc0 = int8_t(99);", 1, makeValueUint8(254)),
1148 SpecConstant(2u, "layout(constant_id = ${ID}) const uint8_t sc1 = int8_t(81);", 1,
1149 makeValueUint8(255))),
1150 2,
1151 " uint8_t r0;\n"
1152 " uint8_t r1;\n",
1153 "",
1154 " uint8_t aux = sc0 + sc1;\n"
1155 " sb_out.r0 = sc0;\n"
1156 " sb_out.r1 = sc1;\n",
1157 makeVector(OffsetValue(1, 0, makeValueUint8(254)), OffsetValue(1, 1, makeValueUint8(255))),
1158 FEATURE_SHADER_INT_8,
1159 false,
1160 },
1161 {
1162 "int16",
1163 makeVector(
1164 SpecConstant(1u, "layout(constant_id = ${ID}) const int16_t sc0 = 20000s;", 2, makeValueInt16(32000)),
1165 SpecConstant(2u, "layout(constant_id = ${ID}) const int16_t sc1 = -20000s;")),
1166 4,
1167 " int16_t r0;\n"
1168 " int16_t r1;\n",
1169 "",
1170 " int16_t aux = sc0 + sc1;\n"
1171 " sb_out.r0 = sc0;\n"
1172 " sb_out.r1 = sc1;\n",
1173 makeVector(OffsetValue(2, 0, makeValueInt16(32000)), OffsetValue(2, 2, makeValueInt16(-20000))),
1174 FEATURE_SHADER_INT_16,
1175 false,
1176 },
1177 {
1178 "int16_2",
1179 makeVector(
1180 SpecConstant(1u, "layout(constant_id = ${ID}) const int16_t sc0 = 20000s;", 2, makeValueInt16(32000)),
1181 SpecConstant(2u, "layout(constant_id = ${ID}) const int16_t sc1 = -20000s;", 2,
1182 makeValueInt16(-21000))),
1183 4,
1184 " int16_t r0;\n"
1185 " int16_t r1;\n",
1186 "",
1187 " int16_t aux = sc0 + sc1;\n"
1188 " sb_out.r0 = sc0;\n"
1189 " sb_out.r1 = sc1;\n",
1190 makeVector(OffsetValue(2, 0, makeValueInt16(32000)), OffsetValue(2, 2, makeValueInt16(-21000))),
1191 FEATURE_SHADER_INT_16,
1192 false,
1193 },
1194 {
1195 "uint16",
1196 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint16_t sc0 = 64000us;", 2,
1197 makeValueUint16(65000)),
1198 SpecConstant(2u, "layout(constant_id = ${ID}) const uint16_t sc1 = 51829us;")),
1199 4,
1200 " uint16_t r0;\n"
1201 " uint16_t r1;\n",
1202 "",
1203 " uint16_t aux = sc0 + sc1;\n"
1204 " sb_out.r0 = sc0;\n"
1205 " sb_out.r1 = sc1;\n",
1206 makeVector(OffsetValue(2, 0, makeValueUint16(65000)), OffsetValue(2, 2, makeValueUint16(51829))),
1207 FEATURE_SHADER_INT_16,
1208 false,
1209 },
1210 {
1211 "uint16_2",
1212 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint16_t sc0 = 64000us;", 2,
1213 makeValueUint16(65000)),
1214 SpecConstant(2u, "layout(constant_id = ${ID}) const uint16_t sc1 = 51829us;", 2,
1215 makeValueUint16(63000))),
1216 4,
1217 " uint16_t r0;\n"
1218 " uint16_t r1;\n",
1219 "",
1220 " uint16_t aux = sc0 + sc1;\n"
1221 " sb_out.r0 = sc0;\n"
1222 " sb_out.r1 = sc1;\n",
1223 makeVector(OffsetValue(2, 0, makeValueUint16(65000)), OffsetValue(2, 2, makeValueUint16(63000))),
1224 FEATURE_SHADER_INT_16,
1225 false,
1226 },
1227 {
1228 "int",
1229 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = -3;", 4, makeValueInt32(33)),
1230 SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 91;"),
1231 SpecConstant(3u, "layout(constant_id = ${ID}) const int sc2 = 17;", 4, makeValueInt32(-15))),
1232 12,
1233 " int r0;\n"
1234 " int r1;\n"
1235 " int r2;\n",
1236 "",
1237 " sb_out.r0 = sc0;\n"
1238 " sb_out.r1 = sc1;\n"
1239 " sb_out.r2 = sc2;\n",
1240 makeVector(OffsetValue(4, 0, makeValueInt32(33)), OffsetValue(4, 4, makeValueInt32(91)),
1241 OffsetValue(4, 8, makeValueInt32(-15))),
1242 (FeatureFlags)0,
1243 false,
1244 },
1245 {
1246 "uint",
1247 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint sc0 = 42u;", 4, makeValueUint32(97u)),
1248 SpecConstant(2u, "layout(constant_id = ${ID}) const uint sc1 = 7u;")),
1249 8,
1250 " uint r0;\n"
1251 " uint r1;\n",
1252 "",
1253 " sb_out.r0 = sc0;\n"
1254 " sb_out.r1 = sc1;\n",
1255 makeVector(OffsetValue(4, 0, makeValueUint32(97u)), OffsetValue(4, 4, makeValueUint32(7u))),
1256 (FeatureFlags)0,
1257 false,
1258 },
1259 {
1260 "uint_2",
1261 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint sc0 = 305419896u;", 4,
1262 makeValueUint32(1985229328u)),
1263 SpecConstant(2u, "layout(constant_id = ${ID}) const uint sc1 = 591751049u;"),
1264 SpecConstant(3u, "layout(constant_id = ${ID}) const uint sc2 = 878082202u;", 4,
1265 makeValueUint32(1698898186u))),
1266 12,
1267 " uint r0;\n"
1268 " uint r1;\n"
1269 " uint r2;\n",
1270 "",
1271 " sb_out.r0 = sc0;\n"
1272 " sb_out.r1 = sc1;\n"
1273 " sb_out.r2 = sc2;\n",
1274 makeVector(OffsetValue(4, 0, makeValueUint32(1985229328u)), OffsetValue(4, 4, makeValueUint32(591751049u)),
1275 OffsetValue(4, 8, makeValueUint32(1698898186u))),
1276 (FeatureFlags)0,
1277 false,
1278 },
1279 {
1280 "int64",
1281 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int64_t sc0 = 9141386509785772560l;", 8,
1282 makeValueInt64(9137147825770275585ll)),
1283 SpecConstant(2u, "layout(constant_id = ${ID}) const int64_t sc1 = -9141386509785772560l;")),
1284 16,
1285 " int64_t r0;\n"
1286 " int64_t r1;\n",
1287 "",
1288 " sb_out.r0 = sc0;\n"
1289 " sb_out.r1 = sc1;\n",
1290 makeVector(OffsetValue(8, 0, makeValueInt64(9137147825770275585ll)),
1291 OffsetValue(8, 8, makeValueInt64(-9141386509785772560ll))),
1292 FEATURE_SHADER_INT_64,
1293 false,
1294 },
1295 {
1296 "int64_2",
1297 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int64_t sc0 = 9141386509785772560l;", 8,
1298 makeValueInt64(9137147825770275585ll)),
1299 SpecConstant(2u, "layout(constant_id = ${ID}) const int64_t sc1 = -9141386509785772560l;", 8,
1300 makeValueInt64(-9137164382869201665ll))),
1301 16,
1302 " int64_t r0;\n"
1303 " int64_t r1;\n",
1304 "",
1305 " sb_out.r0 = sc0;\n"
1306 " sb_out.r1 = sc1;\n",
1307 makeVector(OffsetValue(8, 0, makeValueInt64(9137147825770275585ll)),
1308 OffsetValue(8, 8, makeValueInt64(-9137164382869201665ll))),
1309 FEATURE_SHADER_INT_64,
1310 false,
1311 },
1312 {
1313 "uint64",
1314 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint64_t sc0 = 18364758544493064720ul;", 8,
1315 makeValueUint64(17279655951921914625ull)),
1316 SpecConstant(2u, "layout(constant_id = ${ID}) const uint64_t sc1 = 17298946664678735070ul;")),
1317 16,
1318 " uint64_t r0;\n"
1319 " uint64_t r1;\n",
1320 "",
1321 " sb_out.r0 = sc0;\n"
1322 " sb_out.r1 = sc1;\n",
1323 makeVector(OffsetValue(8, 0, makeValueUint64(17279655951921914625ull)),
1324 OffsetValue(8, 8, makeValueUint64(17298946664678735070ull))),
1325 FEATURE_SHADER_INT_64,
1326 false,
1327 },
1328 {
1329 "uint64_2",
1330 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint64_t sc0 = 18364758544493064720ul;", 8,
1331 makeValueUint64(17279655951921914625ull)),
1332 SpecConstant(2u, "layout(constant_id = ${ID}) const uint64_t sc1 = 17298946664678735070ul;", 8,
1333 makeValueUint64(17270123250533606145ull))),
1334 16,
1335 " uint64_t r0;\n"
1336 " uint64_t r1;\n",
1337 "",
1338 " sb_out.r0 = sc0;\n"
1339 " sb_out.r1 = sc1;\n",
1340 makeVector(OffsetValue(8, 0, makeValueUint64(17279655951921914625ull)),
1341 OffsetValue(8, 8, makeValueUint64(17270123250533606145ull))),
1342 FEATURE_SHADER_INT_64,
1343 false,
1344 },
1345 // We create some floating point values below as unsigned integers to make sure all bytes are set to different values, avoiding special patterns and denormals.
1346 {
1347 "float16",
1348 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const float16_t sc0 = 7.5hf;", 2,
1349 makeValueFloat16(tcu::Float16(15.75))),
1350 SpecConstant(2u, "layout(constant_id = ${ID}) const float16_t sc1 = 1.125hf;")),
1351 4,
1352 " float16_t r0;\n"
1353 " float16_t r1;\n",
1354 "",
1355 " float16_t aux = sc0 + sc1;\n"
1356 " sb_out.r0 = sc0;\n"
1357 " sb_out.r1 = sc1;\n",
1358 makeVector(OffsetValue(2, 0, makeValueFloat16(tcu::Float16(15.75))),
1359 OffsetValue(2, 2, makeValueFloat16(tcu::Float16(1.125)))),
1360 FEATURE_SHADER_FLOAT_16,
1361 false,
1362 },
1363 {
1364 "float16_2",
1365 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const float16_t sc0 = 7.5hf;", 2,
1366 makeValueUint16(0x0123u)),
1367 SpecConstant(2u, "layout(constant_id = ${ID}) const float16_t sc1 = 1.125hf;"),
1368 SpecConstant(3u, "layout(constant_id = ${ID}) const float16_t sc2 = 1.125hf;", 2,
1369 makeValueUint16(0xFEDCu))),
1370 6,
1371 " float16_t r0;\n"
1372 " float16_t r1;\n"
1373 " float16_t r2;\n",
1374 "",
1375 " float16_t aux = sc0 + sc1;\n"
1376 " sb_out.r0 = sc0;\n"
1377 " sb_out.r1 = sc1;\n"
1378 " sb_out.r2 = sc2;\n",
1379 makeVector(OffsetValue(2, 0, makeValueUint16(0x0123u)),
1380 OffsetValue(2, 2, makeValueFloat16(tcu::Float16(1.125))),
1381 OffsetValue(2, 4, makeValueUint16(0xFEDCu))),
1382 FEATURE_SHADER_FLOAT_16,
1383 false,
1384 },
1385 {
1386 "float",
1387 makeVector(
1388 SpecConstant(1u, "layout(constant_id = ${ID}) const float sc0 = 7.5;", 4, makeValueFloat32(15.75f)),
1389 SpecConstant(2u, "layout(constant_id = ${ID}) const float sc1 = 1.125;")),
1390 8,
1391 " float r0;\n"
1392 " float r1;\n",
1393 "",
1394 " sb_out.r0 = sc0;\n"
1395 " sb_out.r1 = sc1;\n",
1396 makeVector(OffsetValue(4, 0, makeValueFloat32(15.75f)), OffsetValue(4, 4, makeValueFloat32(1.125f))),
1397 (FeatureFlags)0,
1398 false,
1399 },
1400 {
1401 "float_2",
1402 makeVector(
1403 SpecConstant(1u, "layout(constant_id = ${ID}) const float sc0 = 7.5;", 4, makeValueUint32(0x01234567u)),
1404 SpecConstant(2u, "layout(constant_id = ${ID}) const float sc1 = 1.125;"),
1405 SpecConstant(3u, "layout(constant_id = ${ID}) const float sc2 = 1.125;", 4,
1406 makeValueUint32(0xfedcba98u))),
1407 12,
1408 " float r0;\n"
1409 " float r1;\n"
1410 " float r2;\n",
1411 "",
1412 " sb_out.r0 = sc0;\n"
1413 " sb_out.r1 = sc1;\n"
1414 " sb_out.r2 = sc2;\n",
1415 makeVector(OffsetValue(4, 0, makeValueUint32(0x01234567u)), OffsetValue(4, 4, makeValueFloat32(1.125f)),
1416 OffsetValue(4, 8, makeValueUint32(0xfedcba98u))),
1417 (FeatureFlags)0,
1418 false,
1419 },
1420 {
1421 "double",
1422 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const double sc0 = 2.75LF;", 8,
1423 makeValueUint64(0xFEDCBA9876543210ull)),
1424 SpecConstant(2u, "layout(constant_id = ${ID}) const double sc1 = 9.25LF;")),
1425 16,
1426 " double r0;\n"
1427 " double r1;\n",
1428 "",
1429 " sb_out.r0 = sc0;\n"
1430 " sb_out.r1 = sc1;\n",
1431 makeVector(OffsetValue(8, 0, makeValueUint64(0xFEDCBA9876543210ull)),
1432 OffsetValue(8, 8, makeValueFloat64(9.25))),
1433 FEATURE_SHADER_FLOAT_64,
1434 false,
1435 },
1436 {
1437 "double_2",
1438 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const double sc0 = 2.75LF;", 8,
1439 makeValueUint64(0xFEDCBA9876543210ull)),
1440 SpecConstant(2u, "layout(constant_id = ${ID}) const double sc1 = 9.25LF;", 8,
1441 makeValueUint64(0xEFCDAB8967452301ull))),
1442 16,
1443 " double r0;\n"
1444 " double r1;\n",
1445 "",
1446 " sb_out.r0 = sc0;\n"
1447 " sb_out.r1 = sc1;\n",
1448 makeVector(OffsetValue(8, 0, makeValueUint64(0xFEDCBA9876543210ull)),
1449 OffsetValue(8, 8, makeValueUint64(0xEFCDAB8967452301ull))),
1450 FEATURE_SHADER_FLOAT_64,
1451 false,
1452 },
1453 {
1454 "mixed",
1455 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint8_t sc0 = uint8_t (0);", 1,
1456 makeValueUint8(0x98)),
1457 SpecConstant(2u, "layout(constant_id = ${ID}) const uint16_t sc1 = uint16_t (0);", 2,
1458 makeValueUint16(0x9876)),
1459 SpecConstant(3u, "layout(constant_id = ${ID}) const uint sc2 = uint (0);", 4,
1460 makeValueUint32(0xba987654u)),
1461 SpecConstant(4u, "layout(constant_id = ${ID}) const uint64_t sc3 = uint64_t (0);", 8,
1462 makeValueUint64(0xfedcba9876543210ull))),
1463 8 + 4 + 2 + 1,
1464 " uint64_t r0;\n"
1465 " uint r1;\n"
1466 " uint16_t r2;\n"
1467 " uint8_t r3;\n",
1468 "",
1469 " uint64_t i0 = sc3;\n"
1470 " uint i1 = sc2;\n"
1471 " uint16_t i2 = sc1;\n"
1472 " uint8_t i3 = sc0;\n"
1473 " sb_out.r0 = i0;\n"
1474 " sb_out.r1 = i1;\n"
1475 " sb_out.r2 = i2;\n"
1476 " sb_out.r3 = i3;\n",
1477 makeVector(OffsetValue(8, 0, makeValueUint64(0xfedcba9876543210ull)),
1478 OffsetValue(4, 8, makeValueUint32(0xba987654u)), OffsetValue(2, 12, makeValueUint16(0x9876)),
1479 OffsetValue(1, 14, makeValueUint8(0x98))),
1480 (FEATURE_SHADER_INT_8 | FEATURE_SHADER_INT_16 | FEATURE_SHADER_INT_64),
1481 false,
1482 },
1483 {
1484 "mixed_reversed",
1485 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint64_t sc3 = uint64_t (0);", 8,
1486 makeValueUint64(0xfedcba9876543210ull)),
1487 SpecConstant(2u, "layout(constant_id = ${ID}) const uint sc2 = uint (0);", 4,
1488 makeValueUint32(0xba987654u)),
1489 SpecConstant(3u, "layout(constant_id = ${ID}) const uint16_t sc1 = uint16_t (0);", 2,
1490 makeValueUint16(0x9876)),
1491 SpecConstant(4u, "layout(constant_id = ${ID}) const uint8_t sc0 = uint8_t (0);", 1,
1492 makeValueUint8(0x98))),
1493 8 + 4 + 2 + 1,
1494 " uint64_t r0;\n"
1495 " uint r1;\n"
1496 " uint16_t r2;\n"
1497 " uint8_t r3;\n",
1498 "",
1499 " uint64_t i0 = sc3;\n"
1500 " uint i1 = sc2;\n"
1501 " uint16_t i2 = sc1;\n"
1502 " uint8_t i3 = sc0;\n"
1503 " sb_out.r0 = i0;\n"
1504 " sb_out.r1 = i1;\n"
1505 " sb_out.r2 = i2;\n"
1506 " sb_out.r3 = i3;\n",
1507 makeVector(OffsetValue(8, 0, makeValueUint64(0xfedcba9876543210ull)),
1508 OffsetValue(4, 8, makeValueUint32(0xba987654u)), OffsetValue(2, 12, makeValueUint16(0x9876)),
1509 OffsetValue(1, 14, makeValueUint8(0x98))),
1510 (FEATURE_SHADER_INT_8 | FEATURE_SHADER_INT_16 | FEATURE_SHADER_INT_64),
1511 false,
1512 },
1513 };
1514
1515 for (int i = 0; i < 2; ++i)
1516 {
1517 const bool packData = (i > 0);
1518 for (int defNdx = 0; defNdx < DE_LENGTH_OF_ARRAY(defs); ++defNdx)
1519 {
1520 auto &def = defs[defNdx];
1521 def.packData = packData;
1522 if (packData)
1523 def.name += "_packed";
1524 testGroup->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, def));
1525 }
1526 }
1527
1528 CaseDefinition defsUnusedCases[] = {
1529 {
1530 "unused_single",
1531 makeVector(SpecConstant(0u, "", 0u, GenericValue(), true)),
1532 4,
1533 " int r0;\n",
1534 "",
1535 " sb_out.r0 = 77;\n",
1536 makeVector(OffsetValue(4u, 0u, makeValueInt32(77))),
1537 (FeatureFlags)0,
1538 false,
1539 },
1540 {
1541 "unused_single_packed",
1542 makeVector(SpecConstant(0u, "", 0u, GenericValue(), true),
1543 SpecConstant(1u, "layout(constant_id = ${ID}) const int sc1 = 0;", 4u, makeValueInt32(100))),
1544 4,
1545 " int r1;\n",
1546 "",
1547 " sb_out.r1 = sc1;\n",
1548 makeVector(OffsetValue(4u, 0u, makeValueInt32(100))),
1549 (FeatureFlags)0,
1550 true,
1551 },
1552 {
1553 "unused_multiple",
1554 makeVector(SpecConstant(7u, "layout(constant_id = ${ID}) const int sc0 = 0;", 4u, makeValueInt32(-999)),
1555 SpecConstant(1u, "", 0u, GenericValue(), true),
1556 SpecConstant(17u, "layout(constant_id = ${ID}) const int sc1 = 0;", 4u, makeValueInt32(999)),
1557 SpecConstant(3u, "", 0u, GenericValue(), true)),
1558 8,
1559 " int r0;\n"
1560 " int r1;\n",
1561 "",
1562 " sb_out.r0 = sc0;\n"
1563 " sb_out.r1 = sc1;\n",
1564 makeVector(OffsetValue(4, 0, makeValueInt32(-999)), OffsetValue(4, 4, makeValueInt32(999))),
1565 (FeatureFlags)0,
1566 false,
1567 },
1568 {
1569 "unused_multiple_packed",
1570 makeVector(SpecConstant(7u, "layout(constant_id = ${ID}) const int sc0 = 0;", 4u, makeValueInt32(-999)),
1571 SpecConstant(1u, "", 0u, GenericValue(), true), SpecConstant(3u, "", 0u, GenericValue(), true),
1572 SpecConstant(17u, "layout(constant_id = ${ID}) const int sc1 = 0;", 4u, makeValueInt32(999))),
1573 8,
1574 " int r0;\n"
1575 " int r1;\n",
1576 "",
1577 " sb_out.r0 = sc0;\n"
1578 " sb_out.r1 = sc1;\n",
1579 makeVector(OffsetValue(4, 0, makeValueInt32(-999)), OffsetValue(4, 4, makeValueInt32(999))),
1580 (FeatureFlags)0,
1581 true,
1582 },
1583 };
1584
1585 for (const auto &caseDef : defsUnusedCases)
1586 testGroup->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, caseDef));
1587
1588 return testGroup.release();
1589 }
1590
1591 //! Specify compute shader work group size through specialization constants.
createWorkGroupSizeTests(tcu::TestContext & testCtx)1592 tcu::TestCaseGroup *createWorkGroupSizeTests(tcu::TestContext &testCtx)
1593 {
1594 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "local_size"));
1595
1596 const uint32_t ssboSize = 16;
1597 const std::string ssboDecl = " uvec3 workGroupSize;\n"
1598 " uint checksum;\n";
1599 const std::string globalDecl = "shared uint count;\n";
1600 const std::string mainCode = " count = 0u;\n"
1601 "\n"
1602 " groupMemoryBarrier();\n"
1603 " barrier();\n"
1604 "\n"
1605 " atomicAdd(count, 1u);\n"
1606 "\n"
1607 " groupMemoryBarrier();\n"
1608 " barrier();\n"
1609 "\n"
1610 " sb_out.workGroupSize = gl_WorkGroupSize;\n"
1611 " sb_out.checksum = count;\n";
1612
1613 const CaseDefinition defs[] = {
1614 {
1615 "x",
1616 makeVector(SpecConstant(1u, "layout(local_size_x_id = ${ID}) in;", 4, makeValueUint32(7u))),
1617 ssboSize,
1618 ssboDecl,
1619 globalDecl,
1620 mainCode,
1621 makeVector(OffsetValue(4, 0, makeValueUint32(7u)), OffsetValue(4, 4, makeValueUint32(1u)),
1622 OffsetValue(4, 8, makeValueUint32(1u)), OffsetValue(4, 12, makeValueUint32(7u))),
1623 (FeatureFlags)0,
1624 false,
1625 },
1626 {
1627 "y",
1628 makeVector(SpecConstant(1u, "layout(local_size_y_id = ${ID}) in;", 4, makeValueUint32(5u))),
1629 ssboSize,
1630 ssboDecl,
1631 globalDecl,
1632 mainCode,
1633 makeVector(OffsetValue(4, 0, makeValueUint32(1u)), OffsetValue(4, 4, makeValueUint32(5u)),
1634 OffsetValue(4, 8, makeValueUint32(1u)), OffsetValue(4, 12, makeValueUint32(5u))),
1635 (FeatureFlags)0,
1636 false,
1637 },
1638 {
1639 "z",
1640 makeVector(SpecConstant(1u, "layout(local_size_z_id = ${ID}) in;", 4, makeValueUint32(3u))),
1641 ssboSize,
1642 ssboDecl,
1643 globalDecl,
1644 mainCode,
1645 makeVector(OffsetValue(4, 0, makeValueUint32(1u)), OffsetValue(4, 4, makeValueUint32(1u)),
1646 OffsetValue(4, 8, makeValueUint32(3u)), OffsetValue(4, 12, makeValueUint32(3u))),
1647 (FeatureFlags)0,
1648 false,
1649 },
1650 {
1651 "xy",
1652 makeVector(SpecConstant(1u, "layout(local_size_x_id = ${ID}) in;", 4, makeValueUint32(6u)),
1653 SpecConstant(2u, "layout(local_size_y_id = ${ID}) in;", 4, makeValueUint32(4u))),
1654 ssboSize,
1655 ssboDecl,
1656 globalDecl,
1657 mainCode,
1658 makeVector(OffsetValue(4, 0, makeValueUint32(6u)), OffsetValue(4, 4, makeValueUint32(4u)),
1659 OffsetValue(4, 8, makeValueUint32(1u)), OffsetValue(4, 12, makeValueUint32(6u * 4u))),
1660 (FeatureFlags)0,
1661 false,
1662 },
1663 {
1664 "xz",
1665 makeVector(SpecConstant(1u, "layout(local_size_x_id = ${ID}) in;", 4, makeValueUint32(3u)),
1666 SpecConstant(2u, "layout(local_size_z_id = ${ID}) in;", 4, makeValueUint32(9u))),
1667 ssboSize,
1668 ssboDecl,
1669 globalDecl,
1670 mainCode,
1671 makeVector(OffsetValue(4, 0, makeValueUint32(3u)), OffsetValue(4, 4, makeValueUint32(1u)),
1672 OffsetValue(4, 8, makeValueUint32(9u)), OffsetValue(4, 12, makeValueUint32(3u * 9u))),
1673 (FeatureFlags)0,
1674 false,
1675 },
1676 {
1677 "yz",
1678 makeVector(SpecConstant(1u, "layout(local_size_y_id = ${ID}) in;", 4, makeValueUint32(2u)),
1679 SpecConstant(2u, "layout(local_size_z_id = ${ID}) in;", 4, makeValueUint32(5u))),
1680 ssboSize,
1681 ssboDecl,
1682 globalDecl,
1683 mainCode,
1684 makeVector(OffsetValue(4, 0, makeValueUint32(1u)), OffsetValue(4, 4, makeValueUint32(2u)),
1685 OffsetValue(4, 8, makeValueUint32(5u)), OffsetValue(4, 12, makeValueUint32(2u * 5u))),
1686 (FeatureFlags)0,
1687 false,
1688 },
1689 {
1690 "xyz",
1691 makeVector(SpecConstant(1u, "layout(local_size_x_id = ${ID}) in;", 4, makeValueUint32(3u)),
1692 SpecConstant(2u, "layout(local_size_y_id = ${ID}) in;", 4, makeValueUint32(5u)),
1693 SpecConstant(3u, "layout(local_size_z_id = ${ID}) in;", 4, makeValueUint32(7u))),
1694 ssboSize,
1695 ssboDecl,
1696 globalDecl,
1697 mainCode,
1698 makeVector(OffsetValue(4, 0, makeValueUint32(3u)), OffsetValue(4, 4, makeValueUint32(5u)),
1699 OffsetValue(4, 8, makeValueUint32(7u)), OffsetValue(4, 12, makeValueUint32(3u * 5u * 7u))),
1700 (FeatureFlags)0,
1701 false,
1702 },
1703 };
1704
1705 for (int defNdx = 0; defNdx < DE_LENGTH_OF_ARRAY(defs); ++defNdx)
1706 testGroup->addChild(new SpecConstantTest(testCtx, PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC,
1707 VK_SHADER_STAGE_COMPUTE_BIT, defs[defNdx]));
1708
1709 return testGroup.release();
1710 }
1711
1712 //! Override a built-in variable with specialization constant value.
createBuiltInOverrideTests(tcu::TestContext & testCtx,const PipelineConstructionType pipelineType,const VkShaderStageFlagBits shaderStage)1713 tcu::TestCaseGroup *createBuiltInOverrideTests(tcu::TestContext &testCtx, const PipelineConstructionType pipelineType,
1714 const VkShaderStageFlagBits shaderStage)
1715 {
1716 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "builtin"));
1717
1718 const CaseDefinition defs[] = {
1719 {
1720 "default",
1721 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) gl_MaxImageUnits;")),
1722 4,
1723 " bool ok;\n",
1724 "",
1725 " sb_out.ok = (gl_MaxImageUnits >= 8);\n", // implementation defined, 8 is the minimum
1726 makeVector(OffsetValue(4, 0, makeValueBool32(true))),
1727 (FeatureFlags)0,
1728 false,
1729 },
1730 {
1731 "specialized",
1732 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) gl_MaxImageUnits;", 4, makeValueInt32(12))),
1733 4,
1734 " int maxImageUnits;\n",
1735 "",
1736 " sb_out.maxImageUnits = gl_MaxImageUnits;\n",
1737 makeVector(OffsetValue(4, 0, makeValueInt32(12))),
1738 (FeatureFlags)0,
1739 false,
1740 },
1741 };
1742
1743 for (int defNdx = 0; defNdx < DE_LENGTH_OF_ARRAY(defs); ++defNdx)
1744 testGroup->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, defs[defNdx]));
1745
1746 return testGroup.release();
1747 }
1748
1749 //! Specialization constants used in expressions.
createExpressionTests(tcu::TestContext & testCtx,const PipelineConstructionType pipelineType,const VkShaderStageFlagBits shaderStage)1750 tcu::TestCaseGroup *createExpressionTests(tcu::TestContext &testCtx, const PipelineConstructionType pipelineType,
1751 const VkShaderStageFlagBits shaderStage)
1752 {
1753 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "expression"));
1754
1755 const CaseDefinition defs[] = {
1756 {
1757 "spec_const_expression",
1758 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 2;"),
1759 SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 3;", 4, makeValueInt32(5))),
1760 4,
1761 " int result;\n",
1762
1763 "const int expr0 = sc0 + 1;\n"
1764 "const int expr1 = sc0 + sc1;\n",
1765
1766 " sb_out.result = expr0 + expr1;\n",
1767 makeVector(OffsetValue(4, 0, makeValueInt32(10))),
1768 (FeatureFlags)0,
1769 false,
1770 },
1771 {
1772 "array_size",
1773 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 1;"),
1774 SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 2;", 4, makeValueInt32(3))),
1775 16,
1776 " int r0;\n"
1777 " int r1[3];\n",
1778
1779 "",
1780
1781 " int a0[sc0];\n"
1782 " int a1[sc1];\n"
1783 "\n"
1784 " for (int i = 0; i < sc0; ++i)\n"
1785 " a0[i] = sc0 - i;\n"
1786 " for (int i = 0; i < sc1; ++i)\n"
1787 " a1[i] = sc1 - i;\n"
1788 "\n"
1789 " sb_out.r0 = a0[0];\n"
1790 " for (int i = 0; i < sc1; ++i)\n"
1791 " sb_out.r1[i] = a1[i];\n",
1792 makeVector(OffsetValue(4, 0, makeValueInt32(1)), OffsetValue(4, 4, makeValueInt32(3)),
1793 OffsetValue(4, 8, makeValueInt32(2)), OffsetValue(4, 12, makeValueInt32(1))),
1794 (FeatureFlags)0,
1795 false,
1796 },
1797 {
1798 "array_size_expression",
1799 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 3;"),
1800 SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 5;", 4, makeValueInt32(7))),
1801 8,
1802 " int r0;\n"
1803 " int r1;\n",
1804
1805 "",
1806
1807 " int a0[sc0 + 3];\n"
1808 " int a1[sc0 + sc1];\n"
1809 "\n"
1810 " const int size0 = sc0 + 3;\n"
1811 " const int size1 = sc0 + sc1;\n"
1812 "\n"
1813 " for (int i = 0; i < size0; ++i)\n"
1814 " a0[i] = 3 - i;\n"
1815 " for (int i = 0; i < size1; ++i)\n"
1816 " a1[i] = 5 - i;\n"
1817 "\n"
1818 " sb_out.r0 = a0[size0 - 1];\n"
1819 " sb_out.r1 = a1[size1 - 1];\n",
1820 makeVector(OffsetValue(4, 0, makeValueInt32(-2)), OffsetValue(4, 4, makeValueInt32(-4))),
1821 (FeatureFlags)0,
1822 false,
1823 },
1824 {
1825 "array_size_spec_const_expression",
1826 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 3;"),
1827 SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 5;", 4, makeValueInt32(7))),
1828 8,
1829 " int r0;\n"
1830 " int r1;\n",
1831
1832 "",
1833
1834 " const int size0 = sc0 + 3;\n"
1835 " const int size1 = sc0 + sc1;\n"
1836 "\n"
1837 " int a0[size0];\n"
1838 " int a1[size1];\n"
1839 "\n"
1840 " for (int i = 0; i < size0; ++i)\n"
1841 " a0[i] = 3 - i;\n"
1842 " for (int i = 0; i < size1; ++i)\n"
1843 " a1[i] = 5 - i;\n"
1844 "\n"
1845 " sb_out.r0 = a0[size0 - 1];\n"
1846 " sb_out.r1 = a1[size1 - 1];\n",
1847 makeVector(OffsetValue(4, 0, makeValueInt32(-2)), OffsetValue(4, 4, makeValueInt32(-4))),
1848 (FeatureFlags)0,
1849 false,
1850 },
1851 {
1852 "array_size_length",
1853 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 1;"),
1854 SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 2;", 4, makeValueInt32(4))),
1855 8,
1856 " int r0;\n"
1857 " int r1;\n",
1858
1859 "",
1860
1861 " int a0[sc0];\n"
1862 " int a1[sc1];\n"
1863 "\n"
1864 " sb_out.r0 = a0.length();\n"
1865 " sb_out.r1 = a1.length();\n",
1866 makeVector(OffsetValue(4, 0, makeValueInt32(1)), OffsetValue(4, 4, makeValueInt32(4))),
1867 (FeatureFlags)0,
1868 false,
1869 },
1870 {
1871 "array_size_pass_to_function",
1872 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 3;"),
1873 SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 1;", 4, makeValueInt32(3))),
1874 4,
1875 " int result;\n",
1876
1877 "int sumArrays (int a0[sc0], int a1[sc1])\n"
1878 "{\n"
1879 " int sum = 0;\n"
1880 " for (int i = 0; (i < sc0) && (i < sc1); ++i)\n"
1881 " sum += a0[i] + a1[i];\n"
1882 " return sum;\n"
1883 "}\n",
1884
1885 " int a0[sc0];\n"
1886 " int a1[sc1];\n"
1887 "\n"
1888 " for (int i = 0; i < sc0; ++i)\n"
1889 " a0[i] = i + 1;\n"
1890 " for (int i = 0; i < sc1; ++i)\n"
1891 " a1[i] = i + 2;\n"
1892 "\n"
1893 " sb_out.result = sumArrays(a0, a1);\n",
1894 makeVector(OffsetValue(4, 0, makeValueInt32(15))),
1895 (FeatureFlags)0,
1896 false,
1897 },
1898 };
1899
1900 for (int defNdx = 0; defNdx < DE_LENGTH_OF_ARRAY(defs); ++defNdx)
1901 testGroup->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, defs[defNdx]));
1902
1903 return testGroup.release();
1904 }
1905
1906 //! Helper functions internal to make*CompositeCaseDefinition functions.
1907 namespace composite_case_internal
1908 {
1909
1910 //! Generate a string like this: "1, 2, sc0, 4" or "true, true, sc0"
1911 //! castToType = true is useful when type requires more initializer values than we are providing, e.g.:
1912 //! vec2(1), vec2(sc0), vec(3)
generateInitializerListWithSpecConstant(const glu::DataType type,const bool castToType,const int idxBegin,const int idxEnd,const std::string & specConstName,const int specConstNdx)1913 std::string generateInitializerListWithSpecConstant(const glu::DataType type, const bool castToType, const int idxBegin,
1914 const int idxEnd, const std::string &specConstName,
1915 const int specConstNdx)
1916 {
1917 std::ostringstream str;
1918
1919 for (int i = idxBegin; i < idxEnd; ++i)
1920 {
1921 const std::string iVal = (i == specConstNdx ? specConstName :
1922 glu::getDataTypeScalarType(type) == glu::TYPE_BOOL ? "true" :
1923 de::toString(i + 1));
1924 str << (i != idxBegin ? ", " : "")
1925 << (castToType ? de::toString(glu::getDataTypeName(type)) + "(" + iVal + ")" : iVal);
1926 }
1927
1928 return str.str();
1929 }
1930
generateArrayConstructorString(const glu::DataType elemType,const int size1,const int size2,const std::string & specConstName,const int specConstNdx)1931 std::string generateArrayConstructorString(const glu::DataType elemType, const int size1, const int size2,
1932 const std::string &specConstName, const int specConstNdx)
1933 {
1934 const bool isArrayOfArray = (size2 > 0);
1935 const bool doCast = (!isDataTypeScalar(elemType));
1936
1937 std::ostringstream arrayCtorExpr;
1938
1939 if (isArrayOfArray)
1940 {
1941 const std::string padding(36, ' ');
1942 int idxBegin = 0;
1943 int idxEnd = size2;
1944
1945 for (int iterNdx = 0; iterNdx < size1; ++iterNdx)
1946 {
1947 // Open sub-array ctor
1948 arrayCtorExpr << (iterNdx != 0 ? ",\n" + padding : "") << glu::getDataTypeName(elemType) << "[" << size2
1949 << "](";
1950
1951 // Sub-array constructor elements
1952 arrayCtorExpr << generateInitializerListWithSpecConstant(elemType, doCast, idxBegin, idxEnd, specConstName,
1953 specConstNdx);
1954
1955 // Close sub-array ctor, move to next range
1956 arrayCtorExpr << ")";
1957
1958 idxBegin += size2;
1959 idxEnd += size2;
1960 }
1961 }
1962 else
1963 {
1964 // Array constructor elements
1965 arrayCtorExpr << generateInitializerListWithSpecConstant(elemType, doCast, 0, size1, specConstName,
1966 specConstNdx);
1967 }
1968
1969 return arrayCtorExpr.str();
1970 }
1971
makeValue(const glu::DataType type,const int specValue)1972 inline GenericValue makeValue(const glu::DataType type, const int specValue)
1973 {
1974 if (type == glu::TYPE_DOUBLE)
1975 return makeValueFloat64(static_cast<double>(specValue));
1976 else if (type == glu::TYPE_FLOAT)
1977 return makeValueFloat32(static_cast<float>(specValue));
1978 else
1979 return makeValueInt32(specValue);
1980 }
1981
getDataTypeScalarSizeBytes(const glu::DataType dataType)1982 uint32_t getDataTypeScalarSizeBytes(const glu::DataType dataType)
1983 {
1984 switch (getDataTypeScalarType(dataType))
1985 {
1986 case glu::TYPE_FLOAT:
1987 case glu::TYPE_INT:
1988 case glu::TYPE_UINT:
1989 case glu::TYPE_BOOL:
1990 return 4;
1991
1992 case glu::TYPE_DOUBLE:
1993 return 8;
1994
1995 default:
1996 DE_ASSERT(false);
1997 return 0;
1998 }
1999 }
2000
2001 //! This applies to matrices/vectors/array cases. dataType must be a basic type.
computeExpectedValues(const int specValue,const glu::DataType dataType,const int numCombinations)2002 std::vector<OffsetValue> computeExpectedValues(const int specValue, const glu::DataType dataType,
2003 const int numCombinations)
2004 {
2005 DE_ASSERT(glu::isDataTypeScalar(dataType));
2006
2007 std::vector<OffsetValue> expectedValues;
2008
2009 for (int combNdx = 0; combNdx < numCombinations; ++combNdx)
2010 {
2011 int sum = 0;
2012 for (int i = 0; i < numCombinations; ++i)
2013 sum += (i == combNdx ? specValue : dataType == glu::TYPE_BOOL ? 1 : (i + 1));
2014
2015 const int dataSize = getDataTypeScalarSizeBytes(dataType);
2016 expectedValues.push_back(OffsetValue(dataSize, dataSize * combNdx, makeValue(dataType, sum)));
2017 }
2018
2019 return expectedValues;
2020 }
2021
getFirstDataElementSubscriptString(const glu::DataType type)2022 inline std::string getFirstDataElementSubscriptString(const glu::DataType type)
2023 {
2024 // Grab the first element of a matrix/vector, if dealing with non-basic types.
2025 return (isDataTypeMatrix(type) ? "[0][0]" : isDataTypeVector(type) ? "[0]" : "");
2026 }
2027
2028 //! This code will go into the main function.
generateShaderChecksumComputationCode(const glu::DataType elemType,const std::string & varName,const std::string & accumType,const int size1,const int size2,const int numCombinations)2029 std::string generateShaderChecksumComputationCode(const glu::DataType elemType, const std::string &varName,
2030 const std::string &accumType, const int size1, const int size2,
2031 const int numCombinations)
2032 {
2033 std::ostringstream mainCode;
2034
2035 // Generate main code to calculate checksums for each array
2036 for (int combNdx = 0; combNdx < numCombinations; ++combNdx)
2037 mainCode << " " << accumType << " sum_" << varName << combNdx << " = " << accumType << "(0);\n";
2038
2039 if (size2 > 0)
2040 {
2041 mainCode << "\n"
2042 << " for (int i = 0; i < " << size1 << "; ++i)\n"
2043 << " for (int j = 0; j < " << size2 << "; ++j)\n"
2044 << " {\n";
2045
2046 for (int combNdx = 0; combNdx < numCombinations; ++combNdx)
2047 mainCode << " sum_" << varName << combNdx << " += " << accumType << "(" << varName << combNdx
2048 << "[i][j]" << getFirstDataElementSubscriptString(elemType) << ");\n";
2049 }
2050 else
2051 {
2052 mainCode << "\n"
2053 << " for (int i = 0; i < " << size1 << "; ++i)\n"
2054 << " {\n";
2055
2056 for (int combNdx = 0; combNdx < numCombinations; ++combNdx)
2057 mainCode << " sum_" << varName << combNdx << " += " << accumType << "(" << varName << combNdx
2058 << "[i]" << getFirstDataElementSubscriptString(elemType) << ");\n";
2059 }
2060
2061 mainCode << " }\n"
2062 << "\n";
2063
2064 for (int combNdx = 0; combNdx < numCombinations; ++combNdx)
2065 mainCode << " sb_out.result[" << combNdx << "] = sum_" << varName << combNdx << ";\n";
2066
2067 return mainCode.str();
2068 }
2069
makeSpecConstant(const std::string specConstName,const uint32_t specConstId,const glu::DataType type,const int specValue)2070 SpecConstant makeSpecConstant(const std::string specConstName, const uint32_t specConstId, const glu::DataType type,
2071 const int specValue)
2072 {
2073 DE_ASSERT(glu::isDataTypeScalar(type));
2074
2075 const std::string typeName(glu::getDataTypeName(type));
2076
2077 return SpecConstant(
2078 specConstId, "layout(constant_id = ${ID}) const " + typeName + " " + specConstName + " = " + typeName + "(1);",
2079 getDataTypeScalarSizeBytes(type), makeValue(type, specValue));
2080 }
2081
2082 } // namespace composite_case_internal
2083
2084 //! Generate a CaseDefinition for a composite test using a matrix or vector (a 1-column matrix)
makeMatrixVectorCompositeCaseDefinition(const glu::DataType type)2085 CaseDefinition makeMatrixVectorCompositeCaseDefinition(const glu::DataType type)
2086 {
2087 using namespace composite_case_internal;
2088
2089 DE_ASSERT(!glu::isDataTypeScalar(type));
2090
2091 const std::string varName = (glu::isDataTypeMatrix(type) ? "m" : "v");
2092 const int numCombinations = getDataTypeScalarSize(type);
2093 const glu::DataType scalarType = glu::getDataTypeScalarType(type);
2094 const std::string typeName = glu::getDataTypeName(type);
2095 const bool isConst = (scalarType != glu::TYPE_FLOAT) && (scalarType != glu::TYPE_DOUBLE);
2096
2097 std::ostringstream globalCode;
2098 {
2099 // Build N matrices/vectors with specialization constant inserted at various locations in the constructor.
2100 for (int combNdx = 0; combNdx < numCombinations; ++combNdx)
2101 globalCode << (isConst ? "const " : "") << typeName << " " << varName << combNdx << " = " << typeName << "("
2102 << generateInitializerListWithSpecConstant(type, false, 0, numCombinations, "sc0", combNdx)
2103 << ");\n";
2104 }
2105
2106 const bool isBoolElement = (scalarType == glu::TYPE_BOOL);
2107 const int specValue = (isBoolElement ? 0 : 42);
2108 const std::string accumType = glu::getDataTypeName(isBoolElement ? glu::TYPE_INT : scalarType);
2109
2110 const int size1 =
2111 glu::isDataTypeMatrix(type) ? glu::getDataTypeMatrixNumColumns(type) : glu::getDataTypeNumComponents(type);
2112 const int size2 = glu::isDataTypeMatrix(type) ? glu::getDataTypeMatrixNumRows(type) : 0;
2113
2114 const CaseDefinition def = {
2115 typeName,
2116 makeVector(makeSpecConstant("sc0", 1u, scalarType, specValue)),
2117 static_cast<VkDeviceSize>(getDataTypeScalarSizeBytes(type) * numCombinations),
2118 " " + accumType + " result[" + de::toString(numCombinations) + "];\n",
2119 globalCode.str(),
2120 generateShaderChecksumComputationCode(scalarType, varName, accumType, size1, size2, numCombinations),
2121 computeExpectedValues(specValue, scalarType, numCombinations),
2122 (scalarType == glu::TYPE_DOUBLE ? (FeatureFlags)FEATURE_SHADER_FLOAT_64 : (FeatureFlags)0),
2123 false,
2124 };
2125 return def;
2126 }
2127
2128 //! Generate a CaseDefinition for a composite test using an array, or an array of array.
2129 //! If (size1, size2) = (N, 0) -> type array[N]
2130 //! = (N, M) -> type array[N][M]
makeArrayCompositeCaseDefinition(const glu::DataType elemType,const int size1,const int size2=0)2131 CaseDefinition makeArrayCompositeCaseDefinition(const glu::DataType elemType, const int size1, const int size2 = 0)
2132 {
2133 using namespace composite_case_internal;
2134
2135 DE_ASSERT(size1 > 0);
2136
2137 const bool isArrayOfArray = (size2 > 0);
2138 const std::string varName = "a";
2139 const std::string arraySizeDecl =
2140 "[" + de::toString(size1) + "]" + (isArrayOfArray ? "[" + de::toString(size2) + "]" : "");
2141 const int numCombinations = (isArrayOfArray ? size1 * size2 : size1);
2142 const std::string elemTypeName(glu::getDataTypeName(elemType));
2143
2144 std::ostringstream globalCode;
2145 {
2146 // Create several arrays with specialization constant inserted in different positions.
2147 for (int combNdx = 0; combNdx < numCombinations; ++combNdx)
2148 globalCode << elemTypeName << " " << varName << combNdx << arraySizeDecl << " = " << elemTypeName
2149 << arraySizeDecl << "(" << generateArrayConstructorString(elemType, size1, size2, "sc0", combNdx)
2150 << ");\n";
2151 }
2152
2153 const glu::DataType scalarType = glu::getDataTypeScalarType(elemType);
2154 const bool isBoolData = (scalarType == glu::TYPE_BOOL);
2155 const int specValue = (isBoolData ? 0 : 19);
2156 const std::string caseName = (isArrayOfArray ? "array_" : "") + elemTypeName;
2157 const std::string accumType = (glu::getDataTypeName(isBoolData ? glu::TYPE_INT : scalarType));
2158
2159 const CaseDefinition def = {
2160 caseName,
2161 makeVector(makeSpecConstant("sc0", 1u, scalarType, specValue)),
2162 static_cast<VkDeviceSize>(getDataTypeScalarSizeBytes(elemType) * numCombinations),
2163 " " + accumType + " result[" + de::toString(numCombinations) + "];\n",
2164 globalCode.str(),
2165 generateShaderChecksumComputationCode(elemType, varName, accumType, size1, size2, numCombinations),
2166 computeExpectedValues(specValue, scalarType, numCombinations),
2167 (scalarType == glu::TYPE_DOUBLE ? (FeatureFlags)FEATURE_SHADER_FLOAT_64 : (FeatureFlags)0),
2168 false,
2169 };
2170 return def;
2171 }
2172
2173 //! A basic struct case, where one member is a specialization constant, or a specialization constant composite
2174 //! (a matrix/vector with a spec. const. element).
makeStructCompositeCaseDefinition(const glu::DataType memberType)2175 CaseDefinition makeStructCompositeCaseDefinition(const glu::DataType memberType)
2176 {
2177 using namespace composite_case_internal;
2178
2179 std::ostringstream globalCode;
2180 {
2181 globalCode << "struct Data {\n"
2182 << " int i;\n"
2183 << " float f;\n"
2184 << " bool b;\n"
2185 << " " << glu::getDataTypeName(memberType) << " sc;\n"
2186 << " uint ui;\n"
2187 << "};\n"
2188 << "\n"
2189 << "Data s0 = Data(3, 2.0, true, " << glu::getDataTypeName(memberType) << "(sc0), 8u);\n";
2190 }
2191
2192 const glu::DataType scalarType = glu::getDataTypeScalarType(memberType);
2193 const bool isBoolData = (scalarType == glu::TYPE_BOOL);
2194 const int specValue = (isBoolData ? 0 : 23);
2195 const int checksum = (3 + 2 + 1 + specValue + 8); // matches the shader code
2196 const glu::DataType accumType = (isBoolData ? glu::TYPE_INT : scalarType);
2197 const std::string accumTypeStr = glu::getDataTypeName(accumType);
2198
2199 std::ostringstream mainCode;
2200 {
2201 mainCode << " " << accumTypeStr << " sum_s0 = " << accumTypeStr << "(0);\n"
2202 << "\n"
2203 << " sum_s0 += " << accumTypeStr << "(s0.i);\n"
2204 << " sum_s0 += " << accumTypeStr << "(s0.f);\n"
2205 << " sum_s0 += " << accumTypeStr << "(s0.b);\n"
2206 << " sum_s0 += " << accumTypeStr << "(s0.sc" << getFirstDataElementSubscriptString(memberType)
2207 << ");\n"
2208 << " sum_s0 += " << accumTypeStr << "(s0.ui);\n"
2209 << "\n"
2210 << " sb_out.result = sum_s0;\n";
2211 }
2212
2213 const std::string caseName = glu::getDataTypeName(memberType);
2214
2215 const CaseDefinition def = {
2216 caseName,
2217 makeVector(makeSpecConstant("sc0", 1u, scalarType, specValue)),
2218 getDataTypeScalarSizeBytes(accumType),
2219 " " + accumTypeStr + " result;\n",
2220 globalCode.str(),
2221 mainCode.str(),
2222 makeVector(OffsetValue(getDataTypeScalarSizeBytes(memberType), 0, makeValue(scalarType, checksum))),
2223 (scalarType == glu::TYPE_DOUBLE ? (FeatureFlags)FEATURE_SHADER_FLOAT_64 : (FeatureFlags)0),
2224 false,
2225 };
2226 return def;
2227 }
2228
2229 //! Specialization constants used in composites.
createCompositeTests(tcu::TestContext & testCtx,const PipelineConstructionType pipelineType,const VkShaderStageFlagBits shaderStage)2230 tcu::TestCaseGroup *createCompositeTests(tcu::TestContext &testCtx, const PipelineConstructionType pipelineType,
2231 const VkShaderStageFlagBits shaderStage)
2232 {
2233 de::MovePtr<tcu::TestCaseGroup> compositeTests(new tcu::TestCaseGroup(testCtx, "composite"));
2234
2235 // Vectors
2236 {
2237 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "vector"));
2238
2239 const glu::DataType types[] = {
2240 glu::TYPE_FLOAT_VEC2, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT_VEC4,
2241
2242 glu::TYPE_DOUBLE_VEC2, glu::TYPE_DOUBLE_VEC3, glu::TYPE_DOUBLE_VEC4,
2243
2244 glu::TYPE_BOOL_VEC2, glu::TYPE_BOOL_VEC3, glu::TYPE_BOOL_VEC4,
2245
2246 glu::TYPE_INT_VEC2, glu::TYPE_INT_VEC3, glu::TYPE_INT_VEC4,
2247
2248 glu::TYPE_UINT_VEC2, glu::TYPE_UINT_VEC3, glu::TYPE_UINT_VEC4,
2249 };
2250 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); ++typeNdx)
2251 group->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage,
2252 makeMatrixVectorCompositeCaseDefinition(types[typeNdx])));
2253
2254 compositeTests->addChild(group.release());
2255 }
2256
2257 // Matrices
2258 {
2259 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "matrix"));
2260
2261 const glu::DataType types[] = {
2262 glu::TYPE_FLOAT_MAT2, glu::TYPE_FLOAT_MAT2X3, glu::TYPE_FLOAT_MAT2X4,
2263 glu::TYPE_FLOAT_MAT3X2, glu::TYPE_FLOAT_MAT3, glu::TYPE_FLOAT_MAT3X4,
2264 glu::TYPE_FLOAT_MAT4X2, glu::TYPE_FLOAT_MAT4X3, glu::TYPE_FLOAT_MAT4,
2265
2266 glu::TYPE_DOUBLE_MAT2, glu::TYPE_DOUBLE_MAT2X3, glu::TYPE_DOUBLE_MAT2X4,
2267 glu::TYPE_DOUBLE_MAT3X2, glu::TYPE_DOUBLE_MAT3, glu::TYPE_DOUBLE_MAT3X4,
2268 glu::TYPE_DOUBLE_MAT4X2, glu::TYPE_DOUBLE_MAT4X3, glu::TYPE_DOUBLE_MAT4,
2269 };
2270 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); ++typeNdx)
2271 group->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage,
2272 makeMatrixVectorCompositeCaseDefinition(types[typeNdx])));
2273
2274 compositeTests->addChild(group.release());
2275 }
2276
2277 const glu::DataType allTypes[] = {
2278 glu::TYPE_FLOAT, glu::TYPE_FLOAT_VEC2, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT_VEC4,
2279 glu::TYPE_FLOAT_MAT2, glu::TYPE_FLOAT_MAT2X3, glu::TYPE_FLOAT_MAT2X4, glu::TYPE_FLOAT_MAT3X2,
2280 glu::TYPE_FLOAT_MAT3, glu::TYPE_FLOAT_MAT3X4, glu::TYPE_FLOAT_MAT4X2, glu::TYPE_FLOAT_MAT4X3,
2281 glu::TYPE_FLOAT_MAT4,
2282
2283 glu::TYPE_DOUBLE, glu::TYPE_DOUBLE_VEC2, glu::TYPE_DOUBLE_VEC3, glu::TYPE_DOUBLE_VEC4,
2284 glu::TYPE_DOUBLE_MAT2, glu::TYPE_DOUBLE_MAT2X3, glu::TYPE_DOUBLE_MAT2X4, glu::TYPE_DOUBLE_MAT3X2,
2285 glu::TYPE_DOUBLE_MAT3, glu::TYPE_DOUBLE_MAT3X4, glu::TYPE_DOUBLE_MAT4X2, glu::TYPE_DOUBLE_MAT4X3,
2286 glu::TYPE_DOUBLE_MAT4,
2287
2288 glu::TYPE_INT, glu::TYPE_INT_VEC2, glu::TYPE_INT_VEC3, glu::TYPE_INT_VEC4,
2289
2290 glu::TYPE_UINT, glu::TYPE_UINT_VEC2, glu::TYPE_UINT_VEC3, glu::TYPE_UINT_VEC4,
2291
2292 glu::TYPE_BOOL, glu::TYPE_BOOL_VEC2, glu::TYPE_BOOL_VEC3, glu::TYPE_BOOL_VEC4,
2293 };
2294
2295 // Array cases
2296 {
2297 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "array"));
2298
2299 // Array of T
2300 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(allTypes); ++typeNdx)
2301 group->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage,
2302 makeArrayCompositeCaseDefinition(allTypes[typeNdx], 3)));
2303
2304 // Array of array of T
2305 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(allTypes); ++typeNdx)
2306 group->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage,
2307 makeArrayCompositeCaseDefinition(allTypes[typeNdx], 3, 2)));
2308
2309 // Special case - array of struct
2310 {
2311 const int checksum = (3 + 2 + 1) + (1 + 5 + 1) + (1 + 2 + 0);
2312 const CaseDefinition def = {
2313 "struct",
2314 makeVector(
2315 SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 1;", 4, makeValueInt32(3)),
2316 SpecConstant(2u, "layout(constant_id = ${ID}) const float sc1 = 1.0;", 4, makeValueFloat32(5.0f)),
2317 SpecConstant(3u, "layout(constant_id = ${ID}) const bool sc2 = true;", 4, makeValueBool32(false))),
2318 4,
2319 " int result;\n",
2320
2321 "struct Data {\n"
2322 " int x;\n"
2323 " float y;\n"
2324 " bool z;\n"
2325 "};\n"
2326 "\n"
2327 "Data a0[3] = Data[3](Data(sc0, 2.0, true), Data(1, sc1, true), Data(1, 2.0, sc2));\n",
2328
2329 " int sum_a0 = 0;\n"
2330 "\n"
2331 " for (int i = 0; i < 3; ++i)\n"
2332 " sum_a0 += int(a0[i].x) + int(a0[i].y) + int(a0[i].z);\n"
2333 "\n"
2334 " sb_out.result = sum_a0;\n",
2335
2336 makeVector(OffsetValue(4, 0, makeValueInt32(checksum))),
2337 (FeatureFlags)0,
2338 false,
2339 };
2340
2341 group->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, def));
2342 }
2343
2344 compositeTests->addChild(group.release());
2345 }
2346
2347 // Struct cases
2348 {
2349 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "struct"));
2350
2351 // Struct with one member being a specialization constant (or spec. const. composite) of a given type
2352 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(allTypes); ++typeNdx)
2353 group->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage,
2354 makeStructCompositeCaseDefinition(allTypes[typeNdx])));
2355
2356 // Special case - struct with array
2357 {
2358 const int checksum = (1 + 2 + 31 + 4 + 0);
2359 const CaseDefinition def = {
2360 "array",
2361 makeVector(
2362 SpecConstant(1u, "layout(constant_id = ${ID}) const float sc0 = 1.0;", 4, makeValueFloat32(31.0f))),
2363 4,
2364 " float result;\n",
2365
2366 "struct Data {\n"
2367 " int i;\n"
2368 " vec3 sc[3];\n"
2369 " bool b;\n"
2370 "};\n"
2371 "\n"
2372 "Data s0 = Data(1, vec3[3](vec3(2.0), vec3(sc0), vec3(4.0)), false);\n",
2373
2374 " float sum_s0 = 0;\n"
2375 "\n"
2376 " sum_s0 += float(s0.i);\n"
2377 " sum_s0 += float(s0.sc[0][0]);\n"
2378 " sum_s0 += float(s0.sc[1][0]);\n"
2379 " sum_s0 += float(s0.sc[2][0]);\n"
2380 " sum_s0 += float(s0.b);\n"
2381 "\n"
2382 " sb_out.result = sum_s0;\n",
2383
2384 makeVector(OffsetValue(4, 0, makeValueFloat32(static_cast<float>(checksum)))),
2385 (FeatureFlags)0,
2386 false,
2387 };
2388
2389 group->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, def));
2390 }
2391
2392 // Special case - struct of struct
2393 {
2394 const int checksum = (1 + 2 + 11 + 4 + 1);
2395 const CaseDefinition def = {
2396 "struct",
2397 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 1;", 4, makeValueInt32(11))),
2398 4,
2399 " int result;\n",
2400
2401 "struct Nested {\n"
2402 " vec2 v;\n"
2403 " int sc;\n"
2404 " float f;\n"
2405 "};\n"
2406 "\n"
2407 "struct Data {\n"
2408 " uint ui;\n"
2409 " Nested s;\n"
2410 " bool b;\n"
2411 "};\n"
2412 "\n"
2413 "Data s0 = Data(1u, Nested(vec2(2.0), sc0, 4.0), true);\n",
2414
2415 " int sum_s0 = 0;\n"
2416 "\n"
2417 " sum_s0 += int(s0.ui);\n"
2418 " sum_s0 += int(s0.s.v[0]);\n"
2419 " sum_s0 += int(s0.s.sc);\n"
2420 " sum_s0 += int(s0.s.f);\n"
2421 " sum_s0 += int(s0.b);\n"
2422 "\n"
2423 " sb_out.result = sum_s0;\n",
2424
2425 makeVector(OffsetValue(4, 0, makeValueInt32(checksum))),
2426 (FeatureFlags)0,
2427 false,
2428 };
2429
2430 group->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, def));
2431 }
2432
2433 compositeTests->addChild(group.release());
2434 }
2435
2436 return compositeTests.release();
2437 }
2438
2439 } // namespace
2440
createSpecConstantTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineType)2441 tcu::TestCaseGroup *createSpecConstantTests(tcu::TestContext &testCtx, PipelineConstructionType pipelineType)
2442 {
2443 de::MovePtr<tcu::TestCaseGroup> allTests(new tcu::TestCaseGroup(testCtx, "spec_constant"));
2444 de::MovePtr<tcu::TestCaseGroup> graphicsGroup(new tcu::TestCaseGroup(testCtx, "graphics"));
2445
2446 struct StageDef
2447 {
2448 tcu::TestCaseGroup *parentGroup;
2449 const char *name;
2450 VkShaderStageFlagBits stage;
2451 };
2452
2453 const StageDef stages[] = {
2454 {graphicsGroup.get(), "vertex", VK_SHADER_STAGE_VERTEX_BIT},
2455 {graphicsGroup.get(), "fragment", VK_SHADER_STAGE_FRAGMENT_BIT},
2456 {graphicsGroup.get(), "tess_control", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT},
2457 {graphicsGroup.get(), "tess_eval", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT},
2458 {graphicsGroup.get(), "geometry", VK_SHADER_STAGE_GEOMETRY_BIT},
2459 {allTests.get(), "compute", VK_SHADER_STAGE_COMPUTE_BIT},
2460 };
2461
2462 allTests->addChild(graphicsGroup.release());
2463
2464 for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
2465 {
2466 const StageDef &stage = stages[stageNdx];
2467 const bool isCompute = (stage.stage == VK_SHADER_STAGE_COMPUTE_BIT);
2468
2469 if (isCompute && (pipelineType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC))
2470 continue;
2471
2472 de::MovePtr<tcu::TestCaseGroup> stageGroup(new tcu::TestCaseGroup(testCtx, stage.name));
2473
2474 stageGroup->addChild(createDefaultValueTests(testCtx, pipelineType, stage.stage));
2475 stageGroup->addChild(createBasicSpecializationTests(testCtx, pipelineType, stage.stage));
2476 stageGroup->addChild(createBuiltInOverrideTests(testCtx, pipelineType, stage.stage));
2477 stageGroup->addChild(createExpressionTests(testCtx, pipelineType, stage.stage));
2478 stageGroup->addChild(createCompositeTests(testCtx, pipelineType, stage.stage));
2479
2480 if (isCompute)
2481 stageGroup->addChild(createWorkGroupSizeTests(testCtx));
2482
2483 stage.parentGroup->addChild(stageGroup.release());
2484 }
2485
2486 return allTests.release();
2487 }
2488
2489 } // namespace pipeline
2490 } // namespace vkt
2491