1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Imagination Technologies Ltd.
7 * Copyright (c) 2023 LunarG, Inc.
8 * Copyright (c) 2023 Nintendo
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 *//*!
23 * \file
24 * \brief Input Assembly Tests
25 *//*--------------------------------------------------------------------*/
26
27 #include "vktPipelineInputAssemblyTests.hpp"
28 #include "vktPipelineClearUtil.hpp"
29 #include "vktPipelineImageUtil.hpp"
30 #include "vktPipelineVertexUtil.hpp"
31 #include "vktPipelineReferenceRenderer.hpp"
32 #include "vktAmberTestCase.hpp"
33 #include "vktTestCase.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkRef.hpp"
39 #include "vkRefUtil.hpp"
40 #include "vkTypeUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43 #include "tcuImageCompare.hpp"
44 #include "deMath.h"
45 #include "deMemory.h"
46 #include "deRandom.hpp"
47 #include "deStringUtil.hpp"
48 #include "deUniquePtr.hpp"
49
50 #include <algorithm>
51 #include <sstream>
52 #include <vector>
53
54 namespace vkt
55 {
56 namespace pipeline
57 {
58
59 using namespace vk;
60
61 enum class RestartType
62 {
63 NORMAL,
64 NONE,
65 ALL,
66 };
67
68 namespace
69 {
70
71 class InputAssemblyTest : public vkt::TestCase
72 {
73 public:
74 const static VkPrimitiveTopology s_primitiveTopologies[];
75 const static deUint32 s_restartIndex32;
76 const static deUint16 s_restartIndex16;
77 const static deUint8 s_restartIndex8;
78
79 InputAssemblyTest (tcu::TestContext& testContext,
80 const std::string& name,
81 const PipelineConstructionType pipelineConstructionType,
82 VkPrimitiveTopology primitiveTopology,
83 int primitiveCount,
84 bool testPrimitiveRestart,
85 VkIndexType indexType);
~InputAssemblyTest(void)86 virtual ~InputAssemblyTest (void) {}
87 virtual void initPrograms (SourceCollections& sourceCollections) const;
88 virtual void checkSupport (Context& context) const;
89 virtual TestInstance* createInstance (Context& context) const;
90 static bool isRestartIndex (VkIndexType indexType, deUint32 indexValue);
91 #ifndef CTS_USES_VULKANSC
92 static deUint32 getRestartIndex (VkIndexType indexType);
93 #endif // CTS_USES_VULKANSC
94
95 protected:
96 virtual void createBufferData (VkPrimitiveTopology topology,
97 int primitiveCount,
98 VkIndexType indexType,
99 std::vector<deUint32>& indexData,
100 std::vector<Vertex4RGBA>& vertexData) const = 0;
101 VkPrimitiveTopology m_primitiveTopology;
102 const int m_primitiveCount;
103
104 private:
105 const PipelineConstructionType m_pipelineConstructionType;
106 bool m_testPrimitiveRestart;
107 VkIndexType m_indexType;
108 };
109
110 class PrimitiveTopologyTest : public InputAssemblyTest
111 {
112 public:
113 PrimitiveTopologyTest (tcu::TestContext& testContext,
114 const std::string& name,
115 PipelineConstructionType pipelineConstructionType,
116 VkPrimitiveTopology primitiveTopology,
117 VkIndexType indexType);
~PrimitiveTopologyTest(void)118 virtual ~PrimitiveTopologyTest (void) {}
119
120 protected:
121 virtual void createBufferData (VkPrimitiveTopology topology,
122 int primitiveCount,
123 VkIndexType indexType,
124 std::vector<deUint32>& indexData,
125 std::vector<Vertex4RGBA>& vertexData) const;
126
127 private:
128 };
129
130 #ifndef CTS_USES_VULKANSC
131 class PrimitiveRestartTest : public InputAssemblyTest
132 {
133 public:
134 PrimitiveRestartTest (tcu::TestContext& testContext,
135 const std::string& name,
136 const PipelineConstructionType pipelineConstructionType,
137 VkPrimitiveTopology primitiveTopology,
138 VkIndexType indexType,
139 RestartType restartType);
~PrimitiveRestartTest(void)140 virtual ~PrimitiveRestartTest (void) {}
141 virtual void checkSupport (Context& context) const;
142
143 protected:
144 virtual void createBufferData (VkPrimitiveTopology topology,
145 int primitiveCount,
146 VkIndexType indexType,
147 std::vector<deUint32>& indexData,
148 std::vector<Vertex4RGBA>& vertexData) const;
149
150 private:
151 bool isRestartPrimitive (int primitiveIndex) const;
152 void createListPrimitives (int primitiveCount,
153 float originX,
154 float originY,
155 float primitiveSizeX,
156 float primitiveSizeY,
157 int verticesPerPrimitive,
158 VkIndexType indexType,
159 std::vector<deUint32>& indexData,
160 std::vector<Vertex4RGBA>& vertexData,
161 std::vector<deUint32> adjacencies) const;
162
163 std::vector<deUint32> m_restartPrimitives;
164 RestartType m_restartType;
165 };
166 #endif // CTS_USES_VULKANSC
167
168
169 class InputAssemblyInstance : public vkt::TestInstance
170 {
171 public:
172 InputAssemblyInstance (Context& context,
173 const PipelineConstructionType pipelineConstructionType,
174 const VkPrimitiveTopology primitiveTopology,
175 bool testPrimitiveRestart,
176 VkIndexType indexType,
177 const std::vector<deUint32>& indexBufferData,
178 const std::vector<Vertex4RGBA>& vertexBufferData);
179 virtual ~InputAssemblyInstance (void);
180 virtual tcu::TestStatus iterate (void);
181
182 private:
183 tcu::TestStatus verifyImage (void);
184 void uploadIndexBufferData16 (deUint16* destPtr, const std::vector<deUint32>& indexBufferData);
185 void uploadIndexBufferData8 (deUint8* destPtr, const std::vector<deUint32>& indexBufferData);
186
187 VkPrimitiveTopology m_primitiveTopology;
188 bool m_primitiveRestartEnable;
189 VkIndexType m_indexType;
190
191 Move<VkBuffer> m_vertexBuffer;
192 std::vector<Vertex4RGBA> m_vertices;
193 de::MovePtr<Allocation> m_vertexBufferAlloc;
194
195 Move<VkBuffer> m_indexBuffer;
196 std::vector<deUint32> m_indices;
197 de::MovePtr<Allocation> m_indexBufferAlloc;
198
199 const tcu::UVec2 m_renderSize;
200
201 const VkFormat m_colorFormat;
202 VkImageCreateInfo m_colorImageCreateInfo;
203 Move<VkImage> m_colorImage;
204 de::MovePtr<Allocation> m_colorImageAlloc;
205 Move<VkImageView> m_colorAttachmentView;
206 RenderPassWrapper m_renderPass;
207 Move<VkFramebuffer> m_framebuffer;
208
209 ShaderWrapper m_vertexShaderModule;
210 ShaderWrapper m_fragmentShaderModule;
211 ShaderWrapper m_tcsShaderModule;
212 ShaderWrapper m_tesShaderModule;
213
214 PipelineLayoutWrapper m_pipelineLayout;
215 GraphicsPipelineWrapper m_graphicsPipeline;
216
217 Move<VkCommandPool> m_cmdPool;
218 Move<VkCommandBuffer> m_cmdBuffer;
219 };
220
221
222 // InputAssemblyTest
223
224 const VkPrimitiveTopology InputAssemblyTest::s_primitiveTopologies[] =
225 {
226 VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
227 VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
228 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
229 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
230 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
231 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
232 VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
233 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
234 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
235 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
236 };
237
238 const deUint32 InputAssemblyTest::s_restartIndex32 = ~((deUint32)0u);
239 const deUint16 InputAssemblyTest::s_restartIndex16 = ~((deUint16)0u);
240 const deUint8 InputAssemblyTest::s_restartIndex8 = ~((deUint8)0u);
241
InputAssemblyTest(tcu::TestContext& testContext, const std::string& name, const PipelineConstructionType pipelineConstructionType, VkPrimitiveTopology primitiveTopology, int primitiveCount, bool testPrimitiveRestart, VkIndexType indexType)242 InputAssemblyTest::InputAssemblyTest (tcu::TestContext& testContext,
243 const std::string& name,
244 const PipelineConstructionType pipelineConstructionType,
245 VkPrimitiveTopology primitiveTopology,
246 int primitiveCount,
247 bool testPrimitiveRestart,
248 VkIndexType indexType)
249 : vkt::TestCase (testContext, name)
250 , m_primitiveTopology (primitiveTopology)
251 , m_primitiveCount(primitiveCount)
252 , m_pipelineConstructionType(pipelineConstructionType)
253 , m_testPrimitiveRestart (testPrimitiveRestart)
254 , m_indexType (indexType)
255 {
256 }
257
checkSupport(Context& context) const258 void InputAssemblyTest::checkSupport (Context& context) const
259 {
260 if (m_indexType == VK_INDEX_TYPE_UINT8_EXT)
261 context.requireDeviceFunctionality("VK_EXT_index_type_uint8");
262
263 switch (m_primitiveTopology)
264 {
265 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
266 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
267 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
268 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
269 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
270 break;
271
272 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
273 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
274 break;
275
276 default:
277 break;
278 }
279
280 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
281
282 #ifndef CTS_USES_VULKANSC
283 if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN &&
284 context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
285 !context.getPortabilitySubsetFeatures().triangleFans)
286 {
287 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
288 }
289 #endif // CTS_USES_VULKANSC
290 }
291
createInstance(Context& context) const292 TestInstance* InputAssemblyTest::createInstance (Context& context) const
293 {
294 std::vector<deUint32> indexBufferData;
295 std::vector<Vertex4RGBA> vertexBufferData;
296
297 createBufferData(m_primitiveTopology, m_primitiveCount, m_indexType, indexBufferData, vertexBufferData);
298
299 return new InputAssemblyInstance(context, m_pipelineConstructionType, m_primitiveTopology, m_testPrimitiveRestart, m_indexType, indexBufferData, vertexBufferData);
300 }
301
initPrograms(SourceCollections& sourceCollections) const302 void InputAssemblyTest::initPrograms (SourceCollections& sourceCollections) const
303 {
304 std::ostringstream vertexSource;
305
306 vertexSource <<
307 "#version 310 es\n"
308 "layout(location = 0) in vec4 position;\n"
309 "layout(location = 1) in vec4 color;\n"
310 "layout(location = 0) out highp vec4 vtxColor;\n"
311 "void main (void)\n"
312 "{\n"
313 " gl_Position = position;\n"
314 << (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST ? " gl_PointSize = 3.0;\n"
315 : "" )
316 << " vtxColor = color;\n"
317 "}\n";
318
319 sourceCollections.glslSources.add("color_vert") << glu::VertexSource(vertexSource.str());
320
321 sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(
322 "#version 310 es\n"
323 "layout(location = 0) in highp vec4 vtxColor;\n"
324 "layout(location = 0) out highp vec4 fragColor;\n"
325 "void main (void)\n"
326 "{\n"
327 " fragColor = vtxColor;\n"
328 "}\n");
329
330 sourceCollections.glslSources.add("color_tcs") << glu::TessellationControlSource(
331 "#version 310 es\n"
332 "#extension GL_EXT_tessellation_shader : require\n"
333 "layout(vertices = 3) out;\n"
334 "layout(location = 0) in highp vec4 vtxColorIn[];\n"
335 "layout(location = 0) out highp vec4 vtxColorOut[];\n"
336 "#define ID gl_InvocationID\n"
337 "void main (void)\n"
338 "{\n"
339 " vtxColorOut[ID] = vtxColorIn[ID];\n"
340 " gl_out[ID].gl_Position = gl_in[ID].gl_Position;\n"
341 " if (ID == 0)\n"
342 " {\n"
343 " gl_TessLevelInner[0] = 5.0;\n"
344 " gl_TessLevelOuter[0] = 4.0;\n"
345 " gl_TessLevelOuter[1] = 5.0;\n"
346 " gl_TessLevelOuter[2] = 6.0;\n"
347 " }\n"
348 "}\n");
349
350 sourceCollections.glslSources.add("color_tes") << glu::TessellationEvaluationSource(
351 "#version 310 es\n"
352 "#extension GL_EXT_tessellation_shader : require\n"
353 "layout(triangles) in;\n"
354 "layout(location = 0) in vec4 vtxColorIn[];\n"
355 "layout(location = 0) out vec4 vtxColorOut;\n"
356 "void main (void)\n"
357 "{\n"
358 " vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;\n"
359 " vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;\n"
360 " vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;\n"
361 " gl_Position = p0 + p1 + p2;\n"
362 " vec4 q0 = gl_TessCoord.x * vtxColorIn[0];\n"
363 " vec4 q1 = gl_TessCoord.y * vtxColorIn[1];\n"
364 " vec4 q2 = gl_TessCoord.z * vtxColorIn[2];\n"
365 " vtxColorOut = q0 + q1 + q2;\n"
366 "}\n");
367 }
368
isRestartIndex(VkIndexType indexType, deUint32 indexValue)369 bool InputAssemblyTest::isRestartIndex (VkIndexType indexType, deUint32 indexValue)
370 {
371 if (indexType == VK_INDEX_TYPE_UINT16)
372 return indexValue == s_restartIndex16;
373 else if (indexType == VK_INDEX_TYPE_UINT8_EXT)
374 return indexValue == s_restartIndex8;
375 else
376 return indexValue == s_restartIndex32;
377 }
378
379 #ifndef CTS_USES_VULKANSC
getRestartIndex(VkIndexType indexType)380 deUint32 InputAssemblyTest::getRestartIndex (VkIndexType indexType)
381 {
382 if (indexType == VK_INDEX_TYPE_UINT16)
383 return InputAssemblyTest::s_restartIndex16;
384 else if (indexType == VK_INDEX_TYPE_UINT8_EXT)
385 return InputAssemblyTest::s_restartIndex8;
386 else
387 return InputAssemblyTest::s_restartIndex32;
388 }
389 #endif // CTS_USES_VULKANSC
390
391 // PrimitiveTopologyTest
392
PrimitiveTopologyTest(tcu::TestContext& testContext, const std::string& name, PipelineConstructionType pipelineConstructionType, VkPrimitiveTopology primitiveTopology, VkIndexType indexType)393 PrimitiveTopologyTest::PrimitiveTopologyTest (tcu::TestContext& testContext,
394 const std::string& name,
395 PipelineConstructionType pipelineConstructionType,
396 VkPrimitiveTopology primitiveTopology,
397 VkIndexType indexType)
398 : InputAssemblyTest (testContext, name, pipelineConstructionType, primitiveTopology, 10, false, indexType)
399 {
400 }
401
createBufferData(VkPrimitiveTopology topology, int primitiveCount, VkIndexType indexType, std::vector<deUint32>& indexData, std::vector<Vertex4RGBA>& vertexData) const402 void PrimitiveTopologyTest::createBufferData (VkPrimitiveTopology topology, int primitiveCount, VkIndexType indexType, std::vector<deUint32>& indexData, std::vector<Vertex4RGBA>& vertexData) const
403 {
404 DE_ASSERT(primitiveCount > 0);
405 DE_UNREF(indexType);
406
407 const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
408 const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
409 const float border = 0.2f;
410 const float originX = -1.0f + border;
411 const float originY = -1.0f + border;
412 const Vertex4RGBA defaultVertex = { tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), green };
413 float primitiveSizeY = (2.0f - 2.0f * border);
414 float primitiveSizeX;
415 std::vector<deUint32> indices;
416 std::vector<Vertex4RGBA> vertices;
417
418
419 // Calculate primitive size
420 switch (topology)
421 {
422 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
423 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2 + primitiveCount % 2 - 1);
424 break;
425
426 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
427 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
428 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount - 1);
429 break;
430
431 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
432 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
433 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2);
434 break;
435
436 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
437 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
438 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount + primitiveCount / 2 + primitiveCount % 2 - 1);
439 break;
440
441 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
442 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
443 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2 + primitiveCount % 2);
444 break;
445
446 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
447 primitiveSizeX = 1.0f - border;
448 primitiveSizeY = 1.0f - border;
449 break;
450
451 default:
452 primitiveSizeX = 0.0f; // Garbage
453 DE_ASSERT(false);
454 }
455
456 switch (topology)
457 {
458 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
459 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
460 {
461 const Vertex4RGBA vertex =
462 {
463 tcu::Vec4(originX + float(primitiveNdx / 2) * primitiveSizeX, originY + float(primitiveNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
464 red
465 };
466
467 vertices.push_back(vertex);
468 indices.push_back(primitiveNdx);
469 }
470 break;
471
472 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
473 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
474 {
475 for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++)
476 {
477 const Vertex4RGBA vertex =
478 {
479 tcu::Vec4(originX + float((primitiveNdx * 2 + vertexNdx) / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
480 red
481 };
482
483 vertices.push_back(vertex);
484 indices.push_back((primitiveNdx * 2 + vertexNdx));
485 }
486 }
487 break;
488
489 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
490 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
491 {
492 if (primitiveNdx == 0)
493 {
494 Vertex4RGBA vertex =
495 {
496 tcu::Vec4(originX, originY, 0.0f, 1.0f),
497 red
498 };
499
500 vertices.push_back(vertex);
501 indices.push_back(0);
502
503 vertex.position = tcu::Vec4(originX, originY + primitiveSizeY, 0.0f, 1.0f);
504 vertices.push_back(vertex);
505 indices.push_back(1);
506 }
507 else
508 {
509 const Vertex4RGBA vertex =
510 {
511 tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f),
512 red
513 };
514
515 vertices.push_back(vertex);
516 indices.push_back(primitiveNdx + 1);
517 }
518 }
519 break;
520
521 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
522 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
523 {
524 for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++)
525 {
526 const Vertex4RGBA vertex =
527 {
528 tcu::Vec4(originX + float((primitiveNdx * 3 + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx * 3 + vertexNdx)% 2) * primitiveSizeY, 0.0f, 1.0f),
529 red
530 };
531
532 vertices.push_back(vertex);
533 indices.push_back(primitiveNdx * 3 + vertexNdx);
534 }
535 }
536 break;
537
538 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
539 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
540 {
541 if (primitiveNdx == 0)
542 {
543 for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++)
544 {
545 const Vertex4RGBA vertex =
546 {
547 tcu::Vec4(originX + float(vertexNdx / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
548 red
549 };
550
551 vertices.push_back(vertex);
552 indices.push_back(vertexNdx);
553 }
554 }
555 else
556 {
557 const Vertex4RGBA vertex =
558 {
559 tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f),
560 red
561 };
562
563 vertices.push_back(vertex);
564 indices.push_back(primitiveNdx + 2);
565 }
566 }
567 break;
568
569 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
570 {
571 const float stepAngle = de::min(DE_PI * 0.5f, (2 * DE_PI) / float(primitiveCount));
572
573 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
574 {
575 if (primitiveNdx == 0)
576 {
577 Vertex4RGBA vertex =
578 {
579 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
580 red
581 };
582
583 vertices.push_back(vertex);
584 indices.push_back(0);
585
586 vertex.position = tcu::Vec4(primitiveSizeX, 0.0f, 0.0f, 1.0f);
587 vertices.push_back(vertex);
588 indices.push_back(1);
589
590 vertex.position = tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle), primitiveSizeY * deFloatSin(stepAngle), 0.0f, 1.0f);
591 vertices.push_back(vertex);
592 indices.push_back(2);
593 }
594 else
595 {
596 const Vertex4RGBA vertex =
597 {
598 tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle * float(primitiveNdx + 1)), primitiveSizeY * deFloatSin(stepAngle * float(primitiveNdx + 1)), 0.0f, 1.0f),
599 red
600 };
601
602 vertices.push_back(vertex);
603 indices.push_back(primitiveNdx + 2);
604 }
605 }
606 break;
607 }
608
609 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
610 vertices.push_back(defaultVertex);
611
612 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
613 {
614 indices.push_back(0);
615
616 for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++)
617 {
618 const Vertex4RGBA vertex =
619 {
620 tcu::Vec4(originX + float((primitiveNdx * 2 + vertexNdx) / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
621 red
622 };
623
624 vertices.push_back(vertex);
625 indices.push_back(primitiveNdx * 2 + vertexNdx + 1);
626 }
627
628 indices.push_back(0);
629 }
630 break;
631
632
633 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
634 vertices.push_back(defaultVertex);
635 indices.push_back(0);
636
637 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
638 {
639 if (primitiveNdx == 0)
640 {
641 Vertex4RGBA vertex =
642 {
643 tcu::Vec4(originX, originY, 0.0f, 1.0f),
644 red
645 };
646
647 vertices.push_back(vertex);
648 indices.push_back(1);
649
650 vertex.position = tcu::Vec4(originX, originY + primitiveSizeY, 0.0f, 1.0f);
651 vertices.push_back(vertex);
652 indices.push_back(2);
653 }
654 else
655 {
656 const Vertex4RGBA vertex =
657 {
658 tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f),
659 red
660 };
661
662 vertices.push_back(vertex);
663 indices.push_back(primitiveNdx + 2);
664 }
665 }
666
667 indices.push_back(0);
668 break;
669
670 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
671 vertices.push_back(defaultVertex);
672
673 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
674 {
675 for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++)
676 {
677 const Vertex4RGBA vertex =
678 {
679 tcu::Vec4(originX + float((primitiveNdx * 3 + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx * 3 + vertexNdx)% 2) * primitiveSizeY, 0.0f, 1.0f),
680 red
681 };
682
683 vertices.push_back(vertex);
684 indices.push_back(primitiveNdx * 3 + vertexNdx + 1);
685 indices.push_back(0);
686 }
687 }
688 break;
689
690 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
691 vertices.push_back(defaultVertex);
692
693 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
694 {
695 if (primitiveNdx == 0)
696 {
697 for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++)
698 {
699 const Vertex4RGBA vertex =
700 {
701 tcu::Vec4(originX + float(vertexNdx / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
702 red
703 };
704
705 vertices.push_back(vertex);
706 indices.push_back(vertexNdx + 1);
707 indices.push_back(0);
708 }
709 }
710 else
711 {
712 const Vertex4RGBA vertex =
713 {
714 tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f),
715 red
716 };
717
718 vertices.push_back(vertex);
719 indices.push_back(primitiveNdx + 2 + 1);
720 indices.push_back(0);
721 }
722 }
723 break;
724
725 default:
726 DE_ASSERT(false);
727 break;
728 }
729
730 vertexData = vertices;
731 indexData = indices;
732 }
733
734 #ifndef CTS_USES_VULKANSC
735 // PrimitiveRestartTest
736
PrimitiveRestartTest(tcu::TestContext& testContext, const std::string& name, PipelineConstructionType pipelineConstructionType, VkPrimitiveTopology primitiveTopology, VkIndexType indexType, RestartType restartType)737 PrimitiveRestartTest::PrimitiveRestartTest (tcu::TestContext& testContext,
738 const std::string& name,
739 PipelineConstructionType pipelineConstructionType,
740 VkPrimitiveTopology primitiveTopology,
741 VkIndexType indexType,
742 RestartType restartType)
743
744 : InputAssemblyTest (testContext, name, pipelineConstructionType, primitiveTopology, 10, true, indexType)
745 , m_restartType(restartType)
746 {
747 deUint32 restartPrimitives[] = { 1, 5 };
748
749 if (restartType == RestartType::NORMAL)
750 {
751 m_restartPrimitives = std::vector<deUint32>(restartPrimitives, restartPrimitives + sizeof(restartPrimitives) / sizeof(deUint32));
752 }
753 else if (restartType == RestartType::NONE)
754 {
755 m_restartPrimitives = std::vector<deUint32>{};
756 }
757 else
758 {
759 deUint32 count = 1;
760 switch (primitiveTopology)
761 {
762 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
763 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
764 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
765 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
766 count = 2;
767 break;
768 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
769 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
770 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
771 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
772 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
773 count = 3;
774 break;
775 default:
776 break;
777 }
778 for (deUint32 i = 0; i < (deUint32)m_primitiveCount; ++i)
779 {
780 if (i % count == count - 1)
781 {
782 m_restartPrimitives.push_back(i);
783 }
784 }
785 }
786 }
787
checkSupport(Context& context) const788 void PrimitiveRestartTest::checkSupport (Context& context) const
789 {
790 switch (m_primitiveTopology)
791 {
792 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
793 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
794 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
795 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
796 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
797 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
798 {
799 context.requireDeviceFunctionality("VK_EXT_primitive_topology_list_restart");
800
801 const auto& features = context.getPrimitiveTopologyListRestartFeaturesEXT();
802 if (!features.primitiveTopologyListRestart)
803 TCU_THROW(NotSupportedError, "Primitive topology list restart feature not supported");
804 if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && !features.primitiveTopologyPatchListRestart)
805 TCU_THROW(NotSupportedError, "Primitive topology patch list restart feature not supported");
806 }
807 break;
808
809 default:
810 break;
811 }
812
813 InputAssemblyTest::checkSupport(context);
814 }
815
createBufferData(VkPrimitiveTopology topology, int primitiveCount, VkIndexType indexType, std::vector<deUint32>& indexData, std::vector<Vertex4RGBA>& vertexData) const816 void PrimitiveRestartTest::createBufferData (VkPrimitiveTopology topology, int primitiveCount, VkIndexType indexType, std::vector<deUint32>& indexData, std::vector<Vertex4RGBA>& vertexData) const
817 {
818 DE_ASSERT(primitiveCount > 0);
819 DE_UNREF(indexType);
820
821 const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
822 const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
823 const float border = 0.2f;
824 const float originX = -1.0f + border;
825 const float originY = -1.0f + border;
826 const Vertex4RGBA defaultVertex = { tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), green };
827 float primitiveSizeY = (2.0f - 2.0f * border);
828 float primitiveSizeX;
829 bool primitiveStart = true;
830 std::vector<deUint32> indices;
831 std::vector<Vertex4RGBA> vertices;
832
833 // Calculate primitive size
834 switch (topology)
835 {
836 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
837 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2 + primitiveCount % 2 - 1);
838 break;
839
840 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
841 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
842 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
843 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
844 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2);
845 break;
846
847 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
848 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
849 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
850 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
851 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
852 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2 + primitiveCount % 2);
853 break;
854
855 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
856 primitiveSizeX = 1.0f - border;
857 primitiveSizeY = 1.0f - border;
858 break;
859
860 default:
861 primitiveSizeX = 0.0f; // Garbage
862 DE_ASSERT(false);
863 }
864
865 switch (topology)
866 {
867 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
868 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
869 {
870 if (isRestartPrimitive(primitiveNdx))
871 {
872 indices.push_back(InputAssemblyTest::getRestartIndex(indexType));
873 primitiveStart = true;
874 }
875 else
876 {
877 if (primitiveStart && m_restartType != RestartType::ALL)
878 {
879 const Vertex4RGBA vertex =
880 {
881 tcu::Vec4(originX + float(primitiveNdx / 2) * primitiveSizeX, originY + float(primitiveNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
882 red
883 };
884
885 vertices.push_back(vertex);
886 indices.push_back((deUint32)vertices.size() - 1);
887
888 primitiveStart = false;
889 }
890
891 const Vertex4RGBA vertex =
892 {
893 tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f),
894 red
895 };
896
897 vertices.push_back(vertex);
898 indices.push_back((deUint32)vertices.size() - 1);
899 }
900 }
901 break;
902
903 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
904 {
905 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
906 {
907 if (isRestartPrimitive(primitiveNdx))
908 {
909 indices.push_back(InputAssemblyTest::getRestartIndex(indexType));
910 primitiveStart = true;
911 }
912 else
913 {
914 if (primitiveStart && m_restartType != RestartType::ALL)
915 {
916 for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++)
917 {
918 const Vertex4RGBA vertex =
919 {
920 tcu::Vec4(originX + float((primitiveNdx + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx + vertexNdx) % 2) * primitiveSizeY, 0.0f, 1.0f),
921 red
922 };
923
924 vertices.push_back(vertex);
925 indices.push_back((deUint32)vertices.size() - 1);
926 }
927
928 primitiveStart = false;
929 }
930 const Vertex4RGBA vertex =
931 {
932 tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f),
933 red
934 };
935
936 vertices.push_back(vertex);
937 indices.push_back((deUint32)vertices.size() - 1);
938 }
939 }
940 break;
941 }
942
943 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
944 {
945 const float stepAngle = de::min(DE_PI * 0.5f, (2 * DE_PI) / float(primitiveCount));
946
947 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
948 {
949 if (isRestartPrimitive(primitiveNdx))
950 {
951 indices.push_back(InputAssemblyTest::getRestartIndex(indexType));
952 primitiveStart = true;
953 }
954 else
955 {
956 if (primitiveStart && m_restartType != RestartType::ALL)
957 {
958 Vertex4RGBA vertex =
959 {
960 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
961 red
962 };
963
964 vertices.push_back(vertex);
965 indices.push_back((deUint32)vertices.size() - 1);
966
967 vertex.position = tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle * float(primitiveNdx)), primitiveSizeY * deFloatSin(stepAngle * float(primitiveNdx)), 0.0f, 1.0f);
968 vertices.push_back(vertex);
969 indices.push_back((deUint32)vertices.size() - 1);
970
971 primitiveStart = false;
972 }
973
974 const Vertex4RGBA vertex =
975 {
976 tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle * float(primitiveNdx + 1)), primitiveSizeY * deFloatSin(stepAngle * float(primitiveNdx + 1)), 0.0f, 1.0f),
977 red
978 };
979
980 vertices.push_back(vertex);
981 indices.push_back((deUint32)vertices.size() - 1);
982 }
983 }
984 break;
985 }
986
987 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
988 vertices.push_back(defaultVertex);
989
990 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
991 {
992 if (isRestartPrimitive(primitiveNdx))
993 {
994 indices.push_back(0);
995 indices.push_back(InputAssemblyTest::getRestartIndex(indexType));
996 primitiveStart = true;
997 }
998 else
999 {
1000 if (primitiveStart && m_restartType != RestartType::ALL)
1001 {
1002 indices.push_back(0);
1003
1004 const Vertex4RGBA vertex =
1005 {
1006 tcu::Vec4(originX + float(primitiveNdx / 2) * primitiveSizeX, originY + float(primitiveNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
1007 red
1008 };
1009
1010 vertices.push_back(vertex);
1011 indices.push_back((deUint32)vertices.size() - 1);
1012
1013 primitiveStart = false;
1014 }
1015
1016 const Vertex4RGBA vertex =
1017 {
1018 tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f),
1019 red
1020 };
1021
1022 vertices.push_back(vertex);
1023 indices.push_back((deUint32)vertices.size() - 1);
1024 }
1025 }
1026
1027 indices.push_back(0);
1028 break;
1029
1030 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
1031 vertices.push_back(defaultVertex);
1032
1033 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
1034 {
1035 if (isRestartPrimitive(primitiveNdx))
1036 {
1037 indices.push_back(InputAssemblyTest::getRestartIndex(indexType));
1038 primitiveStart = true;
1039 }
1040 else
1041 {
1042 if (primitiveStart && m_restartType != RestartType::ALL)
1043 {
1044 for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++)
1045 {
1046 const Vertex4RGBA vertex =
1047 {
1048 tcu::Vec4(originX + float((primitiveNdx + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx + vertexNdx) % 2) * primitiveSizeY, 0.0f, 1.0f),
1049 red
1050 };
1051
1052 vertices.push_back(vertex);
1053 indices.push_back((deUint32)vertices.size() - 1);
1054 indices.push_back(0);
1055 }
1056
1057 primitiveStart = false;
1058 }
1059
1060 const Vertex4RGBA vertex =
1061 {
1062 tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f),
1063 red
1064 };
1065
1066 vertices.push_back(vertex);
1067 indices.push_back((deUint32)vertices.size() - 1);
1068 indices.push_back(0);
1069 }
1070 }
1071 break;
1072
1073 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
1074 createListPrimitives(primitiveCount, originX, originY, primitiveSizeX, primitiveSizeY,
1075 1, indexType, indices, vertices, std::vector<deUint32>());
1076 break;
1077
1078 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
1079 createListPrimitives(primitiveCount, originX, originY, primitiveSizeX, primitiveSizeY,
1080 2, indexType, indices, vertices, std::vector<deUint32>());
1081 break;
1082
1083 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
1084 {
1085 std::vector<deUint32> adjacencies = { 0, 3 };
1086
1087 createListPrimitives(primitiveCount, originX, originY, primitiveSizeX, primitiveSizeY,
1088 4, indexType, indices, vertices, adjacencies);
1089 }
1090 break;
1091
1092 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
1093 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
1094 createListPrimitives(primitiveCount, originX, originY, primitiveSizeX, primitiveSizeY,
1095 3, indexType, indices, vertices, std::vector<deUint32>());
1096 break;
1097
1098 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
1099 {
1100 std::vector<deUint32> adjacencies = { 1, 3, 5 };
1101
1102 createListPrimitives(primitiveCount, originX, originY, primitiveSizeX, primitiveSizeY,
1103 6, indexType, indices, vertices, adjacencies);
1104 }
1105 break;
1106
1107 default:
1108 DE_ASSERT(false);
1109 break;
1110 }
1111
1112 vertexData = vertices;
1113 indexData = indices;
1114 }
1115
createListPrimitives(int primitiveCount, float originX, float originY, float primitiveSizeX, float primitiveSizeY, int verticesPerPrimitive, VkIndexType indexType, std::vector<deUint32>& indexData, std::vector<Vertex4RGBA>& vertexData, std::vector<deUint32> adjacencies) const1116 void PrimitiveRestartTest::createListPrimitives (int primitiveCount,
1117 float originX,
1118 float originY,
1119 float primitiveSizeX,
1120 float primitiveSizeY,
1121 int verticesPerPrimitive,
1122 VkIndexType indexType,
1123 std::vector<deUint32>& indexData,
1124 std::vector<Vertex4RGBA>& vertexData,
1125 std::vector<deUint32> adjacencies) const
1126 {
1127 const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
1128 const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
1129 // Tells which vertex of a primitive is used as a restart index.
1130 // This is decreased each time a restart primitive is used.
1131 int restartVertexIndex = verticesPerPrimitive - 1;
1132
1133 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
1134 {
1135 deUint32 nonAdjacentVertexNdx = 0;
1136
1137 for (int vertexNdx = 0; vertexNdx < verticesPerPrimitive; vertexNdx++)
1138 {
1139 if (isRestartPrimitive(primitiveNdx) && vertexNdx == restartVertexIndex)
1140 {
1141 indexData.push_back(InputAssemblyTest::getRestartIndex(indexType));
1142
1143 restartVertexIndex--;
1144 if (restartVertexIndex < 0) restartVertexIndex = verticesPerPrimitive - 1;
1145
1146 break;
1147 }
1148
1149 if (std::find(adjacencies.begin(), adjacencies.end(), vertexNdx) != adjacencies.end())
1150 {
1151 // This is an adjacency vertex index. Add a green vertex that should never end up to the framebuffer.
1152 const Vertex4RGBA vertex =
1153 {
1154 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
1155 green
1156 };
1157 vertexData.push_back(vertex);
1158 indexData.push_back((deUint32) vertexData.size() - 1);
1159 continue;
1160 }
1161
1162 const Vertex4RGBA vertex =
1163 {
1164 tcu::Vec4(originX + float((primitiveNdx + nonAdjacentVertexNdx) / 2) * primitiveSizeX,
1165 originY + float((primitiveNdx + nonAdjacentVertexNdx) % 2) * primitiveSizeY, 0.0f, 1.0f),
1166 red
1167 };
1168
1169 vertexData.push_back(vertex);
1170 indexData.push_back((deUint32) vertexData.size() - 1);
1171 nonAdjacentVertexNdx++;
1172 }
1173 }
1174 }
1175
isRestartPrimitive(int primitiveIndex) const1176 bool PrimitiveRestartTest::isRestartPrimitive (int primitiveIndex) const
1177 {
1178 return std::find(m_restartPrimitives.begin(), m_restartPrimitives.end(), primitiveIndex) != m_restartPrimitives.end();
1179 }
1180 #endif // CTS_USES_VULKANSC
1181
1182 // InputAssemblyInstance
1183
InputAssemblyInstance(Context& context, PipelineConstructionType pipelineConstructionType, VkPrimitiveTopology primitiveTopology, bool testPrimitiveRestart, VkIndexType indexType, const std::vector<deUint32>& indexBufferData, const std::vector<Vertex4RGBA>& vertexBufferData)1184 InputAssemblyInstance::InputAssemblyInstance (Context& context,
1185 PipelineConstructionType pipelineConstructionType,
1186 VkPrimitiveTopology primitiveTopology,
1187 bool testPrimitiveRestart,
1188 VkIndexType indexType,
1189 const std::vector<deUint32>& indexBufferData,
1190 const std::vector<Vertex4RGBA>& vertexBufferData)
1191
1192 : vkt::TestInstance (context)
1193 , m_primitiveTopology (primitiveTopology)
1194 , m_primitiveRestartEnable (testPrimitiveRestart)
1195 , m_indexType (indexType)
1196 , m_vertices (vertexBufferData)
1197 , m_indices (indexBufferData)
1198 , m_renderSize ((primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN) ? tcu::UVec2(32, 32) : tcu::UVec2(64, 16))
1199 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
1200 , m_graphicsPipeline (context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType)
1201 {
1202 const DeviceInterface& vk = context.getDeviceInterface();
1203 const VkDevice vkDevice = context.getDevice();
1204 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1205 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
1206 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
1207 const bool patchList = m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
1208
1209 // Create color image
1210 {
1211 const VkImageCreateInfo colorImageParams =
1212 {
1213 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1214 DE_NULL, // const void* pNext;
1215 0u, // VkImageCreateFlags flags;
1216 VK_IMAGE_TYPE_2D, // VkImageType imageType;
1217 m_colorFormat, // VkFormat format;
1218 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
1219 1u, // deUint32 mipLevels;
1220 1u, // deUint32 arrayLayers;
1221 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1222 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1223 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
1224 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1225 1u, // deUint32 queueFamilyIndexCount;
1226 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
1227 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
1228 };
1229
1230 m_colorImageCreateInfo = colorImageParams;
1231 m_colorImage = createImage(vk, vkDevice, &m_colorImageCreateInfo);
1232
1233 // Allocate and bind color image memory
1234 m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
1235 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
1236 }
1237
1238 // Create color attachment view
1239 {
1240 const VkImageViewCreateInfo colorAttachmentViewParams =
1241 {
1242 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
1243 DE_NULL, // const void* pNext;
1244 0u, // VkImageViewCreateFlags flags;
1245 *m_colorImage, // VkImage image;
1246 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
1247 m_colorFormat, // VkFormat format;
1248 componentMappingRGBA, // VkComponentMapping components;
1249 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
1250 };
1251
1252 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
1253 }
1254
1255 // Create render pass
1256 m_renderPass = RenderPassWrapper(pipelineConstructionType, vk, vkDevice, m_colorFormat);
1257
1258 // Create framebuffer
1259 {
1260 const VkFramebufferCreateInfo framebufferParams =
1261 {
1262 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
1263 DE_NULL, // const void* pNext;
1264 0u, // VkFramebufferCreateFlags flags;
1265 *m_renderPass, // VkRenderPass renderPass;
1266 1u, // deUint32 attachmentCount;
1267 &m_colorAttachmentView.get(), // const VkImageView* pAttachments;
1268 (deUint32)m_renderSize.x(), // deUint32 width;
1269 (deUint32)m_renderSize.y(), // deUint32 height;
1270 1u // deUint32 layers;
1271 };
1272
1273 m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, *m_colorImage);
1274 }
1275
1276 // Create pipeline layout
1277 {
1278 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1279 {
1280 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1281 DE_NULL, // const void* pNext;
1282 0u, // VkPipelineLayoutCreateFlags flags;
1283 0u, // deUint32 setLayoutCount;
1284 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
1285 0u, // deUint32 pushConstantRangeCount;
1286 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
1287 };
1288
1289 m_pipelineLayout = PipelineLayoutWrapper(pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
1290 }
1291
1292 m_vertexShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
1293 m_fragmentShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
1294
1295 if (patchList)
1296 {
1297 m_tcsShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_tcs"), 0);
1298 m_tesShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_tes"), 0);
1299 }
1300
1301 // Create pipeline
1302 {
1303 const VkVertexInputBindingDescription vertexInputBindingDescription =
1304 {
1305 0u, // deUint32 binding;
1306 sizeof(Vertex4RGBA), // deUint32 stride;
1307 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate;
1308 };
1309
1310 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
1311 {
1312 {
1313 0u, // deUint32 location;
1314 0u, // deUint32 binding;
1315 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
1316 0u // deUint32 offset;
1317 },
1318 {
1319 1u, // deUint32 location;
1320 0u, // deUint32 binding;
1321 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
1322 DE_OFFSET_OF(Vertex4RGBA, color), // deUint32 offset;
1323 }
1324 };
1325
1326 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
1327 {
1328 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1329 DE_NULL, // const void* pNext;
1330 0u, // VkPipelineVertexInputStateCreateFlags flags;
1331 1u, // deUint32 vertexBindingDescriptionCount;
1332 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1333 2u, // deUint32 vertexAttributeDescriptionCount;
1334 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1335 };
1336
1337 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
1338 {
1339 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
1340 DE_NULL, // const void* pNext;
1341 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
1342 m_primitiveTopology, // VkPrimitiveTopology topology;
1343 m_primitiveRestartEnable // VkBool32 primitiveRestartEnable;
1344 };
1345
1346 const std::vector<VkViewport> viewport { makeViewport(m_renderSize) };
1347 const std::vector<VkRect2D> scissor { makeRect2D(m_renderSize) };
1348
1349 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
1350 {
1351 false, // VkBool32 blendEnable;
1352 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
1353 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
1354 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
1355 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
1356 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
1357 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
1358 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask;
1359 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
1360 };
1361
1362 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
1363 {
1364 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
1365 DE_NULL, // const void* pNext;
1366 0u, // VkPipelineColorBlendStateCreateFlags flags;
1367 false, // VkBool32 logicOpEnable;
1368 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
1369 1u, // deUint32 attachmentCount;
1370 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
1371 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4];
1372 };
1373
1374 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
1375 {
1376 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
1377 DE_NULL, // const void* pNext;
1378 0u, // VkPipelineDepthStencilStateCreateFlags flags;
1379 false, // VkBool32 depthTestEnable;
1380 false, // VkBool32 depthWriteEnable;
1381 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
1382 false, // VkBool32 depthBoundsTestEnable;
1383 false, // VkBool32 stencilTestEnable;
1384 // VkStencilOpState front;
1385 {
1386 VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
1387 VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
1388 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
1389 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
1390 0u, // deUint32 compareMask;
1391 0u, // deUint32 writeMask;
1392 0u, // deUint32 reference;
1393 },
1394 // VkStencilOpState back;
1395 {
1396 VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
1397 VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
1398 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
1399 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
1400 0u, // deUint32 compareMask;
1401 0u, // deUint32 writeMask;
1402 0u, // deUint32 reference;
1403 },
1404 0.0f, // float minDepthBounds;
1405 1.0f // float maxDepthBounds;
1406 };
1407
1408 m_graphicsPipeline.setDefaultRasterizationState()
1409 .setDefaultMultisampleState()
1410 .setupVertexInputState(&vertexInputStateParams, &inputAssemblyStateParams)
1411 .setupPreRasterizationShaderState(viewport,
1412 scissor,
1413 m_pipelineLayout,
1414 *m_renderPass,
1415 0u,
1416 m_vertexShaderModule,
1417 DE_NULL,
1418 m_tcsShaderModule,
1419 m_tesShaderModule)
1420 .setupFragmentShaderState(m_pipelineLayout,
1421 *m_renderPass,
1422 0u,
1423 m_fragmentShaderModule,
1424 &depthStencilStateParams)
1425 .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateParams)
1426 .setMonolithicPipelineLayout(m_pipelineLayout)
1427 .buildPipeline();
1428 }
1429
1430 // Create vertex and index buffer
1431 {
1432 const VkBufferCreateInfo indexBufferParams =
1433 {
1434 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1435 DE_NULL, // const void* pNext;
1436 0u, // VkBufferCreateFlags flags;
1437 m_indices.size() * sizeof(deUint32), // VkDeviceSize size;
1438 VK_BUFFER_USAGE_INDEX_BUFFER_BIT, // VkBufferUsageFlags usage;
1439 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1440 1u, // deUint32 queueFamilyIndexCount;
1441 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
1442 };
1443
1444 const VkBufferCreateInfo vertexBufferParams =
1445 {
1446 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1447 DE_NULL, // const void* pNext;
1448 0u, // VkBufferCreateFlags flags;
1449 m_vertices.size() * sizeof(Vertex4RGBA), // VkDeviceSize size;
1450 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
1451 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1452 1u, // deUint32 queueFamilyIndexCount;
1453 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
1454 };
1455
1456 m_indexBuffer = createBuffer(vk, vkDevice, &indexBufferParams);
1457 m_indexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_indexBuffer), MemoryRequirement::HostVisible);
1458
1459 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_indexBuffer, m_indexBufferAlloc->getMemory(), m_indexBufferAlloc->getOffset()));
1460
1461 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
1462 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
1463
1464 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
1465
1466 // Load vertices into index buffer
1467 if (m_indexType == VK_INDEX_TYPE_UINT32)
1468 {
1469 deMemcpy(m_indexBufferAlloc->getHostPtr(), m_indices.data(), m_indices.size() * sizeof(deUint32));
1470 }
1471 else if (m_indexType == VK_INDEX_TYPE_UINT8_EXT)
1472 {
1473 uploadIndexBufferData8((deUint8*)m_indexBufferAlloc->getHostPtr(), m_indices);
1474 }
1475 else // m_indexType == VK_INDEX_TYPE_UINT16
1476 {
1477 uploadIndexBufferData16((deUint16*)m_indexBufferAlloc->getHostPtr(), m_indices);
1478 }
1479
1480 // Load vertices into vertex buffer
1481 deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
1482
1483 flushAlloc(vk, vkDevice, *m_indexBufferAlloc);
1484 flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
1485 }
1486
1487 // Create command pool
1488 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1489
1490 // Create command buffer
1491 {
1492 const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
1493
1494 const VkImageMemoryBarrier attachmentLayoutBarrier =
1495 {
1496 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1497 DE_NULL, // const void* pNext;
1498 0u, // VkAccessFlags srcAccessMask;
1499 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
1500 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1501 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
1502 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1503 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1504 *m_colorImage, // VkImage image;
1505 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
1506 };
1507
1508 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1509
1510 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1511
1512 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0,
1513 0u, DE_NULL, 0u, DE_NULL, 1u, &attachmentLayoutBarrier);
1514
1515 m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
1516
1517 const VkDeviceSize vertexBufferOffset = 0;
1518
1519 m_graphicsPipeline.bind(*m_cmdBuffer);
1520 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1521 vk.cmdBindIndexBuffer(*m_cmdBuffer, *m_indexBuffer, 0, m_indexType);
1522 vk.cmdDrawIndexed(*m_cmdBuffer, (deUint32)m_indices.size(), 1, 0, 0, 0);
1523
1524 m_renderPass.end(vk, *m_cmdBuffer);
1525 endCommandBuffer(vk, *m_cmdBuffer);
1526 }
1527 }
1528
~InputAssemblyInstance(void)1529 InputAssemblyInstance::~InputAssemblyInstance (void)
1530 {
1531 }
1532
iterate(void)1533 tcu::TestStatus InputAssemblyInstance::iterate (void)
1534 {
1535 const DeviceInterface& vk = m_context.getDeviceInterface();
1536 const VkDevice vkDevice = m_context.getDevice();
1537 const VkQueue queue = m_context.getUniversalQueue();
1538
1539 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1540
1541 return verifyImage();
1542 }
1543
verifyImage(void)1544 tcu::TestStatus InputAssemblyInstance::verifyImage (void)
1545 {
1546 const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat);
1547 const tcu::TextureFormat tcuStencilFormat = tcu::TextureFormat();
1548 const ColorVertexShader vertexShader;
1549 const ColorFragmentShader fragmentShader (tcuColorFormat, tcuStencilFormat);
1550 const rr::Program program (&vertexShader, &fragmentShader);
1551 ReferenceRenderer refRenderer (m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuStencilFormat, &program);
1552 bool compareOk = false;
1553
1554 // Render reference image
1555 {
1556 // The reference for tessellated patches are drawn using ordinary triangles.
1557 const rr::PrimitiveType topology = m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST ? rr::PrimitiveType::PRIMITIVETYPE_TRIANGLES : mapVkPrimitiveTopology(m_primitiveTopology);
1558 rr::RenderState renderState (refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
1559
1560 if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
1561 renderState.point.pointSize = 3.0f;
1562
1563 if (m_primitiveRestartEnable)
1564 {
1565 std::vector<deUint32> indicesRange;
1566
1567 for (size_t indexNdx = 0; indexNdx < m_indices.size(); indexNdx++)
1568 {
1569 const bool isRestart = InputAssemblyTest::isRestartIndex(m_indexType, m_indices[indexNdx]);
1570
1571 if (!isRestart)
1572 indicesRange.push_back(m_indices[indexNdx]);
1573
1574 if (isRestart || indexNdx == (m_indices.size() - 1))
1575 {
1576 // Draw the range of indices found so far
1577
1578 std::vector<Vertex4RGBA> nonIndexedVertices;
1579 for (size_t i = 0; i < indicesRange.size(); i++)
1580 nonIndexedVertices.push_back(m_vertices[indicesRange[i]]);
1581
1582 refRenderer.draw(renderState, topology, nonIndexedVertices);
1583 indicesRange.clear();
1584 }
1585 }
1586 }
1587 else
1588 {
1589 std::vector<Vertex4RGBA> nonIndexedVertices;
1590 for (size_t i = 0; i < m_indices.size(); i++)
1591 nonIndexedVertices.push_back(m_vertices[m_indices[i]]);
1592
1593 refRenderer.draw(renderState, topology, nonIndexedVertices);
1594 }
1595 }
1596
1597 // Compare result with reference image
1598 {
1599 const DeviceInterface& vk = m_context.getDeviceInterface();
1600 const VkDevice vkDevice = m_context.getDevice();
1601 const VkQueue queue = m_context.getUniversalQueue();
1602 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1603 SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1604 de::UniquePtr<tcu::TextureLevel> result (readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release());
1605
1606 compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
1607 "IntImageCompare",
1608 "Image comparison",
1609 refRenderer.getAccess(),
1610 result->getAccess(),
1611 tcu::UVec4(2, 2, 2, 2),
1612 tcu::IVec3(1, 1, 0),
1613 true,
1614 tcu::COMPARE_LOG_RESULT);
1615 }
1616
1617 if (compareOk)
1618 return tcu::TestStatus::pass("Result image matches reference");
1619 else
1620 return tcu::TestStatus::fail("Image mismatch");
1621 }
1622
uploadIndexBufferData16(deUint16* destPtr, const std::vector<deUint32>& indexBufferData)1623 void InputAssemblyInstance::uploadIndexBufferData16 (deUint16* destPtr, const std::vector<deUint32>& indexBufferData)
1624 {
1625 for (size_t i = 0; i < indexBufferData.size(); i++)
1626 {
1627 DE_ASSERT(indexBufferData[i] <= 0xFFFF);
1628 destPtr[i] = (deUint16)indexBufferData[i];
1629 }
1630 }
1631
uploadIndexBufferData8(deUint8* destPtr, const std::vector<deUint32>& indexBufferData)1632 void InputAssemblyInstance::uploadIndexBufferData8 (deUint8* destPtr, const std::vector<deUint32>& indexBufferData)
1633 {
1634 for (size_t i = 0; i < indexBufferData.size(); i++)
1635 {
1636 DE_ASSERT(indexBufferData[i] <= 0xFF);
1637 destPtr[i] = (deUint8)indexBufferData[i];
1638 }
1639 }
1640
1641
1642 // Utilities for test names
1643
getPrimitiveTopologyCaseName(VkPrimitiveTopology topology)1644 std::string getPrimitiveTopologyCaseName (VkPrimitiveTopology topology)
1645 {
1646 const std::string fullName = getPrimitiveTopologyName(topology);
1647
1648 DE_ASSERT(de::beginsWith(fullName, "VK_PRIMITIVE_TOPOLOGY_"));
1649
1650 return de::toLower(fullName.substr(22));
1651 }
1652
createPrimitiveTopologyTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)1653 de::MovePtr<tcu::TestCaseGroup> createPrimitiveTopologyTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
1654 {
1655 de::MovePtr<tcu::TestCaseGroup> primitiveTopologyTests (new tcu::TestCaseGroup(testCtx, "primitive_topology"));
1656
1657 de::MovePtr<tcu::TestCaseGroup> indexUint16Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint16"));
1658 de::MovePtr<tcu::TestCaseGroup> indexUint32Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint32"));
1659 de::MovePtr<tcu::TestCaseGroup> indexUint8Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint8"));
1660
1661 for (int topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(InputAssemblyTest::s_primitiveTopologies); topologyNdx++)
1662 {
1663 const VkPrimitiveTopology topology = InputAssemblyTest::s_primitiveTopologies[topologyNdx];
1664
1665 indexUint16Tests->addChild(new PrimitiveTopologyTest(testCtx,
1666 getPrimitiveTopologyCaseName(topology),
1667 pipelineConstructionType,
1668 topology,
1669 VK_INDEX_TYPE_UINT16));
1670
1671 indexUint32Tests->addChild(new PrimitiveTopologyTest(testCtx,
1672 getPrimitiveTopologyCaseName(topology),
1673 pipelineConstructionType,
1674 topology,
1675 VK_INDEX_TYPE_UINT32));
1676
1677 indexUint8Tests->addChild(new PrimitiveTopologyTest(testCtx,
1678 getPrimitiveTopologyCaseName(topology),
1679 pipelineConstructionType,
1680 topology,
1681 VK_INDEX_TYPE_UINT8_EXT));
1682 }
1683
1684 primitiveTopologyTests->addChild(indexUint16Tests.release());
1685 primitiveTopologyTests->addChild(indexUint32Tests.release());
1686 primitiveTopologyTests->addChild(indexUint8Tests.release());
1687
1688 return primitiveTopologyTests;
1689 }
1690
1691 #ifndef CTS_USES_VULKANSC
createPrimitiveRestartTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)1692 de::MovePtr<tcu::TestCaseGroup> createPrimitiveRestartTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
1693 {
1694 const VkPrimitiveTopology primitiveRestartTopologies[] =
1695 {
1696 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
1697 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
1698 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
1699 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
1700 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,
1701
1702 // Supported with VK_EXT_primitive_topology_list_restart
1703 VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
1704 VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
1705 VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
1706 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
1707 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
1708 VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
1709 };
1710
1711 de::MovePtr<tcu::TestCaseGroup> primitiveRestartTests (new tcu::TestCaseGroup(testCtx, "primitive_restart"));
1712
1713 de::MovePtr<tcu::TestCaseGroup> indexUint16Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint16"));
1714 de::MovePtr<tcu::TestCaseGroup> indexUint32Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint32"));
1715 de::MovePtr<tcu::TestCaseGroup> indexUint8Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint8"));
1716
1717 constexpr struct RestartTest
1718 {
1719 RestartType type;
1720 const char* name;
1721 } restartTypes[] =
1722 {
1723 { RestartType::NORMAL, "", },
1724 { RestartType::NONE, "no_restart_", },
1725 { RestartType::ALL, "restart_all_" },
1726 };
1727
1728 for (int topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(primitiveRestartTopologies); topologyNdx++)
1729 {
1730 const VkPrimitiveTopology topology = primitiveRestartTopologies[topologyNdx];
1731
1732 for (int useRestartNdx = 0; useRestartNdx < DE_LENGTH_OF_ARRAY(restartTypes); useRestartNdx++)
1733 {
1734 if (topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && restartTypes[useRestartNdx].type == RestartType::ALL) {
1735 continue;
1736 }
1737 indexUint16Tests->addChild(new PrimitiveRestartTest(testCtx,
1738 restartTypes[useRestartNdx].name + getPrimitiveTopologyCaseName(topology),
1739 pipelineConstructionType,
1740 topology,
1741 VK_INDEX_TYPE_UINT16,
1742 restartTypes[useRestartNdx].type));
1743
1744 indexUint32Tests->addChild(new PrimitiveRestartTest(testCtx,
1745 restartTypes[useRestartNdx].name + getPrimitiveTopologyCaseName(topology),
1746 pipelineConstructionType,
1747 topology,
1748 VK_INDEX_TYPE_UINT32,
1749 restartTypes[useRestartNdx].type));
1750
1751 indexUint8Tests->addChild(new PrimitiveRestartTest(testCtx,
1752 restartTypes[useRestartNdx].name + getPrimitiveTopologyCaseName(topology),
1753 pipelineConstructionType,
1754 topology,
1755 VK_INDEX_TYPE_UINT8_EXT,
1756 restartTypes[useRestartNdx].type));
1757 }
1758 }
1759
1760 // Tests that have primitive restart disabled, but have indices with restart index value.
1761 if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1762 {
1763 struct
1764 {
1765 std::string name;
1766 std::vector<std::string> requirements;
1767 } tests[] =
1768 {
1769 { "line_list", { "VK_EXT_primitive_topology_list_restart" } },
1770 { "line_list_with_adjacency", { "Features.geometryShader", "VK_EXT_primitive_topology_list_restart" } },
1771 { "line_strip", {} },
1772 { "line_strip_with_adjacency", {"Features.geometryShader"} },
1773 { "patch_list", { "VK_EXT_primitive_topology_list_restart", "Features.tessellationShader" } },
1774 { "point_list", { "VK_EXT_primitive_topology_list_restart" } },
1775 { "triangle_fan", {} },
1776 { "triangle_list", { "VK_EXT_primitive_topology_list_restart" } },
1777 { "triangle_list_with_adjacency", { "Features.geometryShader", "VK_EXT_primitive_topology_list_restart" } },
1778 { "triangle_strip", {} },
1779 { "triangle_strip_with_adjacency", {"Features.geometryShader"} }
1780 };
1781
1782 const std::string dataDir = "pipeline/input_assembly/primitive_restart";
1783
1784 for (auto& test : tests)
1785 {
1786 std::string testName = "restart_disabled_" + test.name;
1787 indexUint16Tests->addChild(cts_amber::createAmberTestCase(testCtx, testName.c_str(), dataDir.c_str(), testName + "_uint16.amber", test.requirements));
1788 test.requirements.push_back("VK_EXT_index_type_uint8");
1789 indexUint8Tests->addChild(cts_amber::createAmberTestCase(testCtx, testName.c_str(), dataDir.c_str(), testName + "_uint8.amber", test.requirements));
1790 }
1791 }
1792
1793 primitiveRestartTests->addChild(indexUint16Tests.release());
1794 primitiveRestartTests->addChild(indexUint32Tests.release());
1795 primitiveRestartTests->addChild(indexUint8Tests.release());
1796
1797 return primitiveRestartTests;
1798 }
1799 #endif // CTS_USES_VULKANSC
1800
1801 } // anonymous
1802
createInputAssemblyTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)1803 tcu::TestCaseGroup* createInputAssemblyTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
1804 {
1805 de::MovePtr<tcu::TestCaseGroup> inputAssemblyTests (new tcu::TestCaseGroup(testCtx, "input_assembly"));
1806
1807 inputAssemblyTests->addChild(createPrimitiveTopologyTests(testCtx, pipelineConstructionType).release());
1808 #ifndef CTS_USES_VULKANSC
1809 inputAssemblyTests->addChild(createPrimitiveRestartTests(testCtx, pipelineConstructionType).release());
1810 #endif // CTS_USES_VULKANSC
1811
1812 return inputAssemblyTests.release();
1813 }
1814
1815 } // pipeline
1816 } // vkt
1817