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