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