1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Imagination Technologies Ltd.
7 * Copyright (c) 2023 LunarG, Inc.
8 * Copyright (c) 2023 Nintendo
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 *//*!
23 * \file
24 * \brief Vertex Input Tests
25 *//*--------------------------------------------------------------------*/
26
27 #include "vktPipelineVertexInputTests.hpp"
28 #include "vktTestGroupUtil.hpp"
29 #include "vktPipelineClearUtil.hpp"
30 #include "vktPipelineImageUtil.hpp"
31 #include "vktPipelineVertexUtil.hpp"
32 #include "vktPipelineReferenceRenderer.hpp"
33 #include "vktTestCase.hpp"
34 #include "vktTestCaseUtil.hpp"
35 #include "vkImageUtil.hpp"
36 #include "vkMemUtil.hpp"
37 #include "vkPrograms.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkRef.hpp"
40 #include "vkRefUtil.hpp"
41 #include "vkTypeUtil.hpp"
42 #include "vkCmdUtil.hpp"
43 #include "vkObjUtil.hpp"
44 #include "tcuFloat.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "deFloat16.h"
47 #include "deMemory.h"
48 #include "deRandom.hpp"
49 #include "deStringUtil.hpp"
50 #include "deUniquePtr.hpp"
51
52 #include <sstream>
53 #include <vector>
54 #include <map>
55
56 namespace vkt
57 {
58 namespace pipeline
59 {
60
61 namespace
62 {
63
64 using namespace vk;
65
66 constexpr int kMaxComponents = 4;
67
isSupportedVertexFormat(Context & context,VkFormat format)68 bool isSupportedVertexFormat (Context& context, VkFormat format)
69 {
70 if (isVertexFormatDouble(format) && !context.getDeviceFeatures().shaderFloat64)
71 return false;
72
73 VkFormatProperties formatProps;
74 deMemset(&formatProps, 0, sizeof(VkFormatProperties));
75 context.getInstanceInterface().getPhysicalDeviceFormatProperties(context.getPhysicalDevice(), format, &formatProps);
76
77 return (formatProps.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) != 0u;
78 }
79
getRepresentableDifferenceUnorm(VkFormat format)80 float getRepresentableDifferenceUnorm (VkFormat format)
81 {
82 DE_ASSERT(isVertexFormatUnorm(format) || isVertexFormatSRGB(format));
83
84 return 1.0f / float((1 << (getVertexFormatComponentSize(format) * 8)) - 1);
85 }
86
getRepresentableDifferenceUnormPacked(VkFormat format,deUint32 componentNdx)87 float getRepresentableDifferenceUnormPacked(VkFormat format, deUint32 componentNdx)
88 {
89 DE_ASSERT((isVertexFormatUnorm(format) || isVertexFormatSRGB(format)) && isVertexFormatPacked(format));
90
91 return 1.0f / float((1 << (getPackedVertexFormatComponentWidth(format, componentNdx))) - 1);
92 }
93
getRepresentableDifferenceSnorm(VkFormat format)94 float getRepresentableDifferenceSnorm (VkFormat format)
95 {
96 DE_ASSERT(isVertexFormatSnorm(format));
97
98 return 1.0f / float((1 << (getVertexFormatComponentSize(format) * 8 - 1)) - 1);
99 }
100
getRepresentableDifferenceSnormPacked(VkFormat format,deUint32 componentNdx)101 float getRepresentableDifferenceSnormPacked(VkFormat format, deUint32 componentNdx)
102 {
103 DE_ASSERT(isVertexFormatSnorm(format) && isVertexFormatPacked(format));
104
105 return 1.0f / float((1 << (getPackedVertexFormatComponentWidth(format, componentNdx) - 1)) - 1);
106 }
107
getNextMultipleOffset(deUint32 divisor,deUint32 value)108 deUint32 getNextMultipleOffset (deUint32 divisor, deUint32 value)
109 {
110 if (value % divisor == 0)
111 return 0;
112 else
113 return divisor - (value % divisor);
114 }
115
116 class VertexInputTest : public vkt::TestCase
117 {
118 public:
119 enum GlslType
120 {
121 GLSL_TYPE_INT,
122 GLSL_TYPE_IVEC2,
123 GLSL_TYPE_IVEC3,
124 GLSL_TYPE_IVEC4,
125
126 GLSL_TYPE_UINT,
127 GLSL_TYPE_UVEC2,
128 GLSL_TYPE_UVEC3,
129 GLSL_TYPE_UVEC4,
130
131 GLSL_TYPE_FLOAT,
132 GLSL_TYPE_VEC2,
133 GLSL_TYPE_VEC3,
134 GLSL_TYPE_VEC4,
135
136 GLSL_TYPE_F16,
137 GLSL_TYPE_F16VEC2,
138 GLSL_TYPE_F16VEC3,
139 GLSL_TYPE_F16VEC4,
140
141 GLSL_TYPE_MAT2,
142 GLSL_TYPE_MAT3,
143 GLSL_TYPE_MAT4,
144
145 GLSL_TYPE_DOUBLE,
146 GLSL_TYPE_DVEC2,
147 GLSL_TYPE_DVEC3,
148 GLSL_TYPE_DVEC4,
149 GLSL_TYPE_DMAT2,
150 GLSL_TYPE_DMAT3,
151 GLSL_TYPE_DMAT4,
152
153 GLSL_TYPE_COUNT
154 };
155
156 enum GlslBasicType
157 {
158 GLSL_BASIC_TYPE_INT,
159 GLSL_BASIC_TYPE_UINT,
160 GLSL_BASIC_TYPE_FLOAT,
161 GLSL_BASIC_TYPE_DOUBLE,
162 GLSL_BASIC_TYPE_FLOAT16,
163 };
164
165 enum BindingMapping
166 {
167 BINDING_MAPPING_ONE_TO_ONE, //!< Vertex input bindings will not contain data for more than one attribute.
168 BINDING_MAPPING_ONE_TO_MANY //!< Vertex input bindings can contain data for more than one attribute.
169 };
170
171 enum AttributeLayout
172 {
173 ATTRIBUTE_LAYOUT_INTERLEAVED, //!< Attribute data is bundled together as if in a structure: [pos 0][color 0][pos 1][color 1]...
174 ATTRIBUTE_LAYOUT_SEQUENTIAL //!< Data for each attribute is laid out separately: [pos 0][pos 1]...[color 0][color 1]...
175 // Sequential only makes a difference if ONE_TO_MANY mapping is used (more than one attribute in a binding).
176 };
177
178 enum LayoutSkip
179 {
180 LAYOUT_SKIP_ENABLED, //!< Skip one location slot after each attribute
181 LAYOUT_SKIP_DISABLED //!< Consume locations sequentially
182 };
183
184 enum LayoutOrder
185 {
186 LAYOUT_ORDER_IN_ORDER, //!< Assign locations in order
187 LAYOUT_ORDER_OUT_OF_ORDER //!< Assign locations out of order
188 };
189
190 struct AttributeInfo
191 {
192 GlslType glslType;
193 VkFormat vkType;
194 VkVertexInputRate inputRate;
195 };
196
197 struct GlslTypeDescription
198 {
199 const char* name;
200 int vertexInputComponentCount;
201 int vertexInputCount;
202 GlslBasicType basicType;
203 };
204
205 static const GlslTypeDescription s_glslTypeDescriptions[GLSL_TYPE_COUNT];
206
207 VertexInputTest (tcu::TestContext& testContext,
208 const std::string& name,
209 const PipelineConstructionType pipelineConstructionType,
210 const std::vector<AttributeInfo>& attributeInfos,
211 BindingMapping bindingMapping,
212 AttributeLayout attributeLayout,
213 LayoutSkip layoutSkip = LAYOUT_SKIP_DISABLED,
214 LayoutOrder layoutOrder = LAYOUT_ORDER_IN_ORDER,
215 const bool testMissingComponents = false);
216
~VertexInputTest(void)217 virtual ~VertexInputTest (void) {}
218 virtual void initPrograms (SourceCollections& programCollection) const;
219 virtual void checkSupport (Context& context) const;
220 virtual TestInstance* createInstance (Context& context) const;
221 static bool isCompatibleType (VkFormat format, GlslType glslType);
222
223 private:
224 AttributeInfo getAttributeInfo (size_t attributeNdx) const;
225 size_t getNumAttributes (void) const;
226 std::string getGlslExtensions (void) const;
227 std::string getGlslInputDeclarations (void) const;
228 std::string getGlslVertexCheck (void) const;
229 std::string getGlslAttributeConditions (const AttributeInfo& attributeInfo, const std::string attributeIndex) const;
230 static tcu::Vec4 getFormatThreshold (VkFormat format);
231
232 const PipelineConstructionType m_pipelineConstructionType;
233 const std::vector<AttributeInfo> m_attributeInfos;
234 const BindingMapping m_bindingMapping;
235 const AttributeLayout m_attributeLayout;
236 const LayoutSkip m_layoutSkip;
237 mutable std::vector<deUint32> m_locations;
238 const bool m_queryMaxAttributes;
239 bool m_usesDoubleType;
240 bool m_usesFloat16Type;
241 mutable size_t m_maxAttributes;
242 const bool m_testMissingComponents;
243 };
244
245 class VertexInputInstance : public vkt::TestInstance
246 {
247 public:
248 struct VertexInputAttributeDescription
249 {
250 VertexInputTest::GlslType glslType;
251 int vertexInputIndex;
252 VkVertexInputAttributeDescription vkDescription;
253 };
254
255 typedef std::vector<VertexInputAttributeDescription> AttributeDescriptionList;
256
257 VertexInputInstance (Context& context,
258 const PipelineConstructionType pipelineConstructionType,
259 const AttributeDescriptionList& attributeDescriptions,
260 const std::vector<VkVertexInputBindingDescription>& bindingDescriptions,
261 const std::vector<VkDeviceSize>& bindingOffsets);
262
263 virtual ~VertexInputInstance (void);
264 virtual tcu::TestStatus iterate (void);
265
266
267 static void writeVertexInputData (deUint8* destPtr, const VkVertexInputBindingDescription& bindingDescription, const VkDeviceSize bindingOffset, const AttributeDescriptionList& attributes);
268 static void writeVertexInputValue (deUint8* destPtr, const VertexInputAttributeDescription& attributes, int indexId);
269
270 private:
271 tcu::TestStatus verifyImage (void);
272
273 private:
274 std::vector<VkBuffer> m_vertexBuffers;
275 std::vector<Allocation*> m_vertexBufferAllocs;
276
277 const tcu::UVec2 m_renderSize;
278 const VkFormat m_colorFormat;
279
280 Move<VkImage> m_colorImage;
281 de::MovePtr<Allocation> m_colorImageAlloc;
282 Move<VkImage> m_depthImage;
283 Move<VkImageView> m_colorAttachmentView;
284 RenderPassWrapper m_renderPass;
285
286 ShaderWrapper m_vertexShaderModule;
287 ShaderWrapper m_fragmentShaderModule;
288
289 PipelineLayoutWrapper m_pipelineLayout;
290 GraphicsPipelineWrapper m_graphicsPipeline;
291
292 Move<VkCommandPool> m_cmdPool;
293 Move<VkCommandBuffer> m_cmdBuffer;
294 };
295
296 const VertexInputTest::GlslTypeDescription VertexInputTest::s_glslTypeDescriptions[GLSL_TYPE_COUNT] =
297 {
298 { "int", 1, 1, GLSL_BASIC_TYPE_INT },
299 { "ivec2", 2, 1, GLSL_BASIC_TYPE_INT },
300 { "ivec3", 3, 1, GLSL_BASIC_TYPE_INT },
301 { "ivec4", 4, 1, GLSL_BASIC_TYPE_INT },
302
303 { "uint", 1, 1, GLSL_BASIC_TYPE_UINT },
304 { "uvec2", 2, 1, GLSL_BASIC_TYPE_UINT },
305 { "uvec3", 3, 1, GLSL_BASIC_TYPE_UINT },
306 { "uvec4", 4, 1, GLSL_BASIC_TYPE_UINT },
307
308 { "float", 1, 1, GLSL_BASIC_TYPE_FLOAT },
309 { "vec2", 2, 1, GLSL_BASIC_TYPE_FLOAT },
310 { "vec3", 3, 1, GLSL_BASIC_TYPE_FLOAT },
311 { "vec4", 4, 1, GLSL_BASIC_TYPE_FLOAT },
312
313 { "float16_t", 1, 1, GLSL_BASIC_TYPE_FLOAT16 },
314 { "f16vec2", 2, 1, GLSL_BASIC_TYPE_FLOAT16 },
315 { "f16vec3", 3, 1, GLSL_BASIC_TYPE_FLOAT16 },
316 { "f16vec4", 4, 1, GLSL_BASIC_TYPE_FLOAT16 },
317
318 { "mat2", 2, 2, GLSL_BASIC_TYPE_FLOAT },
319 { "mat3", 3, 3, GLSL_BASIC_TYPE_FLOAT },
320 { "mat4", 4, 4, GLSL_BASIC_TYPE_FLOAT },
321
322 { "double", 1, 1, GLSL_BASIC_TYPE_DOUBLE },
323 { "dvec2", 2, 1, GLSL_BASIC_TYPE_DOUBLE },
324 { "dvec3", 3, 1, GLSL_BASIC_TYPE_DOUBLE },
325 { "dvec4", 4, 1, GLSL_BASIC_TYPE_DOUBLE },
326 { "dmat2", 2, 2, GLSL_BASIC_TYPE_DOUBLE },
327 { "dmat3", 3, 3, GLSL_BASIC_TYPE_DOUBLE },
328 { "dmat4", 4, 4, GLSL_BASIC_TYPE_DOUBLE }
329 };
330
expandGlslNameToFullComponents(const char * name)331 const char* expandGlslNameToFullComponents (const char* name)
332 {
333 static const std::map<std::string, std::string> nameMap
334 {
335 std::make_pair("int", "ivec4"),
336 std::make_pair("ivec2", "ivec4"),
337 std::make_pair("ivec3", "ivec4"),
338 std::make_pair("ivec4", "ivec4"),
339 std::make_pair("uint", "uvec4"),
340 std::make_pair("uvec2", "uvec4"),
341 std::make_pair("uvec3", "uvec4"),
342 std::make_pair("uvec4", "uvec4"),
343 std::make_pair("float", "vec4"),
344 std::make_pair("vec2", "vec4"),
345 std::make_pair("vec3", "vec4"),
346 std::make_pair("vec4", "vec4"),
347 std::make_pair("float16_t", "f16vec4"),
348 std::make_pair("f16vec2", "f16vec4"),
349 std::make_pair("f16vec3", "f16vec4"),
350 std::make_pair("f16vec4", "f16vec4"),
351 std::make_pair("mat2", "mat2x4"),
352 std::make_pair("mat3", "mat3x4"),
353 std::make_pair("mat4", "mat4"),
354 #if 0
355 // 64-bit types don't have default values, so they cannot be used in missing component tests.
356 // In addition, they may be expanded from one location to using more than one, which creates vertex input mismatches.
357 std::make_pair("double", "dvec4"),
358 std::make_pair("dvec2", "dvec4"),
359 std::make_pair("dvec3", "dvec4"),
360 std::make_pair("dvec4", "dvec4"),
361 std::make_pair("dmat2", "dmat2x4"),
362 std::make_pair("dmat3", "dmat3x4"),
363 std::make_pair("dmat4", "dmat4"),
364 #endif
365 };
366
367 const auto pos = nameMap.find(name);
368 if (pos == nameMap.end())
369 return nullptr;
370 return pos->second.c_str();
371 }
372
getAttributeBinding(const VertexInputTest::BindingMapping bindingMapping,const VkVertexInputRate firstInputRate,const VkVertexInputRate inputRate,const deUint32 attributeNdx)373 deUint32 getAttributeBinding (const VertexInputTest::BindingMapping bindingMapping, const VkVertexInputRate firstInputRate, const VkVertexInputRate inputRate, const deUint32 attributeNdx)
374 {
375 if (bindingMapping == VertexInputTest::BINDING_MAPPING_ONE_TO_ONE)
376 {
377 // Each attribute uses a unique binding
378 return attributeNdx;
379 }
380 else // bindingMapping == BINDING_MAPPING_ONE_TO_MANY
381 {
382 // Alternate between two bindings
383 return deUint32(firstInputRate + inputRate) % 2u;
384 }
385 }
386
387 //! Number of locations used up by an attribute.
getConsumedLocations(const VertexInputTest::AttributeInfo & attributeInfo)388 deUint32 getConsumedLocations (const VertexInputTest::AttributeInfo& attributeInfo)
389 {
390 // double formats with more than 2 components will take 2 locations
391 const VertexInputTest::GlslType type = attributeInfo.glslType;
392 if ((type == VertexInputTest::GLSL_TYPE_DMAT2 || type == VertexInputTest::GLSL_TYPE_DMAT3 || type == VertexInputTest::GLSL_TYPE_DMAT4) &&
393 (attributeInfo.vkType == VK_FORMAT_R64G64B64_SFLOAT || attributeInfo.vkType == VK_FORMAT_R64G64B64A64_SFLOAT))
394 {
395 return 2u;
396 }
397 else
398 return 1u;
399 }
400
VertexInputTest(tcu::TestContext & testContext,const std::string & name,const PipelineConstructionType pipelineConstructionType,const std::vector<AttributeInfo> & attributeInfos,BindingMapping bindingMapping,AttributeLayout attributeLayout,LayoutSkip layoutSkip,LayoutOrder layoutOrder,const bool testMissingComponents)401 VertexInputTest::VertexInputTest (tcu::TestContext& testContext,
402 const std::string& name,
403 const PipelineConstructionType pipelineConstructionType,
404 const std::vector<AttributeInfo>& attributeInfos,
405 BindingMapping bindingMapping,
406 AttributeLayout attributeLayout,
407 LayoutSkip layoutSkip,
408 LayoutOrder layoutOrder,
409 const bool testMissingComponents)
410 : vkt::TestCase (testContext, name)
411 , m_pipelineConstructionType (pipelineConstructionType)
412 , m_attributeInfos (attributeInfos)
413 , m_bindingMapping (bindingMapping)
414 , m_attributeLayout (attributeLayout)
415 , m_layoutSkip (layoutSkip)
416 , m_queryMaxAttributes (attributeInfos.size() == 0)
417 , m_usesDoubleType (false)
418 , m_usesFloat16Type (false)
419 , m_maxAttributes (16)
420 , m_testMissingComponents (testMissingComponents)
421 {
422 DE_ASSERT(m_attributeLayout == ATTRIBUTE_LAYOUT_INTERLEAVED || m_bindingMapping == BINDING_MAPPING_ONE_TO_MANY);
423
424 for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++)
425 {
426 const auto& basicType = s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].basicType;
427
428 if (basicType == GLSL_BASIC_TYPE_DOUBLE)
429 m_usesDoubleType = true;
430 else if (basicType == GLSL_BASIC_TYPE_FLOAT16)
431 m_usesFloat16Type = true;
432 }
433
434 // Determine number of location slots required for each attribute
435 deUint32 attributeLocation = 0;
436 std::vector<deUint32> locationSlotsNeeded;
437 const size_t numAttributes = getNumAttributes();
438
439 for (size_t attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx)
440 {
441 const AttributeInfo& attributeInfo = getAttributeInfo(attributeNdx);
442 const GlslTypeDescription& glslTypeDescription = s_glslTypeDescriptions[attributeInfo.glslType];
443 const deUint32 prevAttributeLocation = attributeLocation;
444
445 attributeLocation += glslTypeDescription.vertexInputCount * getConsumedLocations(attributeInfo);
446
447 if (m_layoutSkip == LAYOUT_SKIP_ENABLED)
448 attributeLocation++;
449
450 locationSlotsNeeded.push_back(attributeLocation - prevAttributeLocation);
451 }
452
453 if (layoutOrder == LAYOUT_ORDER_IN_ORDER)
454 {
455 deUint32 loc = 0;
456
457 // Assign locations in order
458 for (size_t attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx)
459 {
460 m_locations.push_back(loc);
461 loc += locationSlotsNeeded[attributeNdx];
462 }
463 }
464 else
465 {
466 // Assign locations out of order
467 std::vector<deUint32> indices;
468 std::vector<deUint32> slots;
469 deUint32 slot = 0;
470
471 // Mix the location slots: first all even and then all odd attributes.
472 for (deUint32 attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx)
473 if (attributeNdx % 2 == 0)
474 indices.push_back(attributeNdx);
475 for (deUint32 attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx)
476 if (attributeNdx % 2 != 0)
477 indices.push_back(attributeNdx);
478
479 for (size_t i = 0; i < indices.size(); i++)
480 {
481 slots.push_back(slot);
482 slot += locationSlotsNeeded[indices[i]];
483 }
484
485 for (size_t attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx)
486 {
487 deUint32 slotIdx = 0;
488 for (deUint32 i = 0; i < (deUint32)indices.size(); i++)
489 if (attributeNdx == indices[i])
490 slotIdx = i;
491 m_locations.push_back(slots[slotIdx]);
492 }
493 }
494 }
495
getAttributeInfo(size_t attributeNdx) const496 VertexInputTest::AttributeInfo VertexInputTest::getAttributeInfo (size_t attributeNdx) const
497 {
498 if (m_queryMaxAttributes)
499 {
500 AttributeInfo attributeInfo =
501 {
502 GLSL_TYPE_VEC4,
503 VK_FORMAT_R8G8B8A8_SNORM,
504 (attributeNdx % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE
505 };
506
507 return attributeInfo;
508 }
509 else
510 {
511 return m_attributeInfos.at(attributeNdx);
512 }
513 }
514
getNumAttributes(void) const515 size_t VertexInputTest::getNumAttributes (void) const
516 {
517 if (m_queryMaxAttributes)
518 return m_maxAttributes;
519 else
520 return m_attributeInfos.size();
521 }
522
checkSupport(Context & context) const523 void VertexInputTest::checkSupport (Context& context) const
524 {
525 const deUint32 maxAttributes = context.getDeviceProperties().limits.maxVertexInputAttributes;
526
527 if (m_attributeInfos.size() > maxAttributes)
528 TCU_THROW(NotSupportedError, "Unsupported number of vertex input attributes, maxVertexInputAttributes: " + de::toString(maxAttributes));
529
530 if (m_usesFloat16Type)
531 {
532 const auto& sf16i8Features = context.getShaderFloat16Int8Features();
533 if (!sf16i8Features.shaderFloat16)
534 TCU_THROW(NotSupportedError, "shaderFloat16 not supported");
535
536 const auto& storage16Features = context.get16BitStorageFeatures();
537 if (!storage16Features.storageInputOutput16)
538 TCU_THROW(NotSupportedError, "storageInputOutput16 not supported");
539 }
540
541 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
542 }
543
createInstance(Context & context) const544 TestInstance* VertexInputTest::createInstance (Context& context) const
545 {
546 typedef VertexInputInstance::VertexInputAttributeDescription VertexInputAttributeDescription;
547
548 // Check upfront for maximum number of vertex input attributes
549 {
550 const InstanceInterface& vki = context.getInstanceInterface();
551 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
552 const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physDevice).limits;
553
554 const deUint32 maxAttributes = limits.maxVertexInputAttributes;
555
556 // Use VkPhysicalDeviceLimits::maxVertexInputAttributes
557 if (m_queryMaxAttributes)
558 {
559 m_maxAttributes = maxAttributes;
560 m_locations.clear();
561 for (deUint32 i = 0; i < maxAttributes; i++)
562 m_locations.push_back(i);
563 }
564 }
565
566 // Create enough binding descriptions with random offsets
567 std::vector<VkVertexInputBindingDescription> bindingDescriptions;
568 std::vector<VkDeviceSize> bindingOffsets;
569 const size_t numAttributes = getNumAttributes();
570 const size_t numBindings = (m_bindingMapping == BINDING_MAPPING_ONE_TO_ONE) ? numAttributes : ((numAttributes > 1) ? 2 : 1);
571 const VkVertexInputRate firstInputrate = getAttributeInfo(0).inputRate;
572
573 for (size_t bindingNdx = 0; bindingNdx < numBindings; ++bindingNdx)
574 {
575 // Bindings alternate between STEP_RATE_VERTEX and STEP_RATE_INSTANCE
576 const VkVertexInputRate inputRate = ((firstInputrate + bindingNdx) % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
577
578 // Stride will be updated when creating the attribute descriptions
579 const VkVertexInputBindingDescription bindingDescription =
580 {
581 static_cast<deUint32>(bindingNdx), // deUint32 binding;
582 0u, // deUint32 stride;
583 inputRate // VkVertexInputRate inputRate;
584 };
585
586 bindingDescriptions.push_back(bindingDescription);
587 bindingOffsets.push_back(4 * bindingNdx);
588 }
589
590 std::vector<VertexInputAttributeDescription> attributeDescriptions;
591 std::vector<deUint32> attributeOffsets (bindingDescriptions.size(), 0);
592 std::vector<deUint32> attributeMaxSizes (bindingDescriptions.size(), 0); // max component or vector size, depending on which layout we are using
593 std::vector<uint32_t> attributeMaxCompSizes (bindingDescriptions.size(), 0u); // max component size for each binding.
594 std::vector<uint32_t> bindingSeqStrides (bindingDescriptions.size(), 0u); // strides for bindings in sequential layout mode
595
596 // To place the attributes sequentially we need to know the largest attribute and use its size in stride and offset calculations.
597 if (m_attributeLayout == ATTRIBUTE_LAYOUT_SEQUENTIAL)
598 {
599 for (size_t attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx)
600 {
601 const AttributeInfo& attributeInfo = getAttributeInfo(attributeNdx);
602 const deUint32 attributeBinding = getAttributeBinding(m_bindingMapping, firstInputrate, attributeInfo.inputRate, static_cast<deUint32>(attributeNdx));
603 const deUint32 inputSize = getVertexFormatSize(attributeInfo.vkType);
604 const auto componentSize = getVertexFormatComponentSize(attributeInfo.vkType);
605 const auto maxSize = de::max(attributeMaxSizes[attributeBinding], inputSize);
606 const auto maxComponentSize = de::max(attributeMaxCompSizes[attributeBinding], componentSize);
607
608 attributeMaxSizes[attributeBinding] = maxSize;
609 attributeMaxCompSizes[attributeBinding] = maxComponentSize;
610 }
611
612 // Round up the maximum size so the components are always aligned.
613 for (size_t bindingIdx = 0u; bindingIdx < bindingSeqStrides.size(); ++bindingIdx)
614 bindingSeqStrides[bindingIdx] = de::roundUp(attributeMaxSizes[bindingIdx], attributeMaxCompSizes[bindingIdx]);
615 }
616
617 // Create attribute descriptions, assign them to bindings and update stride.
618 for (size_t attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx)
619 {
620 const AttributeInfo& attributeInfo = getAttributeInfo(attributeNdx);
621 const GlslTypeDescription& glslTypeDescription = s_glslTypeDescriptions[attributeInfo.glslType];
622 const deUint32 inputSize = getVertexFormatSize(attributeInfo.vkType);
623 const deUint32 attributeBinding = getAttributeBinding(m_bindingMapping, firstInputrate, attributeInfo.inputRate, static_cast<deUint32>(attributeNdx));
624 const deUint32 vertexCount = (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) ? (4 * 2) : 2;
625
626 VertexInputAttributeDescription attributeDescription =
627 {
628 attributeInfo.glslType, // GlslType glslType;
629 0, // int vertexInputIndex;
630 {
631 0u, // uint32_t location;
632 attributeBinding, // uint32_t binding;
633 attributeInfo.vkType, // VkFormat format;
634 0u, // uint32_t offset;
635 },
636 };
637
638 // Matrix types add each column as a separate attribute.
639 for (int descNdx = 0; descNdx < glslTypeDescription.vertexInputCount; ++descNdx)
640 {
641 attributeDescription.vertexInputIndex = descNdx;
642 attributeDescription.vkDescription.location = m_locations[attributeNdx] + getConsumedLocations(attributeInfo) * descNdx;
643
644 if (m_attributeLayout == ATTRIBUTE_LAYOUT_INTERLEAVED)
645 {
646 const deUint32 offsetToComponentAlignment = getNextMultipleOffset(inputSize,
647 (deUint32)bindingOffsets[attributeBinding] + attributeOffsets[attributeBinding]);
648
649 attributeOffsets[attributeBinding] += offsetToComponentAlignment;
650
651 attributeDescription.vkDescription.offset = attributeOffsets[attributeBinding];
652 attributeDescriptions.push_back(attributeDescription);
653
654 bindingDescriptions[attributeBinding].stride += offsetToComponentAlignment + inputSize;
655 attributeOffsets[attributeBinding] += inputSize;
656 attributeMaxSizes[attributeBinding] = de::max(attributeMaxSizes[attributeBinding], inputSize);
657 }
658 else // m_attributeLayout == ATTRIBUTE_LAYOUT_SEQUENTIAL
659 {
660 attributeDescription.vkDescription.offset = attributeOffsets[attributeBinding];
661 attributeDescriptions.push_back(attributeDescription);
662
663 attributeOffsets[attributeBinding] += vertexCount * bindingSeqStrides[attributeBinding];
664 }
665 }
666
667 if (m_attributeLayout == ATTRIBUTE_LAYOUT_SEQUENTIAL)
668 bindingDescriptions[attributeBinding].stride = bindingSeqStrides[attributeBinding];
669 }
670
671 if (m_attributeLayout == ATTRIBUTE_LAYOUT_INTERLEAVED)
672 {
673 // Make sure the stride results in aligned access
674 for (size_t bindingNdx = 0; bindingNdx < bindingDescriptions.size(); ++bindingNdx)
675 {
676 auto& stride = bindingDescriptions[bindingNdx].stride; // note: by reference to modify it below.
677
678 if (attributeMaxSizes[bindingNdx] > 0)
679 stride += getNextMultipleOffset(attributeMaxSizes[bindingNdx], stride);
680 }
681 }
682
683 // Check upfront for maximum number of vertex input bindings
684 {
685 const InstanceInterface& vki = context.getInstanceInterface();
686 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
687 const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physDevice).limits;
688
689 const deUint32 maxBindings = limits.maxVertexInputBindings;
690
691 if (bindingDescriptions.size() > maxBindings)
692 {
693 const std::string notSupportedStr = "Unsupported number of vertex input bindings, maxVertexInputBindings: " + de::toString(maxBindings);
694 TCU_THROW(NotSupportedError, notSupportedStr.c_str());
695 }
696 }
697
698 // Portability requires stride to be multiply of minVertexInputBindingStrideAlignment
699 #ifndef CTS_USES_VULKANSC
700 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset"))
701 {
702 deUint32 minStrideAlignment = context.getPortabilitySubsetProperties().minVertexInputBindingStrideAlignment;
703 for (size_t bindingNdx = 0; bindingNdx < bindingDescriptions.size(); ++bindingNdx)
704 {
705 if ((bindingDescriptions[bindingNdx].stride % minStrideAlignment) != 0)
706 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: stride is not multiply of minVertexInputBindingStrideAlignment");
707 }
708 }
709 #endif // CTS_USES_VULKANSC
710
711 return new VertexInputInstance(context, m_pipelineConstructionType, attributeDescriptions, bindingDescriptions, bindingOffsets);
712 }
713
initPrograms(SourceCollections & programCollection) const714 void VertexInputTest::initPrograms (SourceCollections& programCollection) const
715 {
716 std::ostringstream vertexSrc;
717
718 vertexSrc << "#version 460\n"
719 << getGlslExtensions()
720 << "layout(constant_id = 0) const int numAttributes = " << m_maxAttributes << ";\n"
721 << getGlslInputDeclarations()
722 << "layout(location = 0) out highp vec4 vtxColor;\n"
723 << "out gl_PerVertex {\n"
724 << " vec4 gl_Position;\n"
725 << "};\n";
726
727 vertexSrc << "void main (void)\n"
728 << "{\n"
729 << getGlslVertexCheck()
730 << "}\n";
731
732 programCollection.glslSources.add("attribute_test_vert") << glu::VertexSource(vertexSrc.str());
733
734 programCollection.glslSources.add("attribute_test_frag") << glu::FragmentSource(
735 "#version 460\n"
736 "layout(location = 0) in highp vec4 vtxColor;\n"
737 "layout(location = 0) out highp vec4 fragColor;\n"
738 "void main (void)\n"
739 "{\n"
740 " fragColor = vtxColor;\n"
741 "}\n");
742 }
743
getGlslExtensions(void) const744 std::string VertexInputTest::getGlslExtensions (void) const
745 {
746 std::string extensions;
747
748 if (m_usesFloat16Type)
749 extensions += "#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require\n";
750
751 return extensions;
752 }
753
getGlslInputDeclarations(void) const754 std::string VertexInputTest::getGlslInputDeclarations (void) const
755 {
756 std::ostringstream glslInputs;
757
758 if (m_queryMaxAttributes)
759 {
760 // Don't use the first input binding to leave room for VertexIndex and InstanceIndex, which count towards the
761 // total number of inputs attributes. Leave the first binding so that the largest location number are still used.
762 const GlslTypeDescription& glslTypeDesc = s_glslTypeDescriptions[GLSL_TYPE_VEC4];
763 glslInputs << "layout(location = 1) in " << glslTypeDesc.name << " attr[numAttributes-1];\n";
764 }
765 else
766 {
767 for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++)
768 {
769 const char* declType = nullptr;
770 if (m_testMissingComponents)
771 {
772 const auto& glslType = m_attributeInfos[attributeNdx].glslType;
773 const auto& typeInfo = s_glslTypeDescriptions[glslType];
774
775 DE_ASSERT(typeInfo.vertexInputComponentCount < kMaxComponents);
776 DE_ASSERT(typeInfo.basicType != GLSL_BASIC_TYPE_DOUBLE);
777
778 // Find the equivalent type with 4 components.
779 declType = expandGlslNameToFullComponents(typeInfo.name);
780 }
781 else
782 declType = s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].name;
783
784 glslInputs << "layout(location = " << m_locations[attributeNdx] << ") in " << declType << " attr" << attributeNdx << ";\n";
785 }
786 }
787
788 return glslInputs.str();
789 }
790
getGlslVertexCheck(void) const791 std::string VertexInputTest::getGlslVertexCheck (void) const
792 {
793 std::ostringstream glslCode;
794 std::string inputCountStr;
795
796 glslCode << " int okCount = 0;\n";
797
798 if (m_queryMaxAttributes)
799 {
800 DE_ASSERT(!m_testMissingComponents);
801
802 // numAttributes will be replaced later by a specialisation constant, so this loop and
803 // the multiplication by numAttributes, below, must happen in the shader itself.
804 const AttributeInfo attributeInfo = getAttributeInfo(0);
805
806 glslCode << " for (int checkNdx = 1; checkNdx < numAttributes; checkNdx++)\n"
807 << " {\n"
808 << " uint index = (checkNdx % 2 == 0) ? gl_VertexIndex : gl_InstanceIndex;\n";
809
810 // Because our location is offset by 1 relative to the API definitions, checkNdx-1 here.
811 glslCode << getGlslAttributeConditions(attributeInfo, "checkNdx-1")
812 << " }\n";
813
814 const int vertexInputCount = VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputCount;
815 int totalInputComponentCount = vertexInputCount * VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputComponentCount;
816
817 // Don't count components from location 0 which was skipped.
818 inputCountStr = std::to_string(totalInputComponentCount) + " * (numAttributes-1)";
819 }
820 else
821 {
822 // Generate 1 check per attribute and work out the number of components at compile time.
823 int totalInputComponentCount = 0;
824 for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++)
825 {
826 glslCode << getGlslAttributeConditions(m_attributeInfos[attributeNdx], de::toString(attributeNdx));
827
828 const int vertexInputCount = VertexInputTest::s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].vertexInputCount;
829 const int vertexCompCount = VertexInputTest::s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].vertexInputComponentCount;
830 totalInputComponentCount += vertexInputCount * ((!m_testMissingComponents) ? vertexCompCount : kMaxComponents - vertexCompCount);
831 }
832
833 inputCountStr = std::to_string(totalInputComponentCount);
834 }
835
836 glslCode <<
837 " if (okCount == " << inputCountStr << ")\n"
838 " {\n"
839 " if (gl_InstanceIndex == 0)\n"
840 " vtxColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
841 " else\n"
842 " vtxColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
843 " }\n"
844 " else\n"
845 " {\n"
846 " vtxColor = vec4(okCount / float(" << inputCountStr << "), 0.0f, 0.0f, 1.0);\n" <<
847 " }\n\n"
848 " if (gl_InstanceIndex == 0)\n"
849 " {\n"
850 " if (gl_VertexIndex == 0) gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
851 " else if (gl_VertexIndex == 1) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n"
852 " else if (gl_VertexIndex == 2) gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
853 " else if (gl_VertexIndex == 3) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n"
854 " else gl_Position = vec4(0.0);\n"
855 " }\n"
856 " else\n"
857 " {\n"
858 " if (gl_VertexIndex == 0) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n"
859 " else if (gl_VertexIndex == 1) gl_Position = vec4(1.0, -1.0, 0.0, 1.0);\n"
860 " else if (gl_VertexIndex == 2) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n"
861 " else if (gl_VertexIndex == 3) gl_Position = vec4(1.0, 1.0, 0.0, 1.0);\n"
862 " else gl_Position = vec4(0.0);\n"
863 " }\n";
864
865 return glslCode.str();
866 }
867
getGlslAttributeConditions(const AttributeInfo & attributeInfo,const std::string attributeIndex) const868 std::string VertexInputTest::getGlslAttributeConditions (const AttributeInfo& attributeInfo, const std::string attributeIndex) const
869 {
870 std::ostringstream glslCode;
871 std::ostringstream attributeVar;
872 const int componentCount = VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputComponentCount;
873 const int vertexInputCount = VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputCount;
874 const deUint32 totalComponentCount = componentCount * vertexInputCount;
875 const tcu::Vec4 threshold = getFormatThreshold(attributeInfo.vkType);
876 const std::string indexStr = m_queryMaxAttributes ? "[" + attributeIndex + "]" : attributeIndex;
877 const std::string indentStr = m_queryMaxAttributes ? "\t\t" : "\t";
878 deUint32 componentIndex = 0;
879 deUint32 orderNdx;
880 std::string indexId;
881
882 const deUint32 BGROrder[] = { 2, 1, 0, 3 };
883 const deUint32 ABGROrder[] = { 3, 2, 1, 0 };
884 const deUint32 ARGBOrder[] = { 1, 2, 3, 0 };
885
886 if (m_queryMaxAttributes)
887 indexId = "index";
888 else
889 indexId = (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) ? "gl_VertexIndex" : "gl_InstanceIndex";
890
891 attributeVar << "attr" << indexStr;
892
893 glslCode << std::fixed;
894
895 for (int columnNdx = 0; columnNdx< vertexInputCount; columnNdx++)
896 {
897 for (int rowNdx = 0; rowNdx < kMaxComponents; rowNdx++)
898 {
899 if (isVertexFormatComponentOrderABGR(attributeInfo.vkType))
900 orderNdx = ABGROrder[rowNdx];
901 else if (isVertexFormatComponentOrderARGB(attributeInfo.vkType))
902 orderNdx = ARGBOrder[rowNdx];
903 else
904 orderNdx = BGROrder[rowNdx];
905
906 std::string accessStr;
907 {
908 // Build string representing the access to the attribute component
909 std::ostringstream accessStream;
910 accessStream << attributeVar.str();
911
912 if (vertexInputCount == 1)
913 {
914 if (componentCount > 1 || m_testMissingComponents)
915 accessStream << "[" << rowNdx << "]";
916 }
917 else
918 {
919 accessStream << "[" << columnNdx << "][" << rowNdx << "]";
920 }
921
922 accessStr = accessStream.str();
923 }
924
925 if (rowNdx < componentCount && !m_testMissingComponents)
926 {
927 if (isVertexFormatSint(attributeInfo.vkType))
928 {
929 if (isVertexFormatPacked(attributeInfo.vkType))
930 {
931 const deInt32 maxIntValue = (1 << (getPackedVertexFormatComponentWidth(attributeInfo.vkType, orderNdx) - 1)) - 1;
932 const deInt32 minIntValue = -maxIntValue;
933
934 glslCode << indentStr << "if (" << accessStr << " == clamp(-(" << totalComponentCount << " * " << indexId << " + " << componentIndex << "), " << minIntValue << ", " << maxIntValue << "))\n";
935 }
936 else
937 glslCode << indentStr << "if (" << accessStr << " == -(" << totalComponentCount << " * " << indexId << " + " << componentIndex << "))\n";
938 }
939 else if (isVertexFormatUint(attributeInfo.vkType))
940 {
941 if (isVertexFormatPacked(attributeInfo.vkType))
942 {
943 const deUint32 maxUintValue = (1 << getPackedVertexFormatComponentWidth(attributeInfo.vkType, orderNdx)) - 1;
944
945 glslCode << indentStr << "if (" << accessStr << " == clamp(uint(" << totalComponentCount << " * " << indexId << " + " << componentIndex << "), 0, " << maxUintValue << "))\n";
946 }
947 else
948 glslCode << indentStr << "if (" << accessStr << " == uint(" << totalComponentCount << " * " << indexId << " + " << componentIndex << "))\n";
949 }
950 else if (isVertexFormatSfloat(attributeInfo.vkType))
951 {
952 const auto& basicType = VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].basicType;
953
954 if (basicType == VertexInputTest::GLSL_BASIC_TYPE_DOUBLE)
955 {
956 glslCode << indentStr << "if (abs(" << accessStr << " + double(0.01 * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < double(" << threshold[rowNdx] << "))\n";
957 }
958 else if (basicType == VertexInputTest::GLSL_BASIC_TYPE_FLOAT16)
959 {
960 glslCode << indentStr << "if (abs(" << accessStr << " + float16_t(0.01HF * (" << totalComponentCount << ".0HF * float16_t(" << indexId << ") + " << componentIndex << ".0HF))) < float16_t(" << threshold[rowNdx] << "HF))\n";
961 }
962 else
963 {
964 glslCode << indentStr << "if (abs(" << accessStr << " + (0.01 * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n";
965 }
966 }
967 else if (isVertexFormatSscaled(attributeInfo.vkType))
968 {
969 if (isVertexFormatPacked(attributeInfo.vkType))
970 {
971 const float maxScaledValue = float((1 << (getPackedVertexFormatComponentWidth(attributeInfo.vkType, orderNdx) - 1)) - 1);
972 const float minScaledValue = -maxScaledValue - 1.0f;
973
974 glslCode << indentStr << "if (abs(" << accessStr << " + clamp(" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0, " << minScaledValue << ", " << maxScaledValue << ")) < " << threshold[orderNdx] << ")\n";
975 }
976 else
977 glslCode << indentStr << "if (abs(" << accessStr << " + (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0)) < " << threshold[rowNdx] << ")\n";
978 }
979 else if (isVertexFormatUscaled(attributeInfo.vkType))
980 {
981 if (isVertexFormatPacked(attributeInfo.vkType))
982 {
983 const float maxScaledValue = float((1 << getPackedVertexFormatComponentWidth(attributeInfo.vkType, orderNdx)) - 1);
984
985 glslCode << indentStr << "if (abs(" << accessStr << " - clamp(" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0, 0, " << maxScaledValue << ")) < " << threshold[orderNdx] << ")\n";
986 }
987 else
988 glslCode << indentStr << "if (abs(" << accessStr << " - (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0)) < " << threshold[rowNdx] << ")\n";
989 }
990 else if (isVertexFormatSnorm(attributeInfo.vkType))
991 {
992 const float representableDiff = isVertexFormatPacked(attributeInfo.vkType) ? getRepresentableDifferenceSnormPacked(attributeInfo.vkType, orderNdx) : getRepresentableDifferenceSnorm(attributeInfo.vkType);
993
994 if(isVertexFormatPacked(attributeInfo.vkType))
995 glslCode << indentStr << "if (abs(" << accessStr << " - clamp((-1.0 + " << representableDiff << " * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0)), -1.0, 1.0)) < " << threshold[orderNdx] << ")\n";
996 else
997 glslCode << indentStr << "if (abs(" << accessStr << " - (-1.0 + " << representableDiff << " * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n";
998 }
999 else if (isVertexFormatUnorm(attributeInfo.vkType) || isVertexFormatSRGB(attributeInfo.vkType))
1000 {
1001 const float representableDiff = isVertexFormatPacked(attributeInfo.vkType) ? getRepresentableDifferenceUnormPacked(attributeInfo.vkType, orderNdx) : getRepresentableDifferenceUnorm(attributeInfo.vkType);
1002
1003 if (isVertexFormatPacked(attributeInfo.vkType))
1004 glslCode << indentStr << "if (abs(" << accessStr << " - " << "clamp((" << representableDiff << " * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0)), 0.0, 1.0)) < " << threshold[orderNdx] << ")\n";
1005 else
1006 glslCode << indentStr << "if (abs(" << accessStr << " - " << "(" << representableDiff << " * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n";
1007 }
1008 else if (isVertexFormatUfloat(attributeInfo.vkType))
1009 {
1010 const auto& basicType = VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].basicType;
1011
1012 if (basicType == VertexInputTest::GLSL_BASIC_TYPE_DOUBLE)
1013 {
1014 glslCode << indentStr << "if (abs(" << accessStr << " - double(0.01 * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < double(" << threshold[rowNdx] << "))\n";
1015 }
1016 else if (basicType == VertexInputTest::GLSL_BASIC_TYPE_FLOAT16)
1017 {
1018 glslCode << indentStr << "if (abs(" << accessStr << " - float16_t(0.01HF * (" << totalComponentCount << ".0HF * float16_t(" << indexId << ") + " << componentIndex << ".0HF))) < float16_t(" << threshold[rowNdx] << "HF))\n";
1019 }
1020 else
1021 {
1022 glslCode << indentStr << "if (abs(" << accessStr << " - (0.01 * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < (" << threshold[rowNdx] << "))\n";
1023 }
1024 }
1025 else
1026 {
1027 DE_ASSERT(false);
1028 }
1029
1030 glslCode << indentStr << "\tokCount++;\n\n";
1031
1032 componentIndex++;
1033 }
1034 else if (rowNdx >= componentCount && m_testMissingComponents)
1035 {
1036 const auto expectedValue = ((rowNdx == (kMaxComponents - 1)) ? 1u : 0u); // Color components are expanded with zeros and alpha with one.
1037 const auto& basicType = VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].basicType;
1038 std::string glslType;
1039
1040 switch (basicType)
1041 {
1042 case GLSL_BASIC_TYPE_INT: glslType = "int"; break;
1043 case GLSL_BASIC_TYPE_UINT: glslType = "uint"; break;
1044 case GLSL_BASIC_TYPE_FLOAT: glslType = "float"; break;
1045 case GLSL_BASIC_TYPE_DOUBLE: glslType = "double"; break;
1046 case GLSL_BASIC_TYPE_FLOAT16: glslType = "float16_t"; break;
1047 default:
1048 DE_ASSERT(false); break;
1049 }
1050
1051 glslCode << indentStr << "if (" << accessStr << " == " << glslType << "(" << expectedValue << "))\n";
1052 glslCode << indentStr << "\tokCount++;\n\n";
1053 }
1054 }
1055
1056 }
1057 return glslCode.str();
1058 }
1059
getFormatThreshold(VkFormat format)1060 tcu::Vec4 VertexInputTest::getFormatThreshold (VkFormat format)
1061 {
1062 using tcu::Vec4;
1063
1064 switch (format)
1065 {
1066 case VK_FORMAT_R32_SFLOAT:
1067 case VK_FORMAT_R32G32_SFLOAT:
1068 case VK_FORMAT_R32G32B32_SFLOAT:
1069 case VK_FORMAT_R32G32B32A32_SFLOAT:
1070 case VK_FORMAT_R64_SFLOAT:
1071 case VK_FORMAT_R64G64_SFLOAT:
1072 case VK_FORMAT_R64G64B64_SFLOAT:
1073 case VK_FORMAT_R64G64B64A64_SFLOAT:
1074 return Vec4(0.00001f);
1075
1076 default:
1077 break;
1078 }
1079
1080 if (isVertexFormatSnorm(format))
1081 {
1082 return (isVertexFormatPacked(format) ? Vec4(1.5f * getRepresentableDifferenceSnormPacked(format, 0),
1083 1.5f * getRepresentableDifferenceSnormPacked(format, 1),
1084 1.5f * getRepresentableDifferenceSnormPacked(format, 2),
1085 1.5f * getRepresentableDifferenceSnormPacked(format, 3))
1086 : Vec4(1.5f * getRepresentableDifferenceSnorm(format)));
1087 }
1088 else if (isVertexFormatUnorm(format))
1089 {
1090 return (isVertexFormatPacked(format) ? Vec4(1.5f * getRepresentableDifferenceUnormPacked(format, 0),
1091 1.5f * getRepresentableDifferenceUnormPacked(format, 1),
1092 1.5f * getRepresentableDifferenceUnormPacked(format, 2),
1093 1.5f * getRepresentableDifferenceUnormPacked(format, 3))
1094 : Vec4(1.5f * getRepresentableDifferenceUnorm(format)));
1095 } else if (isVertexFormatUfloat(format))
1096 {
1097 return Vec4(0.008f);
1098 }
1099
1100 return Vec4(0.001f);
1101 }
1102
VertexInputInstance(Context & context,const PipelineConstructionType pipelineConstructionType,const AttributeDescriptionList & attributeDescriptions,const std::vector<VkVertexInputBindingDescription> & bindingDescriptions,const std::vector<VkDeviceSize> & bindingOffsets)1103 VertexInputInstance::VertexInputInstance (Context& context,
1104 const PipelineConstructionType pipelineConstructionType,
1105 const AttributeDescriptionList& attributeDescriptions,
1106 const std::vector<VkVertexInputBindingDescription>& bindingDescriptions,
1107 const std::vector<VkDeviceSize>& bindingOffsets)
1108 : vkt::TestInstance (context)
1109 , m_renderSize (16, 16)
1110 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
1111 , m_graphicsPipeline (context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType)
1112 {
1113 DE_ASSERT(bindingDescriptions.size() == bindingOffsets.size());
1114
1115 const DeviceInterface& vk = context.getDeviceInterface();
1116 const VkDevice vkDevice = context.getDevice();
1117 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1118 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
1119 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
1120
1121 // Check upfront for unsupported features
1122 for (size_t attributeNdx = 0; attributeNdx < attributeDescriptions.size(); attributeNdx++)
1123 {
1124 const VkVertexInputAttributeDescription& attributeDescription = attributeDescriptions[attributeNdx].vkDescription;
1125 if (!isSupportedVertexFormat(context, attributeDescription.format))
1126 {
1127 throw tcu::NotSupportedError(std::string("Unsupported format for vertex input: ") + getFormatName(attributeDescription.format));
1128 }
1129 }
1130
1131 // Create color image
1132 {
1133 const VkImageCreateInfo colorImageParams =
1134 {
1135 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1136 DE_NULL, // const void* pNext;
1137 0u, // VkImageCreateFlags flags;
1138 VK_IMAGE_TYPE_2D, // VkImageType imageType;
1139 m_colorFormat, // VkFormat format;
1140 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
1141 1u, // deUint32 mipLevels;
1142 1u, // deUint32 arrayLayers;
1143 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1144 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1145 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
1146 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1147 1u, // deUint32 queueFamilyIndexCount;
1148 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
1149 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1150 };
1151
1152 m_colorImage = createImage(vk, vkDevice, &colorImageParams);
1153
1154 // Allocate and bind color image memory
1155 m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
1156 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
1157 }
1158
1159 // Create color attachment view
1160 {
1161 const VkImageViewCreateInfo colorAttachmentViewParams =
1162 {
1163 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
1164 DE_NULL, // const void* pNext;
1165 0u, // VkImageViewCreateFlags flags;
1166 *m_colorImage, // VkImage image;
1167 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
1168 m_colorFormat, // VkFormat format;
1169 componentMappingRGBA, // VkComponentMapping components;
1170 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
1171 };
1172
1173 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
1174 }
1175
1176 // Create render pass
1177 m_renderPass = RenderPassWrapper(pipelineConstructionType, vk, vkDevice, m_colorFormat);
1178
1179 // Create framebuffer
1180 {
1181 const VkFramebufferCreateInfo framebufferParams =
1182 {
1183 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
1184 DE_NULL, // const void* pNext;
1185 0u, // VkFramebufferCreateFlags flags;
1186 *m_renderPass, // VkRenderPass renderPass;
1187 1u, // deUint32 attachmentCount;
1188 &m_colorAttachmentView.get(), // const VkImageView* pAttachments;
1189 (deUint32)m_renderSize.x(), // deUint32 width;
1190 (deUint32)m_renderSize.y(), // deUint32 height;
1191 1u // deUint32 layers;
1192 };
1193
1194 m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, *m_colorImage);
1195 }
1196
1197 // Create pipeline layout
1198 {
1199 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1200 {
1201 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1202 DE_NULL, // const void* pNext;
1203 0u, // VkPipelineLayoutCreateFlags flags;
1204 0u, // deUint32 setLayoutCount;
1205 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
1206 0u, // deUint32 pushConstantRangeCount;
1207 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
1208 };
1209
1210 m_pipelineLayout = PipelineLayoutWrapper(pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
1211 }
1212
1213 m_vertexShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("attribute_test_vert"), 0);
1214 m_fragmentShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("attribute_test_frag"), 0);
1215
1216 // Create specialization constant
1217 deUint32 specializationData = static_cast<deUint32>(attributeDescriptions.size());
1218
1219 const VkSpecializationMapEntry specializationMapEntry =
1220 {
1221 0, // uint32_t constantID
1222 0, // uint32_t offset
1223 sizeof(specializationData), // uint32_t size
1224 };
1225 const VkSpecializationInfo specializationInfo =
1226 {
1227 1, // uint32_t mapEntryCount
1228 &specializationMapEntry, // const void* pMapEntries
1229 sizeof(specializationData), // size_t dataSize
1230 &specializationData // const void* pData
1231 };
1232
1233 // Create pipeline
1234 {
1235 // Create vertex attribute array and check if their VK formats are supported
1236 std::vector<VkVertexInputAttributeDescription> vkAttributeDescriptions;
1237 for (size_t attributeNdx = 0; attributeNdx < attributeDescriptions.size(); attributeNdx++)
1238 {
1239 const VkVertexInputAttributeDescription& attributeDescription = attributeDescriptions[attributeNdx].vkDescription;
1240 vkAttributeDescriptions.push_back(attributeDescription);
1241 }
1242
1243 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
1244 {
1245 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1246 DE_NULL, // const void* pNext;
1247 0u, // VkPipelineVertexInputStateCreateFlags flags;
1248 (deUint32)bindingDescriptions.size(), // deUint32 vertexBindingDescriptionCount;
1249 bindingDescriptions.data(), // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1250 (deUint32)vkAttributeDescriptions.size(), // deUint32 vertexAttributeDescriptionCount;
1251 vkAttributeDescriptions.data() // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1252 };
1253
1254 const std::vector<VkViewport> viewport { makeViewport(m_renderSize) };
1255 const std::vector<VkRect2D> scissor { makeRect2D(m_renderSize) };
1256
1257 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
1258 {
1259 false, // VkBool32 blendEnable;
1260 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
1261 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
1262 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
1263 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
1264 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
1265 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
1266 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask;
1267 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
1268 };
1269
1270 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
1271 {
1272 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
1273 DE_NULL, // const void* pNext;
1274 0u, // VkPipelineColorBlendStateCreateFlags flags;
1275 false, // VkBool32 logicOpEnable;
1276 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
1277 1u, // deUint32 attachmentCount;
1278 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
1279 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
1280 };
1281
1282 m_graphicsPipeline.setDefaultRasterizationState()
1283 .setDefaultDepthStencilState()
1284 .setDefaultMultisampleState()
1285 .setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
1286 .setupVertexInputState(&vertexInputStateParams)
1287 .setupPreRasterizationShaderState(viewport,
1288 scissor,
1289 m_pipelineLayout,
1290 *m_renderPass,
1291 0u,
1292 m_vertexShaderModule,
1293 DE_NULL,
1294 ShaderWrapper(),
1295 ShaderWrapper(),
1296 ShaderWrapper(),
1297 &specializationInfo)
1298 .setupFragmentShaderState(m_pipelineLayout,
1299 *m_renderPass,
1300 0u,
1301 m_fragmentShaderModule)
1302 .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateParams)
1303 .setMonolithicPipelineLayout(m_pipelineLayout)
1304 .buildPipeline();
1305 }
1306
1307 // Create vertex buffer
1308 {
1309 // calculate buffer size
1310 // 32 is maximal attribute size (4*sizeof(double)),
1311 // 8 maximal vertex count used in writeVertexInputData
1312 VkDeviceSize bufferSize = 32 * 8 * attributeDescriptions.size();
1313
1314 const VkBufferCreateInfo vertexBufferParams =
1315 {
1316 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1317 DE_NULL, // const void* pNext;
1318 0u, // VkBufferCreateFlags flags;
1319 bufferSize, // VkDeviceSize size;
1320 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
1321 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1322 1u, // deUint32 queueFamilyIndexCount;
1323 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
1324 };
1325
1326 // Upload data for each vertex input binding
1327 for (deUint32 bindingNdx = 0; bindingNdx < bindingDescriptions.size(); bindingNdx++)
1328 {
1329 Move<VkBuffer> vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
1330 de::MovePtr<Allocation> vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
1331
1332 VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset()));
1333
1334 writeVertexInputData((deUint8*)vertexBufferAlloc->getHostPtr(), bindingDescriptions[bindingNdx], bindingOffsets[bindingNdx], attributeDescriptions);
1335 flushAlloc(vk, vkDevice, *vertexBufferAlloc);
1336
1337 m_vertexBuffers.push_back(vertexBuffer.disown());
1338 m_vertexBufferAllocs.push_back(vertexBufferAlloc.release());
1339 }
1340 }
1341
1342 // Create command pool
1343 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1344
1345 // Create command buffer
1346 {
1347 const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
1348
1349 const VkImageMemoryBarrier attachmentLayoutBarrier =
1350 {
1351 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1352 DE_NULL, // const void* pNext;
1353 0u, // VkAccessFlags srcAccessMask;
1354 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
1355 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1356 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
1357 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1358 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1359 *m_colorImage, // VkImage image;
1360 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
1361 };
1362
1363 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1364
1365 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1366
1367 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0,
1368 0u, DE_NULL, 0u, DE_NULL, 1u, &attachmentLayoutBarrier);
1369
1370 m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
1371
1372 m_graphicsPipeline.bind(*m_cmdBuffer);
1373
1374 std::vector<VkBuffer> vertexBuffers;
1375 for (size_t bufferNdx = 0; bufferNdx < m_vertexBuffers.size(); bufferNdx++)
1376 vertexBuffers.push_back(m_vertexBuffers[bufferNdx]);
1377
1378 if (vertexBuffers.size() <= 1)
1379 {
1380 // One vertex buffer
1381 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, (deUint32)vertexBuffers.size(), vertexBuffers.data(), bindingOffsets.data());
1382 }
1383 else
1384 {
1385 // Smoke-test vkCmdBindVertexBuffers(..., startBinding, ... )
1386
1387 const deUint32 firstHalfLength = (deUint32)vertexBuffers.size() / 2;
1388 const deUint32 secondHalfLength = firstHalfLength + (deUint32)(vertexBuffers.size() % 2);
1389
1390 // Bind first half of vertex buffers
1391 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, firstHalfLength, vertexBuffers.data(), bindingOffsets.data());
1392
1393 // Bind second half of vertex buffers
1394 vk.cmdBindVertexBuffers(*m_cmdBuffer, firstHalfLength, secondHalfLength,
1395 vertexBuffers.data() + firstHalfLength,
1396 bindingOffsets.data() + firstHalfLength);
1397 }
1398
1399 vk.cmdDraw(*m_cmdBuffer, 4, 2, 0, 0);
1400
1401 m_renderPass.end(vk, *m_cmdBuffer);
1402 endCommandBuffer(vk, *m_cmdBuffer);
1403 }
1404 }
1405
~VertexInputInstance(void)1406 VertexInputInstance::~VertexInputInstance (void)
1407 {
1408 const DeviceInterface& vk = m_context.getDeviceInterface();
1409 const VkDevice vkDevice = m_context.getDevice();
1410
1411 for (size_t bufferNdx = 0; bufferNdx < m_vertexBuffers.size(); bufferNdx++)
1412 vk.destroyBuffer(vkDevice, m_vertexBuffers[bufferNdx], DE_NULL);
1413
1414 for (size_t allocNdx = 0; allocNdx < m_vertexBufferAllocs.size(); allocNdx++)
1415 delete m_vertexBufferAllocs[allocNdx];
1416 }
1417
writeVertexInputData(deUint8 * destPtr,const VkVertexInputBindingDescription & bindingDescription,const VkDeviceSize bindingOffset,const AttributeDescriptionList & attributes)1418 void VertexInputInstance::writeVertexInputData(deUint8* destPtr, const VkVertexInputBindingDescription& bindingDescription, const VkDeviceSize bindingOffset, const AttributeDescriptionList& attributes)
1419 {
1420 const deUint32 vertexCount = (bindingDescription.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) ? (4 * 2) : 2;
1421
1422 deUint8* destOffsetPtr = ((deUint8 *)destPtr) + bindingOffset;
1423 for (deUint32 vertexNdx = 0; vertexNdx < vertexCount; vertexNdx++)
1424 {
1425 for (size_t attributeNdx = 0; attributeNdx < attributes.size(); attributeNdx++)
1426 {
1427 const VertexInputAttributeDescription& attribDesc = attributes[attributeNdx];
1428
1429 // Only write vertex input data to bindings referenced by attribute descriptions
1430 if (attribDesc.vkDescription.binding == bindingDescription.binding)
1431 {
1432 writeVertexInputValue(destOffsetPtr + attribDesc.vkDescription.offset, attribDesc, vertexNdx);
1433 }
1434 }
1435 destOffsetPtr += bindingDescription.stride;
1436 }
1437 }
1438
writeVertexInputValueSint(deUint8 * destPtr,VkFormat format,int componentNdx,deInt32 value)1439 void writeVertexInputValueSint (deUint8* destPtr, VkFormat format, int componentNdx, deInt32 value)
1440 {
1441 const deUint32 componentSize = getVertexFormatComponentSize(format);
1442 deUint8* destFormatPtr = ((deUint8*)destPtr) + componentSize * componentNdx;
1443
1444 switch (componentSize)
1445 {
1446 case 1:
1447 *((deInt8*)destFormatPtr) = (deInt8)value;
1448 break;
1449
1450 case 2:
1451 *((deInt16*)destFormatPtr) = (deInt16)value;
1452 break;
1453
1454 case 4:
1455 *((deInt32*)destFormatPtr) = (deInt32)value;
1456 break;
1457
1458 default:
1459 DE_ASSERT(false);
1460 }
1461 }
1462
writeVertexInputValueIntPacked(deUint8 * destPtr,deUint32 & packedFormat,deUint32 & componentOffset,VkFormat format,deUint32 componentNdx,deUint32 value)1463 void writeVertexInputValueIntPacked(deUint8* destPtr, deUint32& packedFormat, deUint32& componentOffset, VkFormat format, deUint32 componentNdx, deUint32 value)
1464 {
1465 const deUint32 componentWidth = getPackedVertexFormatComponentWidth(format, componentNdx);
1466 const deUint32 componentCount = getVertexFormatComponentCount(format);
1467 const deUint32 usedBits = ~(deUint32)0 >> ((getVertexFormatSize(format) * 8) - componentWidth);
1468
1469 componentOffset -= componentWidth;
1470 packedFormat |= (((deUint32)value & usedBits) << componentOffset);
1471
1472 if (componentNdx == componentCount - 1)
1473 *((deUint32*)destPtr) = (deUint32)packedFormat;
1474 }
1475
writeVertexInputValueUint(deUint8 * destPtr,VkFormat format,int componentNdx,deUint32 value)1476 void writeVertexInputValueUint (deUint8* destPtr, VkFormat format, int componentNdx, deUint32 value)
1477 {
1478 const deUint32 componentSize = getVertexFormatComponentSize(format);
1479 deUint8* destFormatPtr = ((deUint8*)destPtr) + componentSize * componentNdx;
1480
1481 switch (componentSize)
1482 {
1483 case 1:
1484 *((deUint8 *)destFormatPtr) = (deUint8)value;
1485 break;
1486
1487 case 2:
1488 *((deUint16 *)destFormatPtr) = (deUint16)value;
1489 break;
1490
1491 case 4:
1492 *((deUint32 *)destFormatPtr) = (deUint32)value;
1493 break;
1494
1495 default:
1496 DE_ASSERT(false);
1497 }
1498 }
1499
writeVertexInputValueSfloat(deUint8 * destPtr,VkFormat format,int componentNdx,float value)1500 void writeVertexInputValueSfloat (deUint8* destPtr, VkFormat format, int componentNdx, float value)
1501 {
1502 const deUint32 componentSize = getVertexFormatComponentSize(format);
1503 deUint8* destFormatPtr = ((deUint8*)destPtr) + componentSize * componentNdx;
1504
1505 switch (componentSize)
1506 {
1507 case 2:
1508 {
1509 deFloat16 f16 = deFloat32To16(value);
1510 deMemcpy(destFormatPtr, &f16, sizeof(f16));
1511 break;
1512 }
1513
1514 case 4:
1515 deMemcpy(destFormatPtr, &value, sizeof(value));
1516 break;
1517
1518 default:
1519 DE_ASSERT(false);
1520 }
1521 }
1522
writeVertexInputValueUfloat(deUint8 * destPtr,deUint32 & packedFormat,deUint32 & componentOffset,VkFormat format,deUint32 componentNdx,float value)1523 void writeVertexInputValueUfloat (deUint8* destPtr, deUint32& packedFormat, deUint32& componentOffset, VkFormat format, deUint32 componentNdx, float value)
1524 {
1525 deFloat16 f16 = deFloat32To16(value);
1526
1527 const deUint32 componentWidth = getPackedVertexFormatComponentWidth(format, componentNdx);
1528 const deUint32 componentCount = getVertexFormatComponentCount(format);
1529 const deUint32 usedBits = ~(deUint32)0 >> ((getVertexFormatSize(format) * 8) - componentWidth);
1530 // The ufloat 10 or 11 has no sign bit, but the same exponent bits than float16.
1531 // The sign bit will be removed by the mask. Therefore we pick one more mantissa bit.
1532 deUint32 valueUFloat = f16 >> (16 - componentWidth - 1);
1533
1534 // TODO: VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 not supported.
1535 DE_ASSERT(format == VK_FORMAT_B10G11R11_UFLOAT_PACK32);
1536
1537 componentOffset -= componentWidth;
1538 packedFormat |= (valueUFloat & usedBits) << componentOffset;
1539
1540 if (componentNdx == componentCount - 1)
1541 *((deUint32*)destPtr) = (deUint32)packedFormat;
1542 }
1543
1544
writeVertexInputValue(deUint8 * destPtr,const VertexInputAttributeDescription & attribute,int indexId)1545 void VertexInputInstance::writeVertexInputValue (deUint8* destPtr, const VertexInputAttributeDescription& attribute, int indexId)
1546 {
1547 const int vertexInputCount = VertexInputTest::s_glslTypeDescriptions[attribute.glslType].vertexInputCount;
1548 const int componentCount = VertexInputTest::s_glslTypeDescriptions[attribute.glslType].vertexInputComponentCount;
1549 const deUint32 totalComponentCount = componentCount * vertexInputCount;
1550 const deUint32 vertexInputIndex = indexId * totalComponentCount + attribute.vertexInputIndex * componentCount;
1551 const bool hasBGROrder = isVertexFormatComponentOrderBGR(attribute.vkDescription.format);
1552 const bool hasABGROrder = isVertexFormatComponentOrderABGR(attribute.vkDescription.format);
1553 const bool hasARGBOrder = isVertexFormatComponentOrderARGB(attribute.vkDescription.format);
1554 deUint32 componentOffset = getVertexFormatSize(attribute.vkDescription.format) * 8;
1555 deUint32 packedFormat32 = 0;
1556 deUint32 swizzledNdx;
1557
1558 const deUint32 BGRSwizzle[] = { 2, 1, 0, 3 };
1559 const deUint32 ABGRSwizzle[] = { 3, 2, 1, 0 };
1560 const deUint32 ARGBSwizzle[] = { 3, 0, 1, 2 };
1561
1562 for (int componentNdx = 0; componentNdx < componentCount; componentNdx++)
1563 {
1564 if (hasABGROrder)
1565 swizzledNdx = ABGRSwizzle[componentNdx];
1566 else if (hasARGBOrder)
1567 swizzledNdx = ARGBSwizzle[componentNdx];
1568 else if (hasBGROrder)
1569 swizzledNdx = BGRSwizzle[componentNdx];
1570 else
1571 swizzledNdx = componentNdx;
1572
1573 const deInt32 maxIntValue = isVertexFormatPacked(attribute.vkDescription.format) ? (1 << (getPackedVertexFormatComponentWidth(attribute.vkDescription.format, componentNdx) - 1)) - 1 : (1 << (getVertexFormatComponentSize(attribute.vkDescription.format) * 8 - 1)) - 1;
1574 const deUint32 maxUintValue = isVertexFormatPacked(attribute.vkDescription.format) ? ((1 << getPackedVertexFormatComponentWidth(attribute.vkDescription.format, componentNdx)) - 1) : (1 << (getVertexFormatComponentSize(attribute.vkDescription.format) * 8 )) - 1;
1575 const deInt32 minIntValue = -maxIntValue;
1576 const deUint32 minUintValue = 0;
1577
1578 switch (attribute.glslType)
1579 {
1580 case VertexInputTest::GLSL_TYPE_INT:
1581 case VertexInputTest::GLSL_TYPE_IVEC2:
1582 case VertexInputTest::GLSL_TYPE_IVEC3:
1583 case VertexInputTest::GLSL_TYPE_IVEC4:
1584 {
1585 if (isVertexFormatPacked(attribute.vkDescription.format))
1586 writeVertexInputValueIntPacked(destPtr, packedFormat32, componentOffset, attribute.vkDescription.format, componentNdx, deClamp32(-(deInt32)(vertexInputIndex + swizzledNdx), minIntValue, maxIntValue));
1587 else
1588 writeVertexInputValueSint(destPtr, attribute.vkDescription.format, componentNdx, -(deInt32)(vertexInputIndex + swizzledNdx));
1589
1590 break;
1591 }
1592 case VertexInputTest::GLSL_TYPE_UINT:
1593 case VertexInputTest::GLSL_TYPE_UVEC2:
1594 case VertexInputTest::GLSL_TYPE_UVEC3:
1595 case VertexInputTest::GLSL_TYPE_UVEC4:
1596 {
1597 if (isVertexFormatPacked(attribute.vkDescription.format))
1598 writeVertexInputValueIntPacked(destPtr, packedFormat32, componentOffset, attribute.vkDescription.format, componentNdx, deClamp32(vertexInputIndex + swizzledNdx, minUintValue, maxUintValue));
1599 else
1600 writeVertexInputValueUint(destPtr, attribute.vkDescription.format, componentNdx, vertexInputIndex + swizzledNdx);
1601
1602 break;
1603 }
1604 case VertexInputTest::GLSL_TYPE_FLOAT:
1605 case VertexInputTest::GLSL_TYPE_VEC2:
1606 case VertexInputTest::GLSL_TYPE_VEC3:
1607 case VertexInputTest::GLSL_TYPE_VEC4:
1608 case VertexInputTest::GLSL_TYPE_MAT2:
1609 case VertexInputTest::GLSL_TYPE_MAT3:
1610 case VertexInputTest::GLSL_TYPE_MAT4:
1611 case VertexInputTest::GLSL_TYPE_F16:
1612 case VertexInputTest::GLSL_TYPE_F16VEC2:
1613 case VertexInputTest::GLSL_TYPE_F16VEC3:
1614 case VertexInputTest::GLSL_TYPE_F16VEC4:
1615 {
1616 if (isVertexFormatSfloat(attribute.vkDescription.format))
1617 {
1618 writeVertexInputValueSfloat(destPtr, attribute.vkDescription.format, componentNdx, -(0.01f * (float)(vertexInputIndex + swizzledNdx)));
1619 } else if (isVertexFormatUfloat(attribute.vkDescription.format))
1620 {
1621 writeVertexInputValueUfloat(destPtr, packedFormat32, componentOffset, attribute.vkDescription.format, componentNdx, 0.01f * (float)(vertexInputIndex + swizzledNdx));
1622 }
1623 else if (isVertexFormatSscaled(attribute.vkDescription.format))
1624 {
1625 if (isVertexFormatPacked(attribute.vkDescription.format))
1626 writeVertexInputValueIntPacked(destPtr, packedFormat32, componentOffset, attribute.vkDescription.format, componentNdx, deClamp32(-(deInt32)(vertexInputIndex + swizzledNdx), minIntValue, maxIntValue));
1627 else
1628 writeVertexInputValueSint(destPtr, attribute.vkDescription.format, componentNdx, -(deInt32)(vertexInputIndex + swizzledNdx));
1629 }
1630 else if (isVertexFormatUscaled(attribute.vkDescription.format) || isVertexFormatUnorm(attribute.vkDescription.format) || isVertexFormatSRGB(attribute.vkDescription.format))
1631 {
1632 if (isVertexFormatPacked(attribute.vkDescription.format))
1633 writeVertexInputValueIntPacked(destPtr, packedFormat32, componentOffset, attribute.vkDescription.format, componentNdx, deClamp32(vertexInputIndex + swizzledNdx, minUintValue, maxUintValue));
1634 else
1635 writeVertexInputValueUint(destPtr, attribute.vkDescription.format, componentNdx, vertexInputIndex + swizzledNdx);
1636 }
1637 else if (isVertexFormatSnorm(attribute.vkDescription.format))
1638 {
1639 if (isVertexFormatPacked(attribute.vkDescription.format))
1640 writeVertexInputValueIntPacked(destPtr, packedFormat32, componentOffset, attribute.vkDescription.format, componentNdx, deClamp32(minIntValue + (vertexInputIndex + swizzledNdx), minIntValue, maxIntValue));
1641 else
1642 writeVertexInputValueSint(destPtr, attribute.vkDescription.format, componentNdx, minIntValue + (vertexInputIndex + swizzledNdx));
1643 }
1644 else
1645 DE_ASSERT(false);
1646 break;
1647 }
1648 case VertexInputTest::GLSL_TYPE_DOUBLE:
1649 case VertexInputTest::GLSL_TYPE_DVEC2:
1650 case VertexInputTest::GLSL_TYPE_DVEC3:
1651 case VertexInputTest::GLSL_TYPE_DVEC4:
1652 case VertexInputTest::GLSL_TYPE_DMAT2:
1653 case VertexInputTest::GLSL_TYPE_DMAT3:
1654 case VertexInputTest::GLSL_TYPE_DMAT4:
1655 *(reinterpret_cast<double *>(destPtr) + componentNdx) = -0.01 * (vertexInputIndex + swizzledNdx);
1656
1657 break;
1658
1659 default:
1660 DE_ASSERT(false);
1661 }
1662 }
1663 }
1664
iterate(void)1665 tcu::TestStatus VertexInputInstance::iterate (void)
1666 {
1667 const DeviceInterface& vk = m_context.getDeviceInterface();
1668 const VkDevice vkDevice = m_context.getDevice();
1669 const VkQueue queue = m_context.getUniversalQueue();
1670
1671 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1672
1673 return verifyImage();
1674 }
1675
isCompatibleType(VkFormat format,GlslType glslType)1676 bool VertexInputTest::isCompatibleType (VkFormat format, GlslType glslType)
1677 {
1678 const GlslTypeDescription glslTypeDesc = s_glslTypeDescriptions[glslType];
1679
1680 if ((deUint32)s_glslTypeDescriptions[glslType].vertexInputComponentCount == getVertexFormatComponentCount(format))
1681 {
1682 switch (glslTypeDesc.basicType)
1683 {
1684 case GLSL_BASIC_TYPE_INT:
1685 return isVertexFormatSint(format);
1686
1687 case GLSL_BASIC_TYPE_UINT:
1688 return isVertexFormatUint(format);
1689
1690 case GLSL_BASIC_TYPE_FLOAT:
1691 return (isVertexFormatPacked(format) ? (getVertexFormatSize(format) <= 4) : getVertexFormatComponentSize(format) <= 4) && (isVertexFormatSfloat(format) ||
1692 isVertexFormatSnorm(format) || isVertexFormatUnorm(format) || isVertexFormatSscaled(format) || isVertexFormatUscaled(format) || isVertexFormatSRGB(format) ||
1693 isVertexFormatUfloat(format));
1694
1695 case GLSL_BASIC_TYPE_DOUBLE:
1696 return isVertexFormatSfloat(format) && getVertexFormatComponentSize(format) == 8;
1697
1698 case GLSL_BASIC_TYPE_FLOAT16:
1699 return ((isVertexFormatSfloat(format)/* || isVertexFormatSnorm(format) || isVertexFormatUnorm(format)*/) && getVertexFormatComponentSize(format) == 2);
1700
1701 default:
1702 DE_ASSERT(false);
1703 return false;
1704 }
1705 }
1706 else
1707 return false;
1708 }
1709
verifyImage(void)1710 tcu::TestStatus VertexInputInstance::verifyImage (void)
1711 {
1712 bool compareOk = false;
1713 const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat);
1714 tcu::TextureLevel reference (tcuColorFormat, m_renderSize.x(), m_renderSize.y());
1715 const tcu::PixelBufferAccess refRedSubregion (tcu::getSubregion(reference.getAccess(),
1716 deRoundFloatToInt32((float)m_renderSize.x() * 0.0f),
1717 deRoundFloatToInt32((float)m_renderSize.y() * 0.0f),
1718 deRoundFloatToInt32((float)m_renderSize.x() * 0.5f),
1719 deRoundFloatToInt32((float)m_renderSize.y() * 1.0f)));
1720 const tcu::PixelBufferAccess refBlueSubregion (tcu::getSubregion(reference.getAccess(),
1721 deRoundFloatToInt32((float)m_renderSize.x() * 0.5f),
1722 deRoundFloatToInt32((float)m_renderSize.y() * 0.0f),
1723 deRoundFloatToInt32((float)m_renderSize.x() * 0.5f),
1724 deRoundFloatToInt32((float)m_renderSize.y() * 1.0f)));
1725
1726 // Create reference image
1727 tcu::clear(reference.getAccess(), defaultClearColor(tcuColorFormat));
1728 tcu::clear(refRedSubregion, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1729 tcu::clear(refBlueSubregion, tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
1730
1731 // Compare result with reference image
1732 {
1733 const DeviceInterface& vk = m_context.getDeviceInterface();
1734 const VkDevice vkDevice = m_context.getDevice();
1735 const VkQueue queue = m_context.getUniversalQueue();
1736 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1737 SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1738 de::MovePtr<tcu::TextureLevel> result = readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize);
1739
1740 compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
1741 "IntImageCompare",
1742 "Image comparison",
1743 reference.getAccess(),
1744 result->getAccess(),
1745 tcu::UVec4(2, 2, 2, 2),
1746 tcu::IVec3(1, 1, 0),
1747 true,
1748 tcu::COMPARE_LOG_RESULT);
1749 }
1750
1751 if (compareOk)
1752 return tcu::TestStatus::pass("Result image matches reference");
1753 else
1754 return tcu::TestStatus::fail("Image mismatch");
1755 }
1756
getAttributeInfoCaseName(const VertexInputTest::AttributeInfo & attributeInfo)1757 std::string getAttributeInfoCaseName (const VertexInputTest::AttributeInfo& attributeInfo)
1758 {
1759 std::ostringstream caseName;
1760 const std::string formatName = getFormatName(attributeInfo.vkType);
1761
1762 caseName << "as_" << de::toLower(formatName.substr(10)) << "_rate_";
1763
1764 if (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX)
1765 caseName << "vertex";
1766 else
1767 caseName << "instance";
1768
1769 return caseName.str();
1770 }
1771
1772 struct CompatibleFormats
1773 {
1774 VertexInputTest::GlslType glslType;
1775 std::vector<VkFormat> compatibleVkFormats;
1776 };
1777
createSingleAttributeCases(tcu::TestCaseGroup * singleAttributeTests,PipelineConstructionType pipelineConstructionType,VertexInputTest::GlslType glslType)1778 void createSingleAttributeCases (tcu::TestCaseGroup* singleAttributeTests, PipelineConstructionType pipelineConstructionType, VertexInputTest::GlslType glslType)
1779 {
1780 const VkFormat vertexFormats[] =
1781 {
1782 // Required, unpacked
1783 VK_FORMAT_R8_UNORM,
1784 VK_FORMAT_R8_SNORM,
1785 VK_FORMAT_R8_UINT,
1786 VK_FORMAT_R8_SINT,
1787 VK_FORMAT_R8G8_UNORM,
1788 VK_FORMAT_R8G8_SNORM,
1789 VK_FORMAT_R8G8_UINT,
1790 VK_FORMAT_R8G8_SINT,
1791 VK_FORMAT_R8G8B8A8_UNORM,
1792 VK_FORMAT_R8G8B8A8_SNORM,
1793 VK_FORMAT_R8G8B8A8_UINT,
1794 VK_FORMAT_R8G8B8A8_SINT,
1795 VK_FORMAT_B8G8R8A8_UNORM,
1796 VK_FORMAT_R16_UNORM,
1797 VK_FORMAT_R16_SNORM,
1798 VK_FORMAT_R16_UINT,
1799 VK_FORMAT_R16_SINT,
1800 VK_FORMAT_R16_SFLOAT,
1801 VK_FORMAT_R16G16_UNORM,
1802 VK_FORMAT_R16G16_SNORM,
1803 VK_FORMAT_R16G16_UINT,
1804 VK_FORMAT_R16G16_SINT,
1805 VK_FORMAT_R16G16_SFLOAT,
1806 VK_FORMAT_R16G16B16_UNORM,
1807 VK_FORMAT_R16G16B16_SNORM,
1808 VK_FORMAT_R16G16B16_UINT,
1809 VK_FORMAT_R16G16B16_SINT,
1810 VK_FORMAT_R16G16B16_SFLOAT,
1811 VK_FORMAT_R16G16B16A16_UNORM,
1812 VK_FORMAT_R16G16B16A16_SNORM,
1813 VK_FORMAT_R16G16B16A16_UINT,
1814 VK_FORMAT_R16G16B16A16_SINT,
1815 VK_FORMAT_R16G16B16A16_SFLOAT,
1816 VK_FORMAT_R32_UINT,
1817 VK_FORMAT_R32_SINT,
1818 VK_FORMAT_R32_SFLOAT,
1819 VK_FORMAT_R32G32_UINT,
1820 VK_FORMAT_R32G32_SINT,
1821 VK_FORMAT_R32G32_SFLOAT,
1822 VK_FORMAT_R32G32B32_UINT,
1823 VK_FORMAT_R32G32B32_SINT,
1824 VK_FORMAT_R32G32B32_SFLOAT,
1825 VK_FORMAT_R32G32B32A32_UINT,
1826 VK_FORMAT_R32G32B32A32_SINT,
1827 VK_FORMAT_R32G32B32A32_SFLOAT,
1828
1829 // Scaled formats
1830 VK_FORMAT_R8G8_USCALED,
1831 VK_FORMAT_R8G8_SSCALED,
1832 VK_FORMAT_R16_USCALED,
1833 VK_FORMAT_R16_SSCALED,
1834 VK_FORMAT_R8G8B8_USCALED,
1835 VK_FORMAT_R8G8B8_SSCALED,
1836 VK_FORMAT_B8G8R8_USCALED,
1837 VK_FORMAT_B8G8R8_SSCALED,
1838 VK_FORMAT_R8G8B8A8_USCALED,
1839 VK_FORMAT_R8G8B8A8_SSCALED,
1840 VK_FORMAT_B8G8R8A8_USCALED,
1841 VK_FORMAT_B8G8R8A8_SSCALED,
1842 VK_FORMAT_R16G16_USCALED,
1843 VK_FORMAT_R16G16_SSCALED,
1844 VK_FORMAT_R16G16B16_USCALED,
1845 VK_FORMAT_R16G16B16_SSCALED,
1846 VK_FORMAT_R16G16B16A16_USCALED,
1847 VK_FORMAT_R16G16B16A16_SSCALED,
1848
1849 // SRGB formats
1850 VK_FORMAT_R8_SRGB,
1851 VK_FORMAT_R8G8_SRGB,
1852 VK_FORMAT_R8G8B8_SRGB,
1853 VK_FORMAT_B8G8R8_SRGB,
1854 VK_FORMAT_R8G8B8A8_SRGB,
1855 VK_FORMAT_B8G8R8A8_SRGB,
1856
1857 // Double formats
1858 VK_FORMAT_R64_SFLOAT,
1859 VK_FORMAT_R64G64_SFLOAT,
1860 VK_FORMAT_R64G64B64_SFLOAT,
1861 VK_FORMAT_R64G64B64A64_SFLOAT,
1862
1863 // Packed formats
1864 VK_FORMAT_A2R10G10B10_USCALED_PACK32,
1865 VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
1866 VK_FORMAT_A2R10G10B10_UINT_PACK32,
1867 VK_FORMAT_A2R10G10B10_SINT_PACK32,
1868 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
1869 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
1870 VK_FORMAT_A2R10G10B10_UNORM_PACK32,
1871 VK_FORMAT_A2R10G10B10_SNORM_PACK32,
1872 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
1873 VK_FORMAT_A2B10G10R10_SNORM_PACK32,
1874 VK_FORMAT_B10G11R11_UFLOAT_PACK32
1875 };
1876
1877 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); formatNdx++)
1878 {
1879 if (VertexInputTest::isCompatibleType(vertexFormats[formatNdx], glslType))
1880 {
1881 {
1882 // Create test case for RATE_VERTEX
1883 VertexInputTest::AttributeInfo attributeInfo;
1884 attributeInfo.vkType = vertexFormats[formatNdx];
1885 attributeInfo.glslType = glslType;
1886 attributeInfo.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
1887
1888 singleAttributeTests->addChild(new VertexInputTest(singleAttributeTests->getTestContext(),
1889 getAttributeInfoCaseName(attributeInfo),
1890 pipelineConstructionType,
1891 std::vector<VertexInputTest::AttributeInfo>(1, attributeInfo),
1892 VertexInputTest::BINDING_MAPPING_ONE_TO_ONE,
1893 VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED));
1894
1895 // Create test case for RATE_INSTANCE
1896 attributeInfo.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
1897
1898 singleAttributeTests->addChild(new VertexInputTest(singleAttributeTests->getTestContext(),
1899 getAttributeInfoCaseName(attributeInfo),
1900 pipelineConstructionType,
1901 std::vector<VertexInputTest::AttributeInfo>(1, attributeInfo),
1902 VertexInputTest::BINDING_MAPPING_ONE_TO_ONE,
1903 VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED));
1904 }
1905
1906 // Test accessing missing components to verify "Converstion to RGBA" is correctly applied.
1907 const auto& typeInfo = VertexInputTest::s_glslTypeDescriptions[glslType];
1908 if (typeInfo.vertexInputComponentCount < kMaxComponents && typeInfo.basicType != VertexInputTest::GLSL_BASIC_TYPE_DOUBLE)
1909 {
1910 // Create test case for RATE_VERTEX
1911 VertexInputTest::AttributeInfo attributeInfo;
1912 attributeInfo.vkType = vertexFormats[formatNdx];
1913 attributeInfo.glslType = glslType;
1914 attributeInfo.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
1915 const auto nameSuffix = "_missing_components";
1916
1917 singleAttributeTests->addChild(new VertexInputTest(singleAttributeTests->getTestContext(),
1918 getAttributeInfoCaseName(attributeInfo) + nameSuffix,
1919 pipelineConstructionType,
1920 std::vector<VertexInputTest::AttributeInfo>(1, attributeInfo),
1921 VertexInputTest::BINDING_MAPPING_ONE_TO_ONE,
1922 VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED,
1923 VertexInputTest::LAYOUT_SKIP_DISABLED,
1924 VertexInputTest::LAYOUT_ORDER_IN_ORDER,
1925 true));
1926
1927 // Create test case for RATE_INSTANCE
1928 attributeInfo.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
1929
1930 singleAttributeTests->addChild(new VertexInputTest(singleAttributeTests->getTestContext(),
1931 getAttributeInfoCaseName(attributeInfo) + nameSuffix,
1932 pipelineConstructionType,
1933 std::vector<VertexInputTest::AttributeInfo>(1, attributeInfo),
1934 VertexInputTest::BINDING_MAPPING_ONE_TO_ONE,
1935 VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED,
1936 VertexInputTest::LAYOUT_SKIP_DISABLED,
1937 VertexInputTest::LAYOUT_ORDER_IN_ORDER,
1938 true));
1939 }
1940 }
1941 }
1942 }
1943
createSingleAttributeTests(tcu::TestCaseGroup * singleAttributeTests,PipelineConstructionType pipelineConstructionType)1944 void createSingleAttributeTests (tcu::TestCaseGroup* singleAttributeTests, PipelineConstructionType pipelineConstructionType)
1945 {
1946 for (int glslTypeNdx = 0; glslTypeNdx < VertexInputTest::GLSL_TYPE_COUNT; glslTypeNdx++)
1947 {
1948 VertexInputTest::GlslType glslType = (VertexInputTest::GlslType)glslTypeNdx;
1949 addTestGroup(singleAttributeTests, VertexInputTest::s_glslTypeDescriptions[glslType].name, createSingleAttributeCases, pipelineConstructionType, glslType);
1950 }
1951 }
1952
1953 // Create all unique GlslType combinations recursively
createMultipleAttributeCases(PipelineConstructionType pipelineConstructionType,deUint32 depth,deUint32 firstNdx,CompatibleFormats * compatibleFormats,de::Random & randomFunc,tcu::TestCaseGroup & testGroup,VertexInputTest::BindingMapping bindingMapping,VertexInputTest::AttributeLayout attributeLayout,VertexInputTest::LayoutSkip layoutSkip,VertexInputTest::LayoutOrder layoutOrder,const std::vector<VertexInputTest::AttributeInfo> & attributeInfos=std::vector<VertexInputTest::AttributeInfo> (0))1954 void createMultipleAttributeCases (PipelineConstructionType pipelineConstructionType, deUint32 depth, deUint32 firstNdx, CompatibleFormats* compatibleFormats, de::Random& randomFunc, tcu::TestCaseGroup& testGroup, VertexInputTest::BindingMapping bindingMapping, VertexInputTest::AttributeLayout attributeLayout, VertexInputTest::LayoutSkip layoutSkip, VertexInputTest::LayoutOrder layoutOrder, const std::vector<VertexInputTest::AttributeInfo>& attributeInfos = std::vector<VertexInputTest::AttributeInfo>(0))
1955 {
1956 tcu::TestContext& testCtx = testGroup.getTestContext();
1957
1958 // Exclude double values, which are not included in vertexFormats
1959 for (deUint32 currentNdx = firstNdx; currentNdx < VertexInputTest::GLSL_TYPE_DOUBLE - depth; currentNdx++)
1960 {
1961 std::vector <VertexInputTest::AttributeInfo> newAttributeInfos = attributeInfos;
1962
1963 {
1964 VertexInputTest::AttributeInfo attributeInfo;
1965 attributeInfo.glslType = (VertexInputTest::GlslType)currentNdx;
1966 attributeInfo.inputRate = (depth % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
1967 attributeInfo.vkType = VK_FORMAT_UNDEFINED;
1968
1969 newAttributeInfos.push_back(attributeInfo);
1970 }
1971
1972 // Add test case
1973 if (depth == 0)
1974 {
1975 // Select a random compatible format for each attribute
1976 for (size_t i = 0; i < newAttributeInfos.size(); i++)
1977 {
1978 const std::vector<VkFormat>& formats = compatibleFormats[newAttributeInfos[i].glslType].compatibleVkFormats;
1979 newAttributeInfos[i].vkType = formats[randomFunc.getUint32() % formats.size()];
1980 }
1981
1982 const std::string caseName = VertexInputTest::s_glslTypeDescriptions[currentNdx].name;
1983
1984 testGroup.addChild(new VertexInputTest(testCtx, caseName, pipelineConstructionType, newAttributeInfos, bindingMapping, attributeLayout, layoutSkip, layoutOrder));
1985 }
1986 // Add test group
1987 else
1988 {
1989 const std::string name = VertexInputTest::s_glslTypeDescriptions[currentNdx].name;
1990 de::MovePtr<tcu::TestCaseGroup> newTestGroup (new tcu::TestCaseGroup(testCtx, name.c_str()));
1991
1992 createMultipleAttributeCases(pipelineConstructionType, depth - 1u, currentNdx + 1u, compatibleFormats, randomFunc, *newTestGroup, bindingMapping, attributeLayout, layoutSkip, layoutOrder, newAttributeInfos);
1993 testGroup.addChild(newTestGroup.release());
1994 }
1995 }
1996 }
1997
createMultipleAttributeTests(tcu::TestCaseGroup * multipleAttributeTests,PipelineConstructionType pipelineConstructionType)1998 void createMultipleAttributeTests (tcu::TestCaseGroup* multipleAttributeTests, PipelineConstructionType pipelineConstructionType)
1999 {
2000 // Required vertex formats, unpacked
2001 const VkFormat vertexFormats[] =
2002 {
2003 VK_FORMAT_R8_UNORM,
2004 VK_FORMAT_R8_SNORM,
2005 VK_FORMAT_R8_UINT,
2006 VK_FORMAT_R8_SINT,
2007 VK_FORMAT_R8G8_UNORM,
2008 VK_FORMAT_R8G8_SNORM,
2009 VK_FORMAT_R8G8_UINT,
2010 VK_FORMAT_R8G8_SINT,
2011 VK_FORMAT_R8G8B8A8_UNORM,
2012 VK_FORMAT_R8G8B8A8_SNORM,
2013 VK_FORMAT_R8G8B8A8_UINT,
2014 VK_FORMAT_R8G8B8A8_SINT,
2015 VK_FORMAT_B8G8R8A8_UNORM,
2016 VK_FORMAT_R16_UNORM,
2017 VK_FORMAT_R16_SNORM,
2018 VK_FORMAT_R16_UINT,
2019 VK_FORMAT_R16_SINT,
2020 VK_FORMAT_R16_SFLOAT,
2021 VK_FORMAT_R16G16_UNORM,
2022 VK_FORMAT_R16G16_SNORM,
2023 VK_FORMAT_R16G16_UINT,
2024 VK_FORMAT_R16G16_SINT,
2025 VK_FORMAT_R16G16_SFLOAT,
2026 VK_FORMAT_R16G16B16_UNORM,
2027 VK_FORMAT_R16G16B16_SNORM,
2028 VK_FORMAT_R16G16B16_UINT,
2029 VK_FORMAT_R16G16B16_SINT,
2030 VK_FORMAT_R16G16B16_SFLOAT,
2031 VK_FORMAT_R16G16B16A16_UNORM,
2032 VK_FORMAT_R16G16B16A16_SNORM,
2033 VK_FORMAT_R16G16B16A16_UINT,
2034 VK_FORMAT_R16G16B16A16_SINT,
2035 VK_FORMAT_R16G16B16A16_SFLOAT,
2036 VK_FORMAT_R32_UINT,
2037 VK_FORMAT_R32_SINT,
2038 VK_FORMAT_R32_SFLOAT,
2039 VK_FORMAT_R32G32_UINT,
2040 VK_FORMAT_R32G32_SINT,
2041 VK_FORMAT_R32G32_SFLOAT,
2042 VK_FORMAT_R32G32B32_UINT,
2043 VK_FORMAT_R32G32B32_SINT,
2044 VK_FORMAT_R32G32B32_SFLOAT,
2045 VK_FORMAT_R32G32B32A32_UINT,
2046 VK_FORMAT_R32G32B32A32_SINT,
2047 VK_FORMAT_R32G32B32A32_SFLOAT
2048 };
2049
2050 const VertexInputTest::LayoutSkip layoutSkips[] =
2051 {
2052 VertexInputTest::LAYOUT_SKIP_DISABLED,
2053 VertexInputTest::LAYOUT_SKIP_ENABLED
2054 };
2055
2056 const VertexInputTest::LayoutOrder layoutOrders[] =
2057 {
2058 VertexInputTest::LAYOUT_ORDER_IN_ORDER,
2059 VertexInputTest::LAYOUT_ORDER_OUT_OF_ORDER
2060 };
2061
2062 // Find compatible VK formats for each GLSL vertex type
2063 CompatibleFormats compatibleFormats[VertexInputTest::GLSL_TYPE_COUNT];
2064 {
2065 for (int glslTypeNdx = 0; glslTypeNdx < VertexInputTest::GLSL_TYPE_COUNT; glslTypeNdx++)
2066 {
2067 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); formatNdx++)
2068 {
2069 if (VertexInputTest::isCompatibleType(vertexFormats[formatNdx], (VertexInputTest::GlslType)glslTypeNdx))
2070 compatibleFormats[glslTypeNdx].compatibleVkFormats.push_back(vertexFormats[formatNdx]);
2071 }
2072 }
2073 }
2074
2075 de::Random randomFunc(102030);
2076 tcu::TestContext& testCtx = multipleAttributeTests->getTestContext();
2077
2078 for (deUint32 layoutSkipNdx = 0; layoutSkipNdx < DE_LENGTH_OF_ARRAY(layoutSkips); layoutSkipNdx++)
2079 for (deUint32 layoutOrderNdx = 0; layoutOrderNdx < DE_LENGTH_OF_ARRAY(layoutOrders); layoutOrderNdx++)
2080 {
2081 const VertexInputTest::LayoutSkip layoutSkip = layoutSkips[layoutSkipNdx];
2082 const VertexInputTest::LayoutOrder layoutOrder = layoutOrders[layoutOrderNdx];
2083 de::MovePtr<tcu::TestCaseGroup> oneToOneAttributeTests(new tcu::TestCaseGroup(testCtx, "attributes"));
2084 de::MovePtr<tcu::TestCaseGroup> oneToManyAttributeTests(new tcu::TestCaseGroup(testCtx, "attributes"));
2085 de::MovePtr<tcu::TestCaseGroup> oneToManySequentialAttributeTests(new tcu::TestCaseGroup(testCtx, "attributes_sequential"));
2086
2087 if (layoutSkip == VertexInputTest::LAYOUT_SKIP_ENABLED && layoutOrder == VertexInputTest::LAYOUT_ORDER_OUT_OF_ORDER)
2088 continue;
2089
2090 createMultipleAttributeCases(pipelineConstructionType, 2u, 0u, compatibleFormats, randomFunc, *oneToOneAttributeTests, VertexInputTest::BINDING_MAPPING_ONE_TO_ONE, VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED, layoutSkip, layoutOrder);
2091 createMultipleAttributeCases(pipelineConstructionType, 2u, 0u, compatibleFormats, randomFunc, *oneToManyAttributeTests, VertexInputTest::BINDING_MAPPING_ONE_TO_MANY, VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED, layoutSkip, layoutOrder);
2092 createMultipleAttributeCases(pipelineConstructionType, 2u, 0u, compatibleFormats, randomFunc, *oneToManySequentialAttributeTests, VertexInputTest::BINDING_MAPPING_ONE_TO_MANY, VertexInputTest::ATTRIBUTE_LAYOUT_SEQUENTIAL, layoutSkip, layoutOrder);
2093
2094 if (layoutSkip == VertexInputTest::LAYOUT_SKIP_ENABLED)
2095 {
2096 // Skip one layout after each attribute
2097 de::MovePtr<tcu::TestCaseGroup> layoutSkipTests(new tcu::TestCaseGroup(testCtx, "layout_skip"));
2098
2099 de::MovePtr<tcu::TestCaseGroup> bindingOneToOneTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_one", "Each attribute uses a unique binding"));
2100 bindingOneToOneTests->addChild(oneToOneAttributeTests.release());
2101 layoutSkipTests->addChild(bindingOneToOneTests.release());
2102
2103 de::MovePtr<tcu::TestCaseGroup> bindingOneToManyTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_many", "Attributes share the same binding"));
2104 bindingOneToManyTests->addChild(oneToManyAttributeTests.release());
2105 bindingOneToManyTests->addChild(oneToManySequentialAttributeTests.release());
2106 layoutSkipTests->addChild(bindingOneToManyTests.release());
2107 multipleAttributeTests->addChild(layoutSkipTests.release());
2108 }
2109 else if (layoutOrder == VertexInputTest::LAYOUT_ORDER_OUT_OF_ORDER)
2110 {
2111 de::MovePtr<tcu::TestCaseGroup> layoutOutOfOrderTests(new tcu::TestCaseGroup(testCtx, "out_of_order", "Layout slots out of order"));
2112
2113 de::MovePtr<tcu::TestCaseGroup> bindingOneToOneTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_one", "Each attribute uses a unique binding"));
2114 bindingOneToOneTests->addChild(oneToOneAttributeTests.release());
2115 layoutOutOfOrderTests->addChild(bindingOneToOneTests.release());
2116
2117 de::MovePtr<tcu::TestCaseGroup> bindingOneToManyTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_many", "Attributes share the same binding"));
2118 bindingOneToManyTests->addChild(oneToManyAttributeTests.release());
2119 bindingOneToManyTests->addChild(oneToManySequentialAttributeTests.release());
2120 layoutOutOfOrderTests->addChild(bindingOneToManyTests.release());
2121 multipleAttributeTests->addChild(layoutOutOfOrderTests.release());
2122 }
2123 else
2124 {
2125 de::MovePtr<tcu::TestCaseGroup> bindingOneToOneTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_one", "Each attribute uses a unique binding"));
2126 bindingOneToOneTests->addChild(oneToOneAttributeTests.release());
2127 multipleAttributeTests->addChild(bindingOneToOneTests.release());
2128
2129 de::MovePtr<tcu::TestCaseGroup> bindingOneToManyTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_many", "Attributes share the same binding"));
2130 bindingOneToManyTests->addChild(oneToManyAttributeTests.release());
2131 bindingOneToManyTests->addChild(oneToManySequentialAttributeTests.release());
2132 multipleAttributeTests->addChild(bindingOneToManyTests.release());
2133 }
2134 }
2135 }
2136
createMaxAttributeTests(tcu::TestCaseGroup * maxAttributeTests,PipelineConstructionType pipelineConstructionType)2137 void createMaxAttributeTests (tcu::TestCaseGroup* maxAttributeTests, PipelineConstructionType pipelineConstructionType)
2138 {
2139 // Required vertex formats, unpacked
2140 const VkFormat vertexFormats[] =
2141 {
2142 VK_FORMAT_R8_UNORM,
2143 VK_FORMAT_R8_SNORM,
2144 VK_FORMAT_R8_UINT,
2145 VK_FORMAT_R8_SINT,
2146 VK_FORMAT_R8G8_UNORM,
2147 VK_FORMAT_R8G8_SNORM,
2148 VK_FORMAT_R8G8_UINT,
2149 VK_FORMAT_R8G8_SINT,
2150 VK_FORMAT_R8G8B8A8_UNORM,
2151 VK_FORMAT_R8G8B8A8_SNORM,
2152 VK_FORMAT_R8G8B8A8_UINT,
2153 VK_FORMAT_R8G8B8A8_SINT,
2154 VK_FORMAT_B8G8R8A8_UNORM,
2155 VK_FORMAT_R16_UNORM,
2156 VK_FORMAT_R16_SNORM,
2157 VK_FORMAT_R16_UINT,
2158 VK_FORMAT_R16_SINT,
2159 VK_FORMAT_R16_SFLOAT,
2160 VK_FORMAT_R16G16_UNORM,
2161 VK_FORMAT_R16G16_SNORM,
2162 VK_FORMAT_R16G16_UINT,
2163 VK_FORMAT_R16G16_SINT,
2164 VK_FORMAT_R16G16_SFLOAT,
2165 VK_FORMAT_R16G16B16_UNORM,
2166 VK_FORMAT_R16G16B16_SNORM,
2167 VK_FORMAT_R16G16B16_UINT,
2168 VK_FORMAT_R16G16B16_SINT,
2169 VK_FORMAT_R16G16B16_SFLOAT,
2170 VK_FORMAT_R16G16B16A16_UNORM,
2171 VK_FORMAT_R16G16B16A16_SNORM,
2172 VK_FORMAT_R16G16B16A16_UINT,
2173 VK_FORMAT_R16G16B16A16_SINT,
2174 VK_FORMAT_R16G16B16A16_SFLOAT,
2175 VK_FORMAT_R32_UINT,
2176 VK_FORMAT_R32_SINT,
2177 VK_FORMAT_R32_SFLOAT,
2178 VK_FORMAT_R32G32_UINT,
2179 VK_FORMAT_R32G32_SINT,
2180 VK_FORMAT_R32G32_SFLOAT,
2181 VK_FORMAT_R32G32B32_UINT,
2182 VK_FORMAT_R32G32B32_SINT,
2183 VK_FORMAT_R32G32B32_SFLOAT,
2184 VK_FORMAT_R32G32B32A32_UINT,
2185 VK_FORMAT_R32G32B32A32_SINT,
2186 VK_FORMAT_R32G32B32A32_SFLOAT
2187 };
2188
2189 // VkPhysicalDeviceLimits::maxVertexInputAttributes is used when attributeCount is 0
2190 const deUint32 attributeCount[] = { 16, 32, 64, 128, 0 };
2191 tcu::TestContext& testCtx (maxAttributeTests->getTestContext());
2192 de::Random randomFunc (132030);
2193
2194 // Find compatible VK formats for each GLSL vertex type
2195 CompatibleFormats compatibleFormats[VertexInputTest::GLSL_TYPE_COUNT];
2196 {
2197 for (int glslTypeNdx = 0; glslTypeNdx < VertexInputTest::GLSL_TYPE_COUNT; glslTypeNdx++)
2198 {
2199 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); formatNdx++)
2200 {
2201 if (VertexInputTest::isCompatibleType(vertexFormats[formatNdx], (VertexInputTest::GlslType)glslTypeNdx))
2202 compatibleFormats[glslTypeNdx].compatibleVkFormats.push_back(vertexFormats[formatNdx]);
2203 }
2204 }
2205 }
2206
2207 for (deUint32 attributeCountNdx = 0; attributeCountNdx < DE_LENGTH_OF_ARRAY(attributeCount); attributeCountNdx++)
2208 {
2209 const std::string groupName = (attributeCount[attributeCountNdx] == 0 ? "query_max" : de::toString(attributeCount[attributeCountNdx])) + "_attributes";
2210 const std::string groupDesc = de::toString(attributeCount[attributeCountNdx]) + " vertex input attributes";
2211
2212 de::MovePtr<tcu::TestCaseGroup> numAttributeTests(new tcu::TestCaseGroup(testCtx, groupName.c_str()));
2213 de::MovePtr<tcu::TestCaseGroup> bindingOneToOneTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_one", "Each attribute uses a unique binding"));
2214 de::MovePtr<tcu::TestCaseGroup> bindingOneToManyTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_many", "Attributes share the same binding"));
2215
2216 std::vector<VertexInputTest::AttributeInfo> attributeInfos(attributeCount[attributeCountNdx]);
2217
2218 for (deUint32 attributeNdx = 0; attributeNdx < attributeCount[attributeCountNdx]; attributeNdx++)
2219 {
2220 // Use random glslTypes, each consuming one attribute location
2221 const VertexInputTest::GlslType glslType = (VertexInputTest::GlslType)(randomFunc.getUint32() % VertexInputTest::GLSL_TYPE_MAT2);
2222 const std::vector<VkFormat>& formats = compatibleFormats[glslType].compatibleVkFormats;
2223 const VkFormat format = formats[randomFunc.getUint32() % formats.size()];
2224
2225 attributeInfos[attributeNdx].glslType = glslType;
2226 attributeInfos[attributeNdx].inputRate = ((attributeCountNdx + attributeNdx) % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
2227 attributeInfos[attributeNdx].vkType = format;
2228 }
2229
2230 // Interleaved attribute layout
2231 bindingOneToOneTests->addChild(new VertexInputTest(testCtx, "interleaved", pipelineConstructionType, attributeInfos, VertexInputTest::BINDING_MAPPING_ONE_TO_ONE, VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED));
2232 // Interleaved attribute layout
2233 bindingOneToManyTests->addChild(new VertexInputTest(testCtx, "interleaved", pipelineConstructionType, attributeInfos, VertexInputTest::BINDING_MAPPING_ONE_TO_MANY, VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED));
2234 // Sequential attribute layout
2235 bindingOneToManyTests->addChild(new VertexInputTest(testCtx, "sequential", pipelineConstructionType, attributeInfos, VertexInputTest::BINDING_MAPPING_ONE_TO_MANY, VertexInputTest::ATTRIBUTE_LAYOUT_SEQUENTIAL));
2236
2237 numAttributeTests->addChild(bindingOneToOneTests.release());
2238 numAttributeTests->addChild(bindingOneToManyTests.release());
2239 maxAttributeTests->addChild(numAttributeTests.release());
2240 }
2241 }
2242
2243 } // anonymous
2244
createVertexInputTests(tcu::TestCaseGroup * vertexInputTests,PipelineConstructionType pipelineConstructionType)2245 void createVertexInputTests (tcu::TestCaseGroup* vertexInputTests, PipelineConstructionType pipelineConstructionType)
2246 {
2247 // Uses one attribute
2248 addTestGroup(vertexInputTests, "single_attribute", createSingleAttributeTests, pipelineConstructionType);
2249 // Uses more than one attribute
2250 addTestGroup(vertexInputTests, "multiple_attributes", createMultipleAttributeTests, pipelineConstructionType);
2251 // Implementations can use as many vertex input attributes as they advertise
2252 addTestGroup(vertexInputTests, "max_attributes", createMaxAttributeTests, pipelineConstructionType);
2253 }
2254
2255 } // pipeline
2256 } // vkt
2257