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