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