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 "vktPipelineCombinationsIterator.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 "tcuFloat.hpp"
40 #include "tcuImageCompare.hpp"
41 #include "deFloat16.h"
42 #include "deMemory.h"
43 #include "deStringUtil.hpp"
44 #include "deUniquePtr.hpp"
45
46 #include <sstream>
47 #include <vector>
48
49 namespace vkt
50 {
51 namespace pipeline
52 {
53
54 using namespace vk;
55
56 namespace
57 {
58
isSupportedVertexFormat(Context & context,VkFormat format)59 bool isSupportedVertexFormat (Context& context, VkFormat format)
60 {
61 if (isVertexFormatDouble(format) && !context.getDeviceFeatures().shaderFloat64)
62 return false;
63
64 VkFormatProperties formatProps;
65 deMemset(&formatProps, 0, sizeof(VkFormatProperties));
66 context.getInstanceInterface().getPhysicalDeviceFormatProperties(context.getPhysicalDevice(), format, &formatProps);
67
68 return (formatProps.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) != 0u;
69 }
70
getRepresentableDifferenceUnorm(VkFormat format)71 float getRepresentableDifferenceUnorm (VkFormat format)
72 {
73 DE_ASSERT(isVertexFormatUnorm(format) || isVertexFormatSRGB(format));
74
75 return 1.0f / float((1 << (getVertexFormatComponentSize(format) * 8)) - 1);
76 }
77
getRepresentableDifferenceSnorm(VkFormat format)78 float getRepresentableDifferenceSnorm (VkFormat format)
79 {
80 DE_ASSERT(isVertexFormatSnorm(format));
81
82 return 1.0f / float((1 << (getVertexFormatComponentSize(format) * 8 - 1)) - 1);
83 }
84
getNextMultipleOffset(deUint32 divisor,deUint32 value)85 deUint32 getNextMultipleOffset (deUint32 divisor, deUint32 value)
86 {
87 if (value % divisor == 0)
88 return 0;
89 else
90 return divisor - (value % divisor);
91 }
92
93 class VertexInputTest : public vkt::TestCase
94 {
95 public:
96 enum GlslType
97 {
98 GLSL_TYPE_INT,
99 GLSL_TYPE_IVEC2,
100 GLSL_TYPE_IVEC3,
101 GLSL_TYPE_IVEC4,
102
103 GLSL_TYPE_UINT,
104 GLSL_TYPE_UVEC2,
105 GLSL_TYPE_UVEC3,
106 GLSL_TYPE_UVEC4,
107
108 GLSL_TYPE_FLOAT,
109 GLSL_TYPE_VEC2,
110 GLSL_TYPE_VEC3,
111 GLSL_TYPE_VEC4,
112 GLSL_TYPE_MAT2,
113 GLSL_TYPE_MAT3,
114 GLSL_TYPE_MAT4,
115
116 GLSL_TYPE_DOUBLE,
117 GLSL_TYPE_DVEC2,
118 GLSL_TYPE_DVEC3,
119 GLSL_TYPE_DVEC4,
120 GLSL_TYPE_DMAT2,
121 GLSL_TYPE_DMAT3,
122 GLSL_TYPE_DMAT4,
123
124 GLSL_TYPE_COUNT
125 };
126
127 enum GlslBasicType
128 {
129 GLSL_BASIC_TYPE_INT,
130 GLSL_BASIC_TYPE_UINT,
131 GLSL_BASIC_TYPE_FLOAT,
132 GLSL_BASIC_TYPE_DOUBLE
133 };
134
135 enum BindingMapping
136 {
137 BINDING_MAPPING_ONE_TO_ONE, // Vertex input bindings will not contain data for more than one attribute.
138 BINDING_MAPPING_ONE_TO_MANY // Vertex input bindings can contain data for more than one attribute.
139 };
140
141 struct AttributeInfo
142 {
143 GlslType glslType;
144 VkFormat vkType;
145 VkVertexInputRate inputRate;
146 };
147
148 struct GlslTypeDescription
149 {
150 const char* name;
151 int vertexInputComponentCount;
152 int vertexInputCount;
153 GlslBasicType basicType;
154 };
155
156 static const GlslTypeDescription s_glslTypeDescriptions[GLSL_TYPE_COUNT];
157
158 VertexInputTest (tcu::TestContext& testContext,
159 const std::string& name,
160 const std::string& description,
161 const std::vector<AttributeInfo>& attributeInfos,
162 BindingMapping bindingMapping);
163
~VertexInputTest(void)164 virtual ~VertexInputTest (void) {}
165 virtual void initPrograms (SourceCollections& programCollection) const;
166 virtual TestInstance* createInstance (Context& context) const;
167 static bool isCompatibleType (VkFormat format, GlslType glslType);
168
169 private:
170 std::string getGlslInputDeclarations (void) const;
171 std::string getGlslVertexCheck (void) const;
172 std::string getGlslAttributeConditions (const AttributeInfo& attributeInfo, deUint32 attributeIndex) const;
173 static tcu::Vec4 getFormatThreshold (VkFormat format);
174
175 const std::vector<AttributeInfo> m_attributeInfos;
176 const BindingMapping m_bindingMapping;
177 bool m_usesDoubleType;
178 };
179
180 class GlslTypeCombinationsIterator : public CombinationsIterator< std::vector<VertexInputTest::GlslType> >
181 {
182 public:
183 GlslTypeCombinationsIterator (deUint32 numValues, deUint32 combinationSize);
~GlslTypeCombinationsIterator(void)184 virtual ~GlslTypeCombinationsIterator (void) {}
185
186 protected:
187 virtual std::vector<VertexInputTest::GlslType> getCombinationValue (const std::vector<deUint32>& combination);
188
189 private:
190 std::vector<VertexInputTest::GlslType> m_combinationValue;
191 };
192
193 class VertexInputInstance : public vkt::TestInstance
194 {
195 public:
196 struct VertexInputAttributeDescription
197 {
198 VertexInputTest::GlslType glslType;
199 int vertexInputIndex;
200 VkVertexInputAttributeDescription vkDescription;
201 };
202
203 typedef std::vector<VertexInputAttributeDescription> AttributeDescriptionList;
204
205 VertexInputInstance (Context& context,
206 const AttributeDescriptionList& attributeDescriptions,
207 const std::vector<VkVertexInputBindingDescription>& bindingDescriptions,
208 const std::vector<VkDeviceSize>& bindingOffsets);
209
210 virtual ~VertexInputInstance (void);
211 virtual tcu::TestStatus iterate (void);
212
213
214 static void writeVertexInputData (deUint8* destPtr, const VkVertexInputBindingDescription& bindingDescription, const VkDeviceSize bindingOffset, const AttributeDescriptionList& attributes);
215 static void writeVertexInputValue (deUint8* destPtr, const VertexInputAttributeDescription& attributes, int indexId);
216
217 private:
218 tcu::TestStatus verifyImage (void);
219
220 private:
221 std::vector<VkBuffer> m_vertexBuffers;
222 std::vector<Allocation*> m_vertexBufferAllocs;
223
224 const tcu::UVec2 m_renderSize;
225 const VkFormat m_colorFormat;
226
227 Move<VkImage> m_colorImage;
228 de::MovePtr<Allocation> m_colorImageAlloc;
229 Move<VkImage> m_depthImage;
230 Move<VkImageView> m_colorAttachmentView;
231 Move<VkRenderPass> m_renderPass;
232 Move<VkFramebuffer> m_framebuffer;
233
234 Move<VkShaderModule> m_vertexShaderModule;
235 Move<VkShaderModule> m_fragmentShaderModule;
236
237 Move<VkPipelineLayout> m_pipelineLayout;
238 Move<VkPipeline> m_graphicsPipeline;
239
240 Move<VkCommandPool> m_cmdPool;
241 Move<VkCommandBuffer> m_cmdBuffer;
242
243 Move<VkFence> m_fence;
244 };
245
246 const VertexInputTest::GlslTypeDescription VertexInputTest::s_glslTypeDescriptions[GLSL_TYPE_COUNT] =
247 {
248 { "int", 1, 1, GLSL_BASIC_TYPE_INT },
249 { "ivec2", 2, 1, GLSL_BASIC_TYPE_INT },
250 { "ivec3", 3, 1, GLSL_BASIC_TYPE_INT },
251 { "ivec4", 4, 1, GLSL_BASIC_TYPE_INT },
252
253 { "uint", 1, 1, GLSL_BASIC_TYPE_UINT },
254 { "uvec2", 2, 1, GLSL_BASIC_TYPE_UINT },
255 { "uvec3", 3, 1, GLSL_BASIC_TYPE_UINT },
256 { "uvec4", 4, 1, GLSL_BASIC_TYPE_UINT },
257
258 { "float", 1, 1, GLSL_BASIC_TYPE_FLOAT },
259 { "vec2", 2, 1, GLSL_BASIC_TYPE_FLOAT },
260 { "vec3", 3, 1, GLSL_BASIC_TYPE_FLOAT },
261 { "vec4", 4, 1, GLSL_BASIC_TYPE_FLOAT },
262 { "mat2", 2, 2, GLSL_BASIC_TYPE_FLOAT },
263 { "mat3", 3, 3, GLSL_BASIC_TYPE_FLOAT },
264 { "mat4", 4, 4, GLSL_BASIC_TYPE_FLOAT },
265
266 { "double", 1, 1, GLSL_BASIC_TYPE_DOUBLE },
267 { "dvec2", 2, 1, GLSL_BASIC_TYPE_DOUBLE },
268 { "dvec3", 3, 1, GLSL_BASIC_TYPE_DOUBLE },
269 { "dvec4", 4, 1, GLSL_BASIC_TYPE_DOUBLE },
270 { "dmat2", 2, 2, GLSL_BASIC_TYPE_DOUBLE },
271 { "dmat3", 3, 3, GLSL_BASIC_TYPE_DOUBLE },
272 { "dmat4", 4, 4, GLSL_BASIC_TYPE_DOUBLE }
273 };
274
275
VertexInputTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const std::vector<AttributeInfo> & attributeInfos,BindingMapping bindingMapping)276 VertexInputTest::VertexInputTest (tcu::TestContext& testContext,
277 const std::string& name,
278 const std::string& description,
279 const std::vector<AttributeInfo>& attributeInfos,
280 BindingMapping bindingMapping)
281
282 : vkt::TestCase (testContext, name, description)
283 , m_attributeInfos (attributeInfos)
284 , m_bindingMapping (bindingMapping)
285 {
286 m_usesDoubleType = false;
287
288 for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++)
289 {
290 if (s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].basicType == GLSL_BASIC_TYPE_DOUBLE)
291 {
292 m_usesDoubleType = true;
293 break;
294 }
295 }
296 }
297
createInstance(Context & context) const298 TestInstance* VertexInputTest::createInstance (Context& context) const
299 {
300 // Create enough binding descriptions with random offsets
301 std::vector<VkVertexInputBindingDescription> bindingDescriptions;
302 std::vector<VkDeviceSize> bindingOffsets;
303
304 for (size_t bindingNdx = 0; bindingNdx < m_attributeInfos.size() * 2; bindingNdx++)
305 {
306 // Use STEP_RATE_VERTEX in even bindings and STEP_RATE_INSTANCE in odd bindings
307 const VkVertexInputRate inputRate = (bindingNdx % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
308
309 // .strideInBytes will be updated when creating the attribute descriptions
310 const VkVertexInputBindingDescription bindingDescription =
311 {
312 (deUint32)bindingNdx, // deUint32 binding;
313 0, // deUint32 stride;
314 inputRate // VkVertexInputRate inputRate;
315 };
316
317 bindingDescriptions.push_back(bindingDescription);
318 bindingOffsets.push_back(4 * bindingNdx);
319 }
320
321 // Create attribute descriptions, assign them to bindings and update .strideInBytes
322 std::vector<VertexInputInstance::VertexInputAttributeDescription> attributeDescriptions;
323 deUint32 attributeLocation = 0;
324 std::vector<deUint32> attributeOffsets (bindingDescriptions.size(), 0);
325 std::vector<deUint32> attributeMaxSizes (bindingDescriptions.size(), 0);
326
327 for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++)
328 {
329 const AttributeInfo& attributeInfo = m_attributeInfos[attributeNdx];
330 const GlslTypeDescription& glslTypeDescription = s_glslTypeDescriptions[attributeInfo.glslType];
331 const deUint32 inputSize = getVertexFormatSize(attributeInfo.vkType);
332 deUint32 attributeBinding;
333
334 if (m_bindingMapping == BINDING_MAPPING_ONE_TO_ONE)
335 {
336 if (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX)
337 {
338 attributeBinding = (deUint32)attributeNdx * 2; // Odd binding number
339 }
340 else // attributeInfo.inputRate == VK_VERTEX_INPUT_STEP_RATE_INSTANCE
341 {
342 attributeBinding = (deUint32)attributeNdx * 2 + 1; // Even binding number
343 }
344 }
345 else // m_bindingMapping == BINDING_MAPPING_ONE_TO_MANY
346 {
347 if (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX)
348 {
349 attributeBinding = 0;
350 }
351 else // attributeInfo.inputRate == VK_VERTEX_INPUT_STEP_RATE_INSTANCE
352 {
353 attributeBinding = 1;
354 }
355 }
356
357 for (int descNdx = 0; descNdx < glslTypeDescription.vertexInputCount; descNdx++)
358 {
359 const deUint32 offsetToComponentAlignment = getNextMultipleOffset(getVertexFormatComponentSize(attributeInfo.vkType),
360 (deUint32)bindingOffsets[attributeBinding] + attributeOffsets[attributeBinding]);
361
362 attributeOffsets[attributeBinding] += offsetToComponentAlignment;
363
364 const VertexInputInstance::VertexInputAttributeDescription attributeDescription =
365 {
366 attributeInfo.glslType, // GlslType glslType;
367 descNdx, // int index;
368 {
369 attributeLocation, // deUint32 location;
370 attributeBinding, // deUint32 binding;
371 attributeInfo.vkType, // VkFormat format;
372 attributeOffsets[attributeBinding], // deUint32 offset;
373 },
374 };
375
376 bindingDescriptions[attributeBinding].stride += offsetToComponentAlignment + inputSize;
377 attributeOffsets[attributeBinding] += inputSize;
378 attributeMaxSizes[attributeBinding] = de::max(attributeMaxSizes[attributeBinding], getVertexFormatComponentSize(attributeInfo.vkType));
379
380 //double formats with more than 2 components will take 2 locations
381 const GlslType type = attributeInfo.glslType;
382 if ((type == GLSL_TYPE_DMAT2 || type == GLSL_TYPE_DMAT3 || type == GLSL_TYPE_DMAT4) &&
383 (attributeInfo.vkType == VK_FORMAT_R64G64B64_SFLOAT || attributeInfo.vkType == VK_FORMAT_R64G64B64A64_SFLOAT))
384 {
385 attributeLocation += 2;
386 }
387 else
388 attributeLocation++;
389
390 attributeDescriptions.push_back(attributeDescription);
391 }
392 }
393
394 // Make sure the stride results in aligned access
395 for (deUint32 bindingNdx = 0; bindingNdx < bindingDescriptions.size(); ++bindingNdx)
396 {
397 if (attributeMaxSizes[bindingNdx] > 0)
398 bindingDescriptions[bindingNdx].stride += getNextMultipleOffset(attributeMaxSizes[bindingNdx], bindingDescriptions[bindingNdx].stride);
399 }
400
401 return new VertexInputInstance(context, attributeDescriptions, bindingDescriptions, bindingOffsets);
402 }
403
initPrograms(SourceCollections & programCollection) const404 void VertexInputTest::initPrograms (SourceCollections& programCollection) const
405 {
406 std::ostringstream vertexSrc;
407
408 vertexSrc << "#version 440\n"
409 << getGlslInputDeclarations()
410 << "layout(location = 0) out highp vec4 vtxColor;\n"
411 << "out gl_PerVertex {\n"
412 << " vec4 gl_Position;\n"
413 << "};\n";
414
415 // NOTE: double abs(double x) undefined in glslang ??
416 if (m_usesDoubleType)
417 vertexSrc << "double abs (double x) { if (x < 0.0LF) return -x; else return x; }\n";
418
419 vertexSrc << "void main (void)\n"
420 << "{\n"
421 << getGlslVertexCheck()
422 << "}\n";
423
424 programCollection.glslSources.add("attribute_test_vert") << glu::VertexSource(vertexSrc.str());
425
426 programCollection.glslSources.add("attribute_test_frag") << glu::FragmentSource(
427 "#version 440\n"
428 "layout(location = 0) in highp vec4 vtxColor;\n"
429 "layout(location = 0) out highp vec4 fragColor;\n"
430 "void main (void)\n"
431 "{\n"
432 " fragColor = vtxColor;\n"
433 "}\n");
434 }
435
getGlslInputDeclarations(void) const436 std::string VertexInputTest::getGlslInputDeclarations (void) const
437 {
438 std::ostringstream glslInputs;
439 deUint32 location = 0;
440
441 for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++)
442 {
443 const GlslTypeDescription& glslTypeDesc = s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType];
444
445 glslInputs << "layout(location = " << location << ") in highp " << glslTypeDesc.name << " attr" << attributeNdx << ";\n";
446 location += glslTypeDesc.vertexInputCount;
447 }
448
449 return glslInputs.str();
450 }
451
getGlslVertexCheck(void) const452 std::string VertexInputTest::getGlslVertexCheck (void) const
453 {
454 std::ostringstream glslCode;
455 int totalInputComponentCount = 0;
456
457
458 glslCode << " int okCount = 0;\n";
459
460 for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++)
461 {
462 glslCode << getGlslAttributeConditions(m_attributeInfos[attributeNdx], (deUint32)attributeNdx);
463
464 const int vertexInputCount = VertexInputTest::s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].vertexInputCount;
465 totalInputComponentCount += vertexInputCount * VertexInputTest::s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].vertexInputComponentCount;
466 }
467
468 glslCode <<
469 " if (okCount == " << totalInputComponentCount << ")\n"
470 " {\n"
471 " if (gl_InstanceIndex == 0)\n"
472 " vtxColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
473 " else\n"
474 " vtxColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
475 " }\n"
476 " else\n"
477 " {\n"
478 " vtxColor = vec4(okCount / float(" << totalInputComponentCount << "), 0.0f, 0.0f, 1.0);\n" <<
479 " }\n\n"
480 " if (gl_InstanceIndex == 0)\n"
481 " {\n"
482 " if (gl_VertexIndex == 0) gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
483 " else if (gl_VertexIndex == 1) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n"
484 " else if (gl_VertexIndex == 2) gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
485 " else if (gl_VertexIndex == 3) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n"
486 " else gl_Position = vec4(0.0);\n"
487 " }\n"
488 " else\n"
489 " {\n"
490 " if (gl_VertexIndex == 0) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n"
491 " else if (gl_VertexIndex == 1) gl_Position = vec4(1.0, -1.0, 0.0, 1.0);\n"
492 " else if (gl_VertexIndex == 2) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n"
493 " else if (gl_VertexIndex == 3) gl_Position = vec4(1.0, 1.0, 0.0, 1.0);\n"
494 " else gl_Position = vec4(0.0);\n"
495 " }\n";
496
497 return glslCode.str();
498 }
499
getGlslAttributeConditions(const AttributeInfo & attributeInfo,deUint32 attributeIndex) const500 std::string VertexInputTest::getGlslAttributeConditions (const AttributeInfo& attributeInfo, deUint32 attributeIndex) const
501 {
502 std::ostringstream glslCode;
503 std::ostringstream attributeVar;
504 const std::string indexId = (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) ? "gl_VertexIndex" : "gl_InstanceIndex";
505 const int componentCount = VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputComponentCount;
506 const int vertexInputCount = VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputCount;
507 const deUint32 totalComponentCount = componentCount * vertexInputCount;
508 const tcu::Vec4 threshold = getFormatThreshold(attributeInfo.vkType);
509 deUint32 componentIndex = 0;
510
511 attributeVar << "attr" << attributeIndex;
512
513 glslCode << std::fixed;
514
515 for (int columnNdx = 0; columnNdx< vertexInputCount; columnNdx++)
516 {
517 for (int rowNdx = 0; rowNdx < componentCount; rowNdx++)
518 {
519 std::string accessStr;
520 {
521 // Build string representing the access to the attribute component
522 std::ostringstream accessStream;
523 accessStream << attributeVar.str();
524
525 if (vertexInputCount == 1)
526 {
527 if (componentCount > 1)
528 accessStream << "[" << rowNdx << "]";
529 }
530 else
531 {
532 accessStream << "[" << columnNdx << "][" << rowNdx << "]";
533 }
534
535 accessStr = accessStream.str();
536 }
537
538 if (isVertexFormatSint(attributeInfo.vkType))
539 {
540 glslCode << "\tif (" << accessStr << " == -(" << totalComponentCount << " * " << indexId << " + " << componentIndex << "))\n";
541 }
542 else if (isVertexFormatUint(attributeInfo.vkType))
543 {
544 glslCode << "\tif (" << accessStr << " == uint(" << totalComponentCount << " * " << indexId << " + " << componentIndex << "))\n";
545 }
546 else if (isVertexFormatSfloat(attributeInfo.vkType))
547 {
548 if (VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].basicType == VertexInputTest::GLSL_BASIC_TYPE_DOUBLE)
549 {
550 glslCode << "\tif (abs(" << accessStr << " + double(0.01 * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < double(" << threshold[rowNdx] << "))\n";
551 }
552 else
553 {
554 glslCode << "\tif (abs(" << accessStr << " + (0.01 * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n";
555 }
556 }
557 else if (isVertexFormatSscaled(attributeInfo.vkType))
558 {
559 glslCode << "\tif (abs(" << accessStr << " + (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0)) < " << threshold[rowNdx] << ")\n";
560 }
561 else if (isVertexFormatUscaled(attributeInfo.vkType))
562 {
563 glslCode << "\t if (abs(" << accessStr << " - (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0)) < " << threshold[rowNdx] << ")\n";
564 }
565 else if (isVertexFormatSnorm(attributeInfo.vkType))
566 {
567 const float representableDiff = getRepresentableDifferenceSnorm(attributeInfo.vkType);
568
569 glslCode << "\tif (abs(" << accessStr << " - (-1.0 + " << representableDiff << " * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n";
570 }
571 else if (isVertexFormatUnorm(attributeInfo.vkType) || isVertexFormatSRGB(attributeInfo.vkType))
572 {
573 const float representableDiff = getRepresentableDifferenceUnorm(attributeInfo.vkType);
574
575 glslCode << "\tif (abs(" << accessStr << " - " << "(" << representableDiff << " * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n";
576 }
577 else
578 {
579 DE_ASSERT(false);
580 }
581
582 glslCode << "\t\tokCount++;\n\n";
583
584 componentIndex++;
585 }
586 }
587 return glslCode.str();
588 }
589
getFormatThreshold(VkFormat format)590 tcu::Vec4 VertexInputTest::getFormatThreshold (VkFormat format)
591 {
592 using tcu::Vec4;
593
594 switch (format)
595 {
596 case VK_FORMAT_R32_SFLOAT:
597 case VK_FORMAT_R32G32_SFLOAT:
598 case VK_FORMAT_R32G32B32_SFLOAT:
599 case VK_FORMAT_R32G32B32A32_SFLOAT:
600 case VK_FORMAT_R64_SFLOAT:
601 case VK_FORMAT_R64G64_SFLOAT:
602 case VK_FORMAT_R64G64B64_SFLOAT:
603 case VK_FORMAT_R64G64B64A64_SFLOAT:
604 return Vec4(0.00001f);
605
606 default:
607 break;
608 }
609
610 if (isVertexFormatSnorm(format))
611 {
612 return Vec4(1.5f * getRepresentableDifferenceSnorm(format));
613 }
614 else if (isVertexFormatUnorm(format))
615 {
616 return Vec4(1.5f * getRepresentableDifferenceUnorm(format));
617 }
618
619 return Vec4(0.001f);
620 }
621
GlslTypeCombinationsIterator(deUint32 numValues,deUint32 combinationSize)622 GlslTypeCombinationsIterator::GlslTypeCombinationsIterator (deUint32 numValues, deUint32 combinationSize)
623 : CombinationsIterator< std::vector<VertexInputTest::GlslType> > (numValues, combinationSize)
624 , m_combinationValue (std::vector<VertexInputTest::GlslType>(combinationSize))
625 {
626 DE_ASSERT(numValues <= VertexInputTest::GLSL_TYPE_COUNT);
627 }
628
getCombinationValue(const std::vector<deUint32> & combination)629 std::vector<VertexInputTest::GlslType> GlslTypeCombinationsIterator::getCombinationValue (const std::vector<deUint32>& combination)
630 {
631 for (size_t combinationItemNdx = 0; combinationItemNdx < combination.size(); combinationItemNdx++)
632 m_combinationValue[combinationItemNdx] = (VertexInputTest::GlslType)combination[combinationItemNdx];
633
634 return m_combinationValue;
635 }
636
VertexInputInstance(Context & context,const AttributeDescriptionList & attributeDescriptions,const std::vector<VkVertexInputBindingDescription> & bindingDescriptions,const std::vector<VkDeviceSize> & bindingOffsets)637 VertexInputInstance::VertexInputInstance (Context& context,
638 const AttributeDescriptionList& attributeDescriptions,
639 const std::vector<VkVertexInputBindingDescription>& bindingDescriptions,
640 const std::vector<VkDeviceSize>& bindingOffsets)
641 : vkt::TestInstance (context)
642 , m_renderSize (16, 16)
643 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
644 {
645 DE_ASSERT(bindingDescriptions.size() == bindingOffsets.size());
646
647 const DeviceInterface& vk = context.getDeviceInterface();
648 const VkDevice vkDevice = context.getDevice();
649 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
650 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
651 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
652
653 // Create color image
654 {
655 const VkImageCreateInfo colorImageParams =
656 {
657 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
658 DE_NULL, // const void* pNext;
659 0u, // VkImageCreateFlags flags;
660 VK_IMAGE_TYPE_2D, // VkImageType imageType;
661 m_colorFormat, // VkFormat format;
662 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
663 1u, // deUint32 mipLevels;
664 1u, // deUint32 arrayLayers;
665 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
666 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
667 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
668 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
669 1u, // deUint32 queueFamilyIndexCount;
670 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
671 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
672 };
673
674 m_colorImage = createImage(vk, vkDevice, &colorImageParams);
675
676 // Allocate and bind color image memory
677 m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
678 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
679 }
680
681 // Create color attachment view
682 {
683 const VkImageViewCreateInfo colorAttachmentViewParams =
684 {
685 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
686 DE_NULL, // const void* pNext;
687 0u, // VkImageViewCreateFlags flags;
688 *m_colorImage, // VkImage image;
689 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
690 m_colorFormat, // VkFormat format;
691 componentMappingRGBA, // VkComponentMapping components;
692 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
693 };
694
695 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
696 }
697
698 // Create render pass
699 {
700 const VkAttachmentDescription colorAttachmentDescription =
701 {
702 0u, // VkAttachmentDescriptionFlags flags;
703 m_colorFormat, // VkFormat format;
704 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
705 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
706 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
707 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
708 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
709 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
710 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
711 };
712
713 const VkAttachmentReference colorAttachmentReference =
714 {
715 0u, // deUint32 attachment;
716 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
717 };
718
719 const VkSubpassDescription subpassDescription =
720 {
721 0u, // VkSubpassDescriptionFlags flags;
722 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
723 0u, // deUint32 inputAttachmentCount;
724 DE_NULL, // const VkAttachmentReference* pInputAttachments;
725 1u, // deUint32 colorAttachmentCount;
726 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments;
727 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
728 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
729 0u, // deUint32 preserveAttachmentCount;
730 DE_NULL // const VkAttachmentReference* pPreserveAttachments;
731 };
732
733 const VkRenderPassCreateInfo renderPassParams =
734 {
735 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
736 DE_NULL, // const void* pNext;
737 0u, // VkRenderPassCreateFlags flags;
738 1u, // deUint32 attachmentCount;
739 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments;
740 1u, // deUint32 subpassCount;
741 &subpassDescription, // const VkSubpassDescription* pSubpasses;
742 0u, // deUint32 dependencyCount;
743 DE_NULL // const VkSubpassDependency* pDependencies;
744 };
745
746 m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
747 }
748
749 // Create framebuffer
750 {
751 const VkFramebufferCreateInfo framebufferParams =
752 {
753 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
754 DE_NULL, // const void* pNext;
755 0u, // VkFramebufferCreateFlags flags;
756 *m_renderPass, // VkRenderPass renderPass;
757 1u, // deUint32 attachmentCount;
758 &m_colorAttachmentView.get(), // const VkImageView* pAttachments;
759 (deUint32)m_renderSize.x(), // deUint32 width;
760 (deUint32)m_renderSize.y(), // deUint32 height;
761 1u // deUint32 layers;
762 };
763
764 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
765 }
766
767 // Create pipeline layout
768 {
769 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
770 {
771 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
772 DE_NULL, // const void* pNext;
773 0u, // VkPipelineLayoutCreateFlags flags;
774 0u, // deUint32 setLayoutCount;
775 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
776 0u, // deUint32 pushConstantRangeCount;
777 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
778 };
779
780 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
781 }
782
783 m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("attribute_test_vert"), 0);
784 m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("attribute_test_frag"), 0);
785
786
787 // Create pipeline
788 {
789 const VkPipelineShaderStageCreateInfo shaderStageParams[2] =
790 {
791 {
792 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
793 DE_NULL, // const void* pNext;
794 0u, // VkPipelineShaderStageCreateFlags flags;
795 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
796 *m_vertexShaderModule, // VkShaderModule module;
797 "main", // const char* pName;
798 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
799 },
800 {
801 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
802 DE_NULL, // const void* pNext;
803 0u, // VkPipelineShaderStageCreateFlags flags;
804 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
805 *m_fragmentShaderModule, // VkShaderModule module;
806 "main", // const char* pName;
807 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
808 }
809 };
810
811 // Create vertex attribute array and check if their VK formats are supported
812 std::vector<VkVertexInputAttributeDescription> vkAttributeDescriptions;
813 for (size_t attributeNdx = 0; attributeNdx < attributeDescriptions.size(); attributeNdx++)
814 {
815 const VkVertexInputAttributeDescription& attributeDescription = attributeDescriptions[attributeNdx].vkDescription;
816
817 if (!isSupportedVertexFormat(context, attributeDescription.format))
818 throw tcu::NotSupportedError(std::string("Unsupported format for vertex input: ") + getFormatName(attributeDescription.format));
819
820 vkAttributeDescriptions.push_back(attributeDescription);
821 }
822
823 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
824 {
825 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
826 DE_NULL, // const void* pNext;
827 0u, // VkPipelineVertexInputStateCreateFlags flags;
828 (deUint32)bindingDescriptions.size(), // deUint32 vertexBindingDescriptionCount;
829 bindingDescriptions.data(), // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
830 (deUint32)vkAttributeDescriptions.size(), // deUint32 vertexAttributeDescriptionCount;
831 vkAttributeDescriptions.data() // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
832 };
833
834 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
835 {
836 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
837 DE_NULL, // const void* pNext;
838 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
839 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology;
840 false // VkBool32 primitiveRestartEnable;
841 };
842
843 const VkViewport viewport =
844 {
845 0.0f, // float x;
846 0.0f, // float y;
847 (float)m_renderSize.x(), // float width;
848 (float)m_renderSize.y(), // float height;
849 0.0f, // float minDepth;
850 1.0f // float maxDepth;
851 };
852
853 const VkRect2D scissor = { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } };
854
855 const VkPipelineViewportStateCreateInfo viewportStateParams =
856 {
857 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
858 DE_NULL, // const void* pNext;
859 0u, // VkPipelineViewportStateCreateFlags flags;
860 1u, // deUint32 viewportCount;
861 &viewport, // const VkViewport* pViewports;
862 1u, // deUint32 scissorCount;
863 &scissor // const VkRect2D* pScissors;
864 };
865
866 const VkPipelineRasterizationStateCreateInfo rasterStateParams =
867 {
868 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
869 DE_NULL, // const void* pNext;
870 0u, // VkPipelineRasterizationStateCreateFlags flags;
871 false, // VkBool32 depthClampEnable;
872 false, // VkBool32 rasterizerDiscardEnable;
873 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
874 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
875 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
876 VK_FALSE, // VkBool32 depthBiasEnable;
877 0.0f, // float depthBiasConstantFactor;
878 0.0f, // float depthBiasClamp;
879 0.0f, // float depthBiasSlopeFactor;
880 1.0f, // float lineWidth;
881 };
882
883 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
884 {
885 false, // VkBool32 blendEnable;
886 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
887 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
888 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
889 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
890 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
891 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
892 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask;
893 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
894 };
895
896 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
897 {
898 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
899 DE_NULL, // const void* pNext;
900 0u, // VkPipelineColorBlendStateCreateFlags flags;
901 false, // VkBool32 logicOpEnable;
902 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
903 1u, // deUint32 attachmentCount;
904 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
905 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
906 };
907
908 const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
909 {
910 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
911 DE_NULL, // const void* pNext;
912 0u, // VkPipelineMultisampleStateCreateFlags flags;
913 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
914 false, // VkBool32 sampleShadingEnable;
915 0.0f, // float minSampleShading;
916 DE_NULL, // const VkSampleMask* pSampleMask;
917 false, // VkBool32 alphaToCoverageEnable;
918 false // VkBool32 alphaToOneEnable;
919 };
920
921 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
922 {
923 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
924 DE_NULL, // const void* pNext;
925 0u, // VkPipelineDepthStencilStateCreateFlags flags;
926 false, // VkBool32 depthTestEnable;
927 false, // VkBool32 depthWriteEnable;
928 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
929 false, // VkBool32 depthBoundsTestEnable;
930 false, // VkBool32 stencilTestEnable;
931 // VkStencilOpState front;
932 {
933 VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
934 VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
935 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
936 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
937 0u, // deUint32 compareMask;
938 0u, // deUint32 writeMask;
939 0u, // deUint32 reference;
940 },
941 // VkStencilOpState back;
942 {
943 VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
944 VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
945 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
946 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
947 0u, // deUint32 compareMask;
948 0u, // deUint32 writeMask;
949 0u, // deUint32 reference;
950 },
951 0.0f, // float minDepthBounds;
952 1.0f, // float maxDepthBounds;
953 };
954
955 const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
956 {
957 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
958 DE_NULL, // const void* pNext;
959 0u, // VkPipelineCreateFlags flags;
960 2u, // deUint32 stageCount;
961 shaderStageParams, // const VkPipelineShaderStageCreateInfo* pStages;
962 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
963 &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
964 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
965 &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
966 &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
967 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
968 &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
969 &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
970 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
971 *m_pipelineLayout, // VkPipelineLayout layout;
972 *m_renderPass, // VkRenderPass renderPass;
973 0u, // deUint32 subpass;
974 0u, // VkPipeline basePipelineHandle;
975 0u // deInt32 basePipelineIndex;
976 };
977
978 m_graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
979 }
980
981 // Create vertex buffer
982 {
983 const VkBufferCreateInfo vertexBufferParams =
984 {
985 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
986 DE_NULL, // const void* pNext;
987 0u, // VkBufferCreateFlags flags;
988 4096u, // VkDeviceSize size;
989 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
990 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
991 1u, // deUint32 queueFamilyIndexCount;
992 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
993 };
994
995 // Upload data for each vertex input binding
996 for (deUint32 bindingNdx = 0; bindingNdx < bindingDescriptions.size(); bindingNdx++)
997 {
998 Move<VkBuffer> vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
999 de::MovePtr<Allocation> vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
1000
1001 VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset()));
1002
1003 writeVertexInputData((deUint8*)vertexBufferAlloc->getHostPtr(), bindingDescriptions[bindingNdx], bindingOffsets[bindingNdx], attributeDescriptions);
1004 flushMappedMemoryRange(vk, vkDevice, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferParams.size);
1005
1006 m_vertexBuffers.push_back(vertexBuffer.disown());
1007 m_vertexBufferAllocs.push_back(vertexBufferAlloc.release());
1008 }
1009 }
1010
1011 // Create command pool
1012 {
1013 const VkCommandPoolCreateInfo cmdPoolParams =
1014 {
1015 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
1016 DE_NULL, // const void* pNext;
1017 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCommandPoolCreateFlags flags;
1018 queueFamilyIndex, // deUint32 queueFamilyIndex;
1019 };
1020
1021 m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
1022 }
1023
1024 // Create command buffer
1025 {
1026 const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
1027 {
1028 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1029 DE_NULL, // const void* pNext;
1030 *m_cmdPool, // VkCommandPool commandPool;
1031 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
1032 1u // deUint32 bufferCount;
1033 };
1034
1035 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
1036 {
1037 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
1038 DE_NULL, // const void* pNext;
1039 0u, // VkCommandBufferUsageFlags flags;
1040 (const VkCommandBufferInheritanceInfo*)DE_NULL,
1041 };
1042
1043 const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
1044
1045 const VkRenderPassBeginInfo renderPassBeginInfo =
1046 {
1047 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
1048 DE_NULL, // const void* pNext;
1049 *m_renderPass, // VkRenderPass renderPass;
1050 *m_framebuffer, // VkFramebuffer framebuffer;
1051 { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } }, // VkRect2D renderArea;
1052 1u, // deUint32 clearValueCount;
1053 &attachmentClearValue // const VkClearValue* pClearValues;
1054 };
1055
1056 const VkImageMemoryBarrier attachmentLayoutBarrier =
1057 {
1058 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1059 DE_NULL, // const void* pNext;
1060 0u, // VkAccessFlags srcAccessMask;
1061 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
1062 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1063 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
1064 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1065 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1066 *m_colorImage, // VkImage image;
1067 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
1068 };
1069
1070 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
1071
1072 VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1073
1074 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
1075 0u, DE_NULL, 0u, DE_NULL, 1u, &attachmentLayoutBarrier);
1076
1077 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1078
1079 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
1080
1081 std::vector<VkBuffer> vertexBuffers;
1082 for (size_t bufferNdx = 0; bufferNdx < m_vertexBuffers.size(); bufferNdx++)
1083 vertexBuffers.push_back(m_vertexBuffers[bufferNdx]);
1084
1085 if (vertexBuffers.size() <= 1)
1086 {
1087 // One vertex buffer
1088 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, (deUint32)vertexBuffers.size(), vertexBuffers.data(), bindingOffsets.data());
1089 }
1090 else
1091 {
1092 // Smoke-test vkCmdBindVertexBuffers(..., startBinding, ... )
1093
1094 const deUint32 firstHalfLength = (deUint32)vertexBuffers.size() / 2;
1095 const deUint32 secondHalfLength = firstHalfLength + (deUint32)(vertexBuffers.size() % 2);
1096
1097 // Bind first half of vertex buffers
1098 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, firstHalfLength, vertexBuffers.data(), bindingOffsets.data());
1099
1100 // Bind second half of vertex buffers
1101 vk.cmdBindVertexBuffers(*m_cmdBuffer, firstHalfLength, secondHalfLength,
1102 vertexBuffers.data() + firstHalfLength,
1103 bindingOffsets.data() + firstHalfLength);
1104 }
1105
1106 vk.cmdDraw(*m_cmdBuffer, 4, 2, 0, 0);
1107
1108 vk.cmdEndRenderPass(*m_cmdBuffer);
1109 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1110 }
1111
1112 // Create fence
1113 {
1114 const VkFenceCreateInfo fenceParams =
1115 {
1116 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
1117 DE_NULL, // const void* pNext;
1118 0u // VkFenceCreateFlags flags;
1119 };
1120
1121 m_fence = createFence(vk, vkDevice, &fenceParams);
1122 }
1123 }
1124
~VertexInputInstance(void)1125 VertexInputInstance::~VertexInputInstance (void)
1126 {
1127 const DeviceInterface& vk = m_context.getDeviceInterface();
1128 const VkDevice vkDevice = m_context.getDevice();
1129
1130 for (size_t bufferNdx = 0; bufferNdx < m_vertexBuffers.size(); bufferNdx++)
1131 vk.destroyBuffer(vkDevice, m_vertexBuffers[bufferNdx], DE_NULL);
1132
1133 for (size_t allocNdx = 0; allocNdx < m_vertexBufferAllocs.size(); allocNdx++)
1134 delete m_vertexBufferAllocs[allocNdx];
1135 }
1136
writeVertexInputData(deUint8 * destPtr,const VkVertexInputBindingDescription & bindingDescription,const VkDeviceSize bindingOffset,const AttributeDescriptionList & attributes)1137 void VertexInputInstance::writeVertexInputData(deUint8* destPtr, const VkVertexInputBindingDescription& bindingDescription, const VkDeviceSize bindingOffset, const AttributeDescriptionList& attributes)
1138 {
1139 const deUint32 vertexCount = (bindingDescription.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) ? (4 * 2) : 2;
1140
1141 deUint8* destOffsetPtr = ((deUint8 *)destPtr) + bindingOffset;
1142 for (deUint32 vertexNdx = 0; vertexNdx < vertexCount; vertexNdx++)
1143 {
1144 for (size_t attributeNdx = 0; attributeNdx < attributes.size(); attributeNdx++)
1145 {
1146 const VertexInputAttributeDescription& attribDesc = attributes[attributeNdx];
1147
1148 // Only write vertex input data to bindings referenced by attribute descriptions
1149 if (attribDesc.vkDescription.binding == bindingDescription.binding)
1150 {
1151 writeVertexInputValue(destOffsetPtr + attribDesc.vkDescription.offset, attribDesc, vertexNdx);
1152 }
1153 }
1154 destOffsetPtr += bindingDescription.stride;
1155 }
1156 }
1157
writeVertexInputValueSint(deUint8 * destPtr,VkFormat format,int componentNdx,deInt32 value)1158 void writeVertexInputValueSint (deUint8* destPtr, VkFormat format, int componentNdx, deInt32 value)
1159 {
1160 const deUint32 componentSize = getVertexFormatComponentSize(format);
1161 deUint8* destFormatPtr = ((deUint8*)destPtr) + componentSize * componentNdx;
1162
1163 switch (componentSize)
1164 {
1165 case 1:
1166 *((deInt8*)destFormatPtr) = (deInt8)value;
1167 break;
1168
1169 case 2:
1170 *((deInt16*)destFormatPtr) = (deInt16)value;
1171 break;
1172
1173 case 4:
1174 *((deInt32*)destFormatPtr) = (deInt32)value;
1175 break;
1176
1177 default:
1178 DE_ASSERT(false);
1179 }
1180 }
1181
writeVertexInputValueUint(deUint8 * destPtr,VkFormat format,int componentNdx,deUint32 value)1182 void writeVertexInputValueUint (deUint8* destPtr, VkFormat format, int componentNdx, deUint32 value)
1183 {
1184 const deUint32 componentSize = getVertexFormatComponentSize(format);
1185 deUint8* destFormatPtr = ((deUint8*)destPtr) + componentSize * componentNdx;
1186
1187 switch (componentSize)
1188 {
1189 case 1:
1190 *((deUint8 *)destFormatPtr) = (deUint8)value;
1191 break;
1192
1193 case 2:
1194 *((deUint16 *)destFormatPtr) = (deUint16)value;
1195 break;
1196
1197 case 4:
1198 *((deUint32 *)destFormatPtr) = (deUint32)value;
1199 break;
1200
1201 default:
1202 DE_ASSERT(false);
1203 }
1204 }
1205
writeVertexInputValueSfloat(deUint8 * destPtr,VkFormat format,int componentNdx,float value)1206 void writeVertexInputValueSfloat (deUint8* destPtr, VkFormat format, int componentNdx, float value)
1207 {
1208 const deUint32 componentSize = getVertexFormatComponentSize(format);
1209 deUint8* destFormatPtr = ((deUint8*)destPtr) + componentSize * componentNdx;
1210
1211 switch (componentSize)
1212 {
1213 case 2:
1214 {
1215 deFloat16 f16 = deFloat32To16(value);
1216 deMemcpy(destFormatPtr, &f16, sizeof(f16));
1217 break;
1218 }
1219
1220 case 4:
1221 deMemcpy(destFormatPtr, &value, sizeof(value));
1222 break;
1223
1224 default:
1225 DE_ASSERT(false);
1226 }
1227 }
1228
writeVertexInputValue(deUint8 * destPtr,const VertexInputAttributeDescription & attribute,int indexId)1229 void VertexInputInstance::writeVertexInputValue (deUint8* destPtr, const VertexInputAttributeDescription& attribute, int indexId)
1230 {
1231 const int vertexInputCount = VertexInputTest::s_glslTypeDescriptions[attribute.glslType].vertexInputCount;
1232 const int componentCount = VertexInputTest::s_glslTypeDescriptions[attribute.glslType].vertexInputComponentCount;
1233 const deUint32 totalComponentCount = componentCount * vertexInputCount;
1234 const deUint32 vertexInputIndex = indexId * totalComponentCount + attribute.vertexInputIndex * componentCount;
1235 const bool hasBGROrder = isVertexFormatComponentOrderBGR(attribute.vkDescription.format);
1236 int swizzledNdx;
1237
1238 for (int componentNdx = 0; componentNdx < componentCount; componentNdx++)
1239 {
1240 if (hasBGROrder)
1241 {
1242 if (componentNdx == 0)
1243 swizzledNdx = 2;
1244 else if (componentNdx == 2)
1245 swizzledNdx = 0;
1246 else
1247 swizzledNdx = componentNdx;
1248 }
1249 else
1250 swizzledNdx = componentNdx;
1251
1252 switch (attribute.glslType)
1253 {
1254 case VertexInputTest::GLSL_TYPE_INT:
1255 case VertexInputTest::GLSL_TYPE_IVEC2:
1256 case VertexInputTest::GLSL_TYPE_IVEC3:
1257 case VertexInputTest::GLSL_TYPE_IVEC4:
1258 writeVertexInputValueSint(destPtr, attribute.vkDescription.format, componentNdx, -(deInt32)(vertexInputIndex + swizzledNdx));
1259 break;
1260
1261 case VertexInputTest::GLSL_TYPE_UINT:
1262 case VertexInputTest::GLSL_TYPE_UVEC2:
1263 case VertexInputTest::GLSL_TYPE_UVEC3:
1264 case VertexInputTest::GLSL_TYPE_UVEC4:
1265 writeVertexInputValueUint(destPtr, attribute.vkDescription.format, componentNdx, vertexInputIndex + swizzledNdx);
1266 break;
1267
1268 case VertexInputTest::GLSL_TYPE_FLOAT:
1269 case VertexInputTest::GLSL_TYPE_VEC2:
1270 case VertexInputTest::GLSL_TYPE_VEC3:
1271 case VertexInputTest::GLSL_TYPE_VEC4:
1272 case VertexInputTest::GLSL_TYPE_MAT2:
1273 case VertexInputTest::GLSL_TYPE_MAT3:
1274 case VertexInputTest::GLSL_TYPE_MAT4:
1275 if (isVertexFormatSfloat(attribute.vkDescription.format))
1276 {
1277 writeVertexInputValueSfloat(destPtr, attribute.vkDescription.format, componentNdx, -(0.01f * (float)(vertexInputIndex + swizzledNdx)));
1278 }
1279 else if (isVertexFormatSscaled(attribute.vkDescription.format))
1280 {
1281 writeVertexInputValueSint(destPtr, attribute.vkDescription.format, componentNdx, -(deInt32)(vertexInputIndex + swizzledNdx));
1282 }
1283 else if (isVertexFormatUscaled(attribute.vkDescription.format) || isVertexFormatUnorm(attribute.vkDescription.format) || isVertexFormatSRGB(attribute.vkDescription.format))
1284 {
1285 writeVertexInputValueUint(destPtr, attribute.vkDescription.format, componentNdx, vertexInputIndex + swizzledNdx);
1286 }
1287 else if (isVertexFormatSnorm(attribute.vkDescription.format))
1288 {
1289 const deInt32 minIntValue = -((1 << (getVertexFormatComponentSize(attribute.vkDescription.format) * 8 - 1))) + 1;
1290 writeVertexInputValueSint(destPtr, attribute.vkDescription.format, componentNdx, minIntValue + (vertexInputIndex + swizzledNdx));
1291 }
1292 else
1293 DE_ASSERT(false);
1294 break;
1295
1296 case VertexInputTest::GLSL_TYPE_DOUBLE:
1297 case VertexInputTest::GLSL_TYPE_DVEC2:
1298 case VertexInputTest::GLSL_TYPE_DVEC3:
1299 case VertexInputTest::GLSL_TYPE_DVEC4:
1300 case VertexInputTest::GLSL_TYPE_DMAT2:
1301 case VertexInputTest::GLSL_TYPE_DMAT3:
1302 case VertexInputTest::GLSL_TYPE_DMAT4:
1303 *(reinterpret_cast<double *>(destPtr) + componentNdx) = -0.01 * (vertexInputIndex + swizzledNdx);
1304
1305 break;
1306
1307 default:
1308 DE_ASSERT(false);
1309 }
1310 }
1311 }
1312
iterate(void)1313 tcu::TestStatus VertexInputInstance::iterate (void)
1314 {
1315 const DeviceInterface& vk = m_context.getDeviceInterface();
1316 const VkDevice vkDevice = m_context.getDevice();
1317 const VkQueue queue = m_context.getUniversalQueue();
1318 const VkSubmitInfo submitInfo =
1319 {
1320 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
1321 DE_NULL, // const void* pNext;
1322 0u, // deUint32 waitSemaphoreCount;
1323 DE_NULL, // const VkSemaphore* pWaitSemaphores;
1324 (const VkPipelineStageFlags*)DE_NULL,
1325 1u, // deUint32 commandBufferCount;
1326 &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
1327 0u, // deUint32 signalSemaphoreCount;
1328 DE_NULL // const VkSemaphore* pSignalSemaphores;
1329 };
1330
1331 VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
1332 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
1333 VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
1334
1335 return verifyImage();
1336 }
1337
isCompatibleType(VkFormat format,GlslType glslType)1338 bool VertexInputTest::isCompatibleType (VkFormat format, GlslType glslType)
1339 {
1340 const GlslTypeDescription glslTypeDesc = s_glslTypeDescriptions[glslType];
1341
1342 if ((deUint32)s_glslTypeDescriptions[glslType].vertexInputComponentCount == getVertexFormatComponentCount(format))
1343 {
1344 switch (glslTypeDesc.basicType)
1345 {
1346 case GLSL_BASIC_TYPE_INT:
1347 return isVertexFormatSint(format);
1348
1349 case GLSL_BASIC_TYPE_UINT:
1350 return isVertexFormatUint(format);
1351
1352 case GLSL_BASIC_TYPE_FLOAT:
1353 return getVertexFormatComponentSize(format) <= 4 && (isVertexFormatSfloat(format) || isVertexFormatSnorm(format) || isVertexFormatUnorm(format) || isVertexFormatSscaled(format) || isVertexFormatUscaled(format) || isVertexFormatSRGB(format));
1354
1355 case GLSL_BASIC_TYPE_DOUBLE:
1356 return isVertexFormatSfloat(format) && getVertexFormatComponentSize(format) == 8;
1357
1358 default:
1359 DE_ASSERT(false);
1360 return false;
1361 }
1362 }
1363 else
1364 return false;
1365 }
1366
verifyImage(void)1367 tcu::TestStatus VertexInputInstance::verifyImage (void)
1368 {
1369 bool compareOk = false;
1370 const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat);
1371 tcu::TextureLevel reference (tcuColorFormat, m_renderSize.x(), m_renderSize.y());
1372 const tcu::PixelBufferAccess refRedSubregion (tcu::getSubregion(reference.getAccess(),
1373 deRoundFloatToInt32((float)m_renderSize.x() * 0.0f),
1374 deRoundFloatToInt32((float)m_renderSize.y() * 0.0f),
1375 deRoundFloatToInt32((float)m_renderSize.x() * 0.5f),
1376 deRoundFloatToInt32((float)m_renderSize.y() * 1.0f)));
1377 const tcu::PixelBufferAccess refBlueSubregion (tcu::getSubregion(reference.getAccess(),
1378 deRoundFloatToInt32((float)m_renderSize.x() * 0.5f),
1379 deRoundFloatToInt32((float)m_renderSize.y() * 0.0f),
1380 deRoundFloatToInt32((float)m_renderSize.x() * 0.5f),
1381 deRoundFloatToInt32((float)m_renderSize.y() * 1.0f)));
1382
1383 // Create reference image
1384 tcu::clear(reference.getAccess(), defaultClearColor(tcuColorFormat));
1385 tcu::clear(refRedSubregion, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1386 tcu::clear(refBlueSubregion, tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
1387
1388 // Compare result with reference image
1389 {
1390 const DeviceInterface& vk = m_context.getDeviceInterface();
1391 const VkDevice vkDevice = m_context.getDevice();
1392 const VkQueue queue = m_context.getUniversalQueue();
1393 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1394 SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1395 de::MovePtr<tcu::TextureLevel> result = readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize);
1396
1397 compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
1398 "IntImageCompare",
1399 "Image comparison",
1400 reference.getAccess(),
1401 result->getAccess(),
1402 tcu::UVec4(2, 2, 2, 2),
1403 tcu::IVec3(1, 1, 0),
1404 true,
1405 tcu::COMPARE_LOG_RESULT);
1406 }
1407
1408 if (compareOk)
1409 return tcu::TestStatus::pass("Result image matches reference");
1410 else
1411 return tcu::TestStatus::fail("Image mismatch");
1412 }
1413
getAttributeInfoCaseName(const VertexInputTest::AttributeInfo & attributeInfo)1414 std::string getAttributeInfoCaseName (const VertexInputTest::AttributeInfo& attributeInfo)
1415 {
1416 std::ostringstream caseName;
1417 const std::string formatName = getFormatName(attributeInfo.vkType);
1418
1419 caseName << VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].name << "_as_" << de::toLower(formatName.substr(10)) << "_rate_";
1420
1421 if (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX)
1422 caseName << "vertex";
1423 else
1424 caseName << "instance";
1425
1426 return caseName.str();
1427 }
1428
getAttributeInfosCaseName(const std::vector<VertexInputTest::AttributeInfo> & attributeInfos)1429 std::string getAttributeInfosCaseName (const std::vector<VertexInputTest::AttributeInfo>& attributeInfos)
1430 {
1431 std::ostringstream caseName;
1432
1433 for (size_t attributeNdx = 0; attributeNdx < attributeInfos.size(); attributeNdx++)
1434 {
1435 caseName << getAttributeInfoCaseName(attributeInfos[attributeNdx]);
1436
1437 if (attributeNdx < attributeInfos.size() - 1)
1438 caseName << "-";
1439 }
1440
1441 return caseName.str();
1442 }
1443
getAttributeInfoDescription(const VertexInputTest::AttributeInfo & attributeInfo)1444 std::string getAttributeInfoDescription (const VertexInputTest::AttributeInfo& attributeInfo)
1445 {
1446 std::ostringstream caseDesc;
1447
1448 caseDesc << std::string(VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].name) << " from type " << getFormatName(attributeInfo.vkType) << " with ";
1449
1450 if (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX)
1451 caseDesc << "vertex input rate ";
1452 else
1453 caseDesc << "instance input rate ";
1454
1455 return caseDesc.str();
1456 }
1457
getAttributeInfosDescription(const std::vector<VertexInputTest::AttributeInfo> & attributeInfos)1458 std::string getAttributeInfosDescription (const std::vector<VertexInputTest::AttributeInfo>& attributeInfos)
1459 {
1460 std::ostringstream caseDesc;
1461
1462 caseDesc << "Uses vertex attributes:\n";
1463
1464 for (size_t attributeNdx = 0; attributeNdx < attributeInfos.size(); attributeNdx++)
1465 caseDesc << "\t- " << getAttributeInfoDescription (attributeInfos[attributeNdx]) << "\n";
1466
1467 return caseDesc.str();
1468 }
1469
1470 struct CompatibleFormats
1471 {
1472 VertexInputTest::GlslType glslType;
1473 std::vector<VkFormat> compatibleVkFormats;
1474 };
1475
createSingleAttributeTests(tcu::TestContext & testCtx)1476 de::MovePtr<tcu::TestCaseGroup> createSingleAttributeTests (tcu::TestContext& testCtx)
1477 {
1478 const VkFormat vertexFormats[] =
1479 {
1480 // Required, unpacked
1481 VK_FORMAT_R8_UNORM,
1482 VK_FORMAT_R8_SNORM,
1483 VK_FORMAT_R8_UINT,
1484 VK_FORMAT_R8_SINT,
1485 VK_FORMAT_R8G8_UNORM,
1486 VK_FORMAT_R8G8_SNORM,
1487 VK_FORMAT_R8G8_UINT,
1488 VK_FORMAT_R8G8_SINT,
1489 VK_FORMAT_R8G8B8A8_UNORM,
1490 VK_FORMAT_R8G8B8A8_SNORM,
1491 VK_FORMAT_R8G8B8A8_UINT,
1492 VK_FORMAT_R8G8B8A8_SINT,
1493 VK_FORMAT_B8G8R8A8_UNORM,
1494 VK_FORMAT_R16_UNORM,
1495 VK_FORMAT_R16_SNORM,
1496 VK_FORMAT_R16_UINT,
1497 VK_FORMAT_R16_SINT,
1498 VK_FORMAT_R16_SFLOAT,
1499 VK_FORMAT_R16G16_UNORM,
1500 VK_FORMAT_R16G16_SNORM,
1501 VK_FORMAT_R16G16_UINT,
1502 VK_FORMAT_R16G16_SINT,
1503 VK_FORMAT_R16G16_SFLOAT,
1504 VK_FORMAT_R16G16B16A16_UNORM,
1505 VK_FORMAT_R16G16B16A16_SNORM,
1506 VK_FORMAT_R16G16B16A16_UINT,
1507 VK_FORMAT_R16G16B16A16_SINT,
1508 VK_FORMAT_R16G16B16A16_SFLOAT,
1509 VK_FORMAT_R32_UINT,
1510 VK_FORMAT_R32_SINT,
1511 VK_FORMAT_R32_SFLOAT,
1512 VK_FORMAT_R32G32_UINT,
1513 VK_FORMAT_R32G32_SINT,
1514 VK_FORMAT_R32G32_SFLOAT,
1515 VK_FORMAT_R32G32B32_UINT,
1516 VK_FORMAT_R32G32B32_SINT,
1517 VK_FORMAT_R32G32B32_SFLOAT,
1518 VK_FORMAT_R32G32B32A32_UINT,
1519 VK_FORMAT_R32G32B32A32_SINT,
1520 VK_FORMAT_R32G32B32A32_SFLOAT,
1521
1522 // Scaled formats
1523 VK_FORMAT_R8G8_USCALED,
1524 VK_FORMAT_R8G8_SSCALED,
1525 VK_FORMAT_R16_USCALED,
1526 VK_FORMAT_R16_SSCALED,
1527 VK_FORMAT_R8G8B8_USCALED,
1528 VK_FORMAT_R8G8B8_SSCALED,
1529 VK_FORMAT_B8G8R8_USCALED,
1530 VK_FORMAT_B8G8R8_SSCALED,
1531 VK_FORMAT_R8G8B8A8_USCALED,
1532 VK_FORMAT_R8G8B8A8_SSCALED,
1533 VK_FORMAT_B8G8R8A8_USCALED,
1534 VK_FORMAT_B8G8R8A8_SSCALED,
1535 VK_FORMAT_R16G16_USCALED,
1536 VK_FORMAT_R16G16_SSCALED,
1537 VK_FORMAT_R16G16B16_USCALED,
1538 VK_FORMAT_R16G16B16_SSCALED,
1539 VK_FORMAT_R16G16B16A16_USCALED,
1540 VK_FORMAT_R16G16B16A16_SSCALED,
1541
1542 // SRGB formats
1543 VK_FORMAT_R8_SRGB,
1544 VK_FORMAT_R8G8_SRGB,
1545 VK_FORMAT_R8G8B8_SRGB,
1546 VK_FORMAT_B8G8R8_SRGB,
1547 VK_FORMAT_R8G8B8A8_SRGB,
1548 VK_FORMAT_B8G8R8A8_SRGB,
1549
1550 // Double formats
1551 VK_FORMAT_R64_SFLOAT,
1552 VK_FORMAT_R64G64_SFLOAT,
1553 VK_FORMAT_R64G64B64_SFLOAT,
1554 VK_FORMAT_R64G64B64A64_SFLOAT,
1555 };
1556
1557 de::MovePtr<tcu::TestCaseGroup> singleAttributeTests (new tcu::TestCaseGroup(testCtx, "single_attribute", "Uses one attribute"));
1558
1559 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); formatNdx++)
1560 {
1561 for (int glslTypeNdx = 0; glslTypeNdx < VertexInputTest::GLSL_TYPE_COUNT; glslTypeNdx++)
1562 {
1563 if (VertexInputTest::isCompatibleType(vertexFormats[formatNdx], (VertexInputTest::GlslType)glslTypeNdx))
1564 {
1565 // Create test case for RATE_VERTEX
1566 VertexInputTest::AttributeInfo attributeInfo;
1567 attributeInfo.vkType = vertexFormats[formatNdx];
1568 attributeInfo.glslType = (VertexInputTest::GlslType)glslTypeNdx;
1569 attributeInfo.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
1570
1571 singleAttributeTests->addChild(new VertexInputTest(testCtx,
1572 getAttributeInfoCaseName(attributeInfo),
1573 getAttributeInfoDescription(attributeInfo),
1574 std::vector<VertexInputTest::AttributeInfo>(1, attributeInfo),
1575 VertexInputTest::BINDING_MAPPING_ONE_TO_ONE));
1576
1577 // Create test case for RATE_INSTANCE
1578 attributeInfo.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
1579
1580 singleAttributeTests->addChild(new VertexInputTest(testCtx,
1581 getAttributeInfoCaseName(attributeInfo),
1582 getAttributeInfoDescription(attributeInfo),
1583 std::vector<VertexInputTest::AttributeInfo>(1, attributeInfo),
1584 VertexInputTest::BINDING_MAPPING_ONE_TO_ONE));
1585 }
1586 }
1587 }
1588
1589 return singleAttributeTests;
1590 }
1591
createMultipleAttributeTests(tcu::TestContext & testCtx)1592 de::MovePtr<tcu::TestCaseGroup> createMultipleAttributeTests (tcu::TestContext& testCtx)
1593 {
1594 // Required vertex formats, unpacked
1595 const VkFormat vertexFormats[] =
1596 {
1597 VK_FORMAT_R8_UNORM,
1598 VK_FORMAT_R8_SNORM,
1599 VK_FORMAT_R8_UINT,
1600 VK_FORMAT_R8_SINT,
1601 VK_FORMAT_R8G8_UNORM,
1602 VK_FORMAT_R8G8_SNORM,
1603 VK_FORMAT_R8G8_UINT,
1604 VK_FORMAT_R8G8_SINT,
1605 VK_FORMAT_R8G8B8A8_UNORM,
1606 VK_FORMAT_R8G8B8A8_SNORM,
1607 VK_FORMAT_R8G8B8A8_UINT,
1608 VK_FORMAT_R8G8B8A8_SINT,
1609 VK_FORMAT_B8G8R8A8_UNORM,
1610 VK_FORMAT_R16_UNORM,
1611 VK_FORMAT_R16_SNORM,
1612 VK_FORMAT_R16_UINT,
1613 VK_FORMAT_R16_SINT,
1614 VK_FORMAT_R16_SFLOAT,
1615 VK_FORMAT_R16G16_UNORM,
1616 VK_FORMAT_R16G16_SNORM,
1617 VK_FORMAT_R16G16_UINT,
1618 VK_FORMAT_R16G16_SINT,
1619 VK_FORMAT_R16G16_SFLOAT,
1620 VK_FORMAT_R16G16B16A16_UNORM,
1621 VK_FORMAT_R16G16B16A16_SNORM,
1622 VK_FORMAT_R16G16B16A16_UINT,
1623 VK_FORMAT_R16G16B16A16_SINT,
1624 VK_FORMAT_R16G16B16A16_SFLOAT,
1625 VK_FORMAT_R32_UINT,
1626 VK_FORMAT_R32_SINT,
1627 VK_FORMAT_R32_SFLOAT,
1628 VK_FORMAT_R32G32_UINT,
1629 VK_FORMAT_R32G32_SINT,
1630 VK_FORMAT_R32G32_SFLOAT,
1631 VK_FORMAT_R32G32B32_UINT,
1632 VK_FORMAT_R32G32B32_SINT,
1633 VK_FORMAT_R32G32B32_SFLOAT,
1634 VK_FORMAT_R32G32B32A32_UINT,
1635 VK_FORMAT_R32G32B32A32_SINT,
1636 VK_FORMAT_R32G32B32A32_SFLOAT
1637 };
1638
1639 de::MovePtr<tcu::TestCaseGroup> multipleAttributeTests (new tcu::TestCaseGroup(testCtx, "multiple_attributes", "Uses more than one attribute"));
1640
1641 // Find compatible VK formats for each GLSL vertex type
1642 CompatibleFormats compatibleFormats[VertexInputTest::GLSL_TYPE_COUNT];
1643 {
1644 for (int glslTypeNdx = 0; glslTypeNdx < VertexInputTest::GLSL_TYPE_COUNT; glslTypeNdx++)
1645 {
1646 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); formatNdx++)
1647 {
1648 if (VertexInputTest::isCompatibleType(vertexFormats[formatNdx], (VertexInputTest::GlslType)glslTypeNdx))
1649 compatibleFormats[glslTypeNdx].compatibleVkFormats.push_back(vertexFormats[formatNdx]);
1650 }
1651 }
1652 }
1653
1654 de::Random randomFunc (102030);
1655 GlslTypeCombinationsIterator glslTypeCombinationsItr (VertexInputTest::GLSL_TYPE_DOUBLE, 3); // Exclude double values, which are not included in vertexFormats
1656 de::MovePtr<tcu::TestCaseGroup> oneToOneAttributeTests (new tcu::TestCaseGroup(testCtx, "attributes", ""));
1657 de::MovePtr<tcu::TestCaseGroup> oneToManyAttributeTests (new tcu::TestCaseGroup(testCtx, "attributes", ""));
1658
1659 while (glslTypeCombinationsItr.hasNext())
1660 {
1661 const std::vector<VertexInputTest::GlslType> glslTypes = glslTypeCombinationsItr.next();
1662 std::vector<VertexInputTest::AttributeInfo> attributeInfos (glslTypes.size());
1663
1664 for (size_t attributeNdx = 0; attributeNdx < attributeInfos.size(); attributeNdx++)
1665 {
1666 DE_ASSERT(!compatibleFormats[glslTypes[attributeNdx]].compatibleVkFormats.empty());
1667
1668 // Select a random compatible format
1669 const std::vector<VkFormat>& formats = compatibleFormats[glslTypes[attributeNdx]].compatibleVkFormats;
1670 const VkFormat format = formats[randomFunc.getUint32() % formats.size()];
1671
1672 attributeInfos[attributeNdx].glslType = glslTypes[attributeNdx];
1673 attributeInfos[attributeNdx].inputRate = (attributeNdx % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
1674 attributeInfos[attributeNdx].vkType = format;
1675 }
1676
1677 const std::string caseName = getAttributeInfosCaseName(attributeInfos);
1678 const std::string caseDesc = getAttributeInfosDescription(attributeInfos);
1679
1680 oneToOneAttributeTests->addChild(new VertexInputTest(testCtx, caseName, caseDesc, attributeInfos, VertexInputTest::BINDING_MAPPING_ONE_TO_ONE));
1681 oneToManyAttributeTests->addChild(new VertexInputTest(testCtx, caseName, caseDesc, attributeInfos, VertexInputTest::BINDING_MAPPING_ONE_TO_MANY));
1682 }
1683
1684 de::MovePtr<tcu::TestCaseGroup> bindingOneToOneTests (new tcu::TestCaseGroup(testCtx, "binding_one_to_one", "Each attribute uses a unique binding"));
1685 bindingOneToOneTests->addChild(oneToOneAttributeTests.release());
1686 multipleAttributeTests->addChild(bindingOneToOneTests.release());
1687
1688 de::MovePtr<tcu::TestCaseGroup> bindingOneToManyTests (new tcu::TestCaseGroup(testCtx, "binding_one_to_many", "Attributes share the same binding"));
1689 bindingOneToManyTests->addChild(oneToManyAttributeTests.release());
1690 multipleAttributeTests->addChild(bindingOneToManyTests.release());
1691
1692 return multipleAttributeTests;
1693 }
1694
1695 } // anonymous
1696
createVertexInputTests(tcu::TestContext & testCtx)1697 tcu::TestCaseGroup* createVertexInputTests (tcu::TestContext& testCtx)
1698 {
1699 de::MovePtr<tcu::TestCaseGroup> vertexInputTests (new tcu::TestCaseGroup(testCtx, "vertex_input", ""));
1700
1701 vertexInputTests->addChild(createSingleAttributeTests(testCtx).release());
1702 vertexInputTests->addChild(createMultipleAttributeTests(testCtx).release());
1703
1704 return vertexInputTests.release();
1705 }
1706
1707 } // pipeline
1708 } // vkt
1709