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