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