1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Intel Corporation
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 Simple Draw Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktDrawSimpleTest.hpp"
26
27 #include "vktTestCaseUtil.hpp"
28 #include "vktDrawTestCaseUtil.hpp"
29
30 #include "vktDrawBaseClass.hpp"
31
32 #include "tcuTestLog.hpp"
33 #include "tcuResource.hpp"
34 #include "tcuImageCompare.hpp"
35 #include "tcuTextureUtil.hpp"
36 #include "tcuRGBA.hpp"
37
38 #include "vkDefs.hpp"
39 #include "vkCmdUtil.hpp"
40
41 namespace vkt
42 {
43 namespace Draw
44 {
45 namespace
46 {
47 class SimpleDraw : public DrawTestsBaseClass
48 {
49 public:
50 typedef TestSpecBase TestSpec;
51 SimpleDraw(Context &context, TestSpec testSpec);
52 virtual tcu::TestStatus iterate(void);
53 void draw(vk::VkCommandBuffer cmdBuffer, uint32_t instanceCount = 1u, uint32_t firstInstance = 0u);
54 };
55
56 class SimpleDrawInstanced : public SimpleDraw
57 {
58 public:
59 typedef TestSpec TestSpec;
60 SimpleDrawInstanced(Context &context, TestSpec testSpec);
61 tcu::TestStatus iterate(void);
62 };
63
SimpleDraw(Context & context,TestSpec testSpec)64 SimpleDraw::SimpleDraw(Context &context, TestSpec testSpec)
65 : DrawTestsBaseClass(context, testSpec.shaders[glu::SHADERTYPE_VERTEX], testSpec.shaders[glu::SHADERTYPE_FRAGMENT],
66 testSpec.groupParams, testSpec.topology)
67 {
68 m_data.push_back(VertexElementData(tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
69 m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
70
71 int refVertexIndex = 2;
72
73 switch (m_topology)
74 {
75 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
76 m_data.push_back(
77 VertexElementData(tcu::Vec4(-0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
78 m_data.push_back(
79 VertexElementData(tcu::Vec4(-0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
80 m_data.push_back(
81 VertexElementData(tcu::Vec4(0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
82 m_data.push_back(
83 VertexElementData(tcu::Vec4(0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
84 m_data.push_back(
85 VertexElementData(tcu::Vec4(0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
86 m_data.push_back(
87 VertexElementData(tcu::Vec4(-0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
88 break;
89 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
90 m_data.push_back(
91 VertexElementData(tcu::Vec4(-0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
92 m_data.push_back(
93 VertexElementData(tcu::Vec4(-0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
94 m_data.push_back(
95 VertexElementData(tcu::Vec4(0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
96 m_data.push_back(
97 VertexElementData(tcu::Vec4(0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
98 m_data.push_back(
99 VertexElementData(tcu::Vec4(-0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
100 break;
101 case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
102 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
103 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
104 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
105 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
106 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
107 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
108 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
109 case vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
110 case vk::VK_PRIMITIVE_TOPOLOGY_LAST:
111 DE_FATAL("Topology not implemented");
112 break;
113 default:
114 DE_FATAL("Unknown topology");
115 break;
116 }
117
118 m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
119
120 initialize();
121 }
122
iterate(void)123 tcu::TestStatus SimpleDraw::iterate(void)
124 {
125 tcu::TestLog &log = m_context.getTestContext().getLog();
126 const vk::VkQueue queue = m_context.getUniversalQueue();
127 const vk::VkDevice device = m_context.getDevice();
128 const vk::VkDeviceSize vertexBufferOffset = 0;
129 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
130
131 #ifndef CTS_USES_VULKANSC
132 if (m_groupParams->useSecondaryCmdBuffer)
133 {
134 // record secondary command buffer
135 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
136 {
137 beginSecondaryCmdBuffer(m_vk, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
138 beginDynamicRender(*m_secCmdBuffer);
139 }
140 else
141 beginSecondaryCmdBuffer(m_vk);
142
143 m_vk.cmdBindVertexBuffers(*m_secCmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
144 m_vk.cmdBindPipeline(*m_secCmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
145 draw(*m_secCmdBuffer);
146
147 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
148 endDynamicRender(*m_secCmdBuffer);
149
150 endCommandBuffer(m_vk, *m_secCmdBuffer);
151
152 // record primary command buffer
153 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
154 preRenderBarriers();
155
156 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
157 beginDynamicRender(*m_cmdBuffer, vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
158
159 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
160
161 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
162 endDynamicRender(*m_cmdBuffer);
163
164 endCommandBuffer(m_vk, *m_cmdBuffer);
165 }
166 else if (m_groupParams->useDynamicRendering)
167 {
168 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
169 preRenderBarriers();
170 beginDynamicRender(*m_cmdBuffer);
171
172 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
173 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
174 draw(*m_cmdBuffer);
175
176 endDynamicRender(*m_cmdBuffer);
177 endCommandBuffer(m_vk, *m_cmdBuffer);
178 }
179 #endif // CTS_USES_VULKANSC
180
181 if (!m_groupParams->useDynamicRendering)
182 {
183 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
184 preRenderBarriers();
185 beginLegacyRender(*m_cmdBuffer);
186
187 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
188 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
189 draw(*m_cmdBuffer);
190
191 endLegacyRender(*m_cmdBuffer);
192 endCommandBuffer(m_vk, *m_cmdBuffer);
193 }
194
195 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
196
197 // Validation
198 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)),
199 (int)(0.5f + static_cast<float>(HEIGHT)));
200
201 referenceFrame.allocLevel(0);
202
203 const int32_t frameWidth = referenceFrame.getWidth();
204 const int32_t frameHeight = referenceFrame.getHeight();
205
206 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
207
208 ReferenceImageCoordinates refCoords;
209
210 for (int y = 0; y < frameHeight; y++)
211 {
212 const float yCoord = (float)(y / (0.5 * frameHeight)) - 1.0f;
213
214 for (int x = 0; x < frameWidth; x++)
215 {
216 const float xCoord = (float)(x / (0.5 * frameWidth)) - 1.0f;
217
218 if ((yCoord >= refCoords.bottom && yCoord <= refCoords.top && xCoord >= refCoords.left &&
219 xCoord <= refCoords.right))
220 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
221 }
222 }
223
224 const vk::VkOffset3D zeroOffset = {0, 0, 0};
225 const tcu::ConstPixelBufferAccess renderedFrame =
226 m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset,
227 WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
228
229 qpTestResult res = QP_TEST_RESULT_PASS;
230
231 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result", referenceFrame.getLevel(0), renderedFrame, 0.05f,
232 tcu::COMPARE_LOG_RESULT))
233 {
234 res = QP_TEST_RESULT_FAIL;
235 }
236
237 return tcu::TestStatus(res, qpGetTestResultName(res));
238 }
239
draw(vk::VkCommandBuffer cmdBuffer,uint32_t instanceCount,uint32_t firstInstance)240 void SimpleDraw::draw(vk::VkCommandBuffer cmdBuffer, uint32_t instanceCount, uint32_t firstInstance)
241 {
242 switch (m_topology)
243 {
244 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
245 m_vk.cmdDraw(cmdBuffer, 6, instanceCount, 2, firstInstance);
246 break;
247 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
248 m_vk.cmdDraw(cmdBuffer, 4, instanceCount, 2, firstInstance);
249 break;
250 case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
251 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
252 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
253 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
254 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
255 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
256 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
257 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
258 case vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
259 case vk::VK_PRIMITIVE_TOPOLOGY_LAST:
260 DE_FATAL("Topology not implemented");
261 break;
262 default:
263 DE_FATAL("Unknown topology");
264 break;
265 }
266 }
267
SimpleDrawInstanced(Context & context,TestSpec testSpec)268 SimpleDrawInstanced::SimpleDrawInstanced(Context &context, TestSpec testSpec) : SimpleDraw(context, testSpec)
269 {
270 }
271
iterate(void)272 tcu::TestStatus SimpleDrawInstanced::iterate(void)
273 {
274 tcu::TestLog &log = m_context.getTestContext().getLog();
275 const vk::VkQueue queue = m_context.getUniversalQueue();
276 const vk::VkDevice device = m_context.getDevice();
277 const vk::VkDeviceSize vertexBufferOffset = 0;
278 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
279
280 #ifndef CTS_USES_VULKANSC
281 if (m_groupParams->useSecondaryCmdBuffer)
282 {
283 // record secondary command buffer
284 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
285 {
286 beginSecondaryCmdBuffer(m_vk, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
287 beginDynamicRender(*m_secCmdBuffer);
288 }
289 else
290 beginSecondaryCmdBuffer(m_vk);
291
292 m_vk.cmdBindVertexBuffers(*m_secCmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
293 m_vk.cmdBindPipeline(*m_secCmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
294 draw(*m_secCmdBuffer, 4u, 2u);
295
296 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
297 endDynamicRender(*m_secCmdBuffer);
298
299 endCommandBuffer(m_vk, *m_secCmdBuffer);
300
301 // record primary command buffer
302 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
303 preRenderBarriers();
304
305 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
306 beginDynamicRender(*m_cmdBuffer, vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
307
308 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
309
310 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
311 endDynamicRender(*m_cmdBuffer);
312
313 endCommandBuffer(m_vk, *m_cmdBuffer);
314 }
315 else if (m_groupParams->useDynamicRendering)
316 {
317 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
318 preRenderBarriers();
319
320 beginDynamicRender(*m_cmdBuffer);
321 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
322 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
323 draw(*m_cmdBuffer, 4u, 2u);
324 endDynamicRender(*m_cmdBuffer);
325
326 endCommandBuffer(m_vk, *m_cmdBuffer);
327 }
328 #endif // CTS_USES_VULKANSC
329
330 if (!m_groupParams->useDynamicRendering)
331 {
332 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
333 preRenderBarriers();
334
335 beginLegacyRender(*m_cmdBuffer);
336 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
337 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
338 draw(*m_cmdBuffer, 4u, 2u);
339 endLegacyRender(*m_cmdBuffer);
340
341 endCommandBuffer(m_vk, *m_cmdBuffer);
342 }
343
344 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
345
346 // Validation
347 VK_CHECK(m_vk.queueWaitIdle(queue));
348
349 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)),
350 (int)(0.5f + static_cast<float>(HEIGHT)));
351
352 referenceFrame.allocLevel(0);
353
354 const int32_t frameWidth = referenceFrame.getWidth();
355 const int32_t frameHeight = referenceFrame.getHeight();
356
357 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
358
359 ReferenceImageInstancedCoordinates refInstancedCoords;
360
361 for (int y = 0; y < frameHeight; y++)
362 {
363 const float yCoord = (float)(y / (0.5 * frameHeight)) - 1.0f;
364
365 for (int x = 0; x < frameWidth; x++)
366 {
367 const float xCoord = (float)(x / (0.5 * frameWidth)) - 1.0f;
368
369 if ((yCoord >= refInstancedCoords.bottom && yCoord <= refInstancedCoords.top &&
370 xCoord >= refInstancedCoords.left && xCoord <= refInstancedCoords.right))
371 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
372 }
373 }
374
375 const vk::VkOffset3D zeroOffset = {0, 0, 0};
376 const tcu::ConstPixelBufferAccess renderedFrame =
377 m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset,
378 WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
379
380 qpTestResult res = QP_TEST_RESULT_PASS;
381
382 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result", referenceFrame.getLevel(0), renderedFrame, 0.05f,
383 tcu::COMPARE_LOG_RESULT))
384 {
385 res = QP_TEST_RESULT_FAIL;
386 }
387
388 return tcu::TestStatus(res, qpGetTestResultName(res));
389 }
390
checkSupport(Context & context,SimpleDraw::TestSpec testSpec)391 void checkSupport(Context &context, SimpleDraw::TestSpec testSpec)
392 {
393 if (testSpec.groupParams->useDynamicRendering)
394 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
395 }
396
397 } // namespace
398
SimpleDrawTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)399 SimpleDrawTests::SimpleDrawTests(tcu::TestContext &testCtx, const SharedGroupParams groupParams)
400 : TestCaseGroup(testCtx, "simple_draw")
401 , m_groupParams(groupParams)
402 {
403 /* Left blank on purpose */
404 }
405
~SimpleDrawTests(void)406 SimpleDrawTests::~SimpleDrawTests(void)
407 {
408 }
409
init(void)410 void SimpleDrawTests::init(void)
411 {
412 {
413 SimpleDraw::TestSpec testSpec{
414 {// ShaderMap shaders;
415 {glu::SHADERTYPE_VERTEX, "vulkan/draw/VertexFetch.vert"},
416 {glu::SHADERTYPE_FRAGMENT, "vulkan/draw/VertexFetch.frag"}},
417 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // vk::VkPrimitiveTopology topology;
418 m_groupParams // const SharedGroupParams groupParams;
419 };
420
421 addChild(new InstanceFactory<SimpleDraw, FunctionSupport1<SimpleDraw::TestSpec>>(
422 m_testCtx, "simple_draw_triangle_list", testSpec,
423 FunctionSupport1<SimpleDraw::TestSpec>::Args(checkSupport, testSpec)));
424 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
425 addChild(new InstanceFactory<SimpleDraw, FunctionSupport1<SimpleDraw::TestSpec>>(
426 m_testCtx, "simple_draw_triangle_strip", testSpec,
427 FunctionSupport1<SimpleDraw::TestSpec>::Args(checkSupport, testSpec)));
428 }
429 {
430 SimpleDrawInstanced::TestSpec testSpec{
431 {{glu::SHADERTYPE_VERTEX, "vulkan/draw/VertexFetchInstancedFirstInstance.vert"},
432 {glu::SHADERTYPE_FRAGMENT, "vulkan/draw/VertexFetch.frag"}},
433 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
434 m_groupParams};
435
436 addChild(new InstanceFactory<SimpleDrawInstanced, FunctionSupport1<SimpleDrawInstanced::TestSpec>>(
437 m_testCtx, "simple_draw_instanced_triangle_list", testSpec,
438 FunctionSupport1<SimpleDrawInstanced::TestSpec>::Args(checkSupport, testSpec)));
439 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
440 addChild(new InstanceFactory<SimpleDrawInstanced, FunctionSupport1<SimpleDrawInstanced::TestSpec>>(
441 m_testCtx, "simple_draw_instanced_triangle_strip", testSpec,
442 FunctionSupport1<SimpleDrawInstanced::TestSpec>::Args(checkSupport, testSpec)));
443 }
444 }
445
446 } // namespace Draw
447 } // namespace vkt
448