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