1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Intel Corporation
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Simple Draw Tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktDrawSimpleTest.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktDrawTestCaseUtil.hpp"
30 #include "vktDrawBaseClass.hpp"
32 #include "tcuTestLog.hpp"
33 #include "tcuResource.hpp"
34 #include "tcuImageCompare.hpp"
35 #include "tcuTextureUtil.hpp"
36 #include "tcuRGBA.hpp"
39 #include "vkCmdUtil.hpp"
47 class SimpleDraw : public DrawTestsBaseClass
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);
56 class SimpleDrawInstanced : public SimpleDraw
59 typedef TestSpec TestSpec;
60 SimpleDrawInstanced (Context &context, TestSpec testSpec);
61 tcu::TestStatus iterate (void);
64 SimpleDraw::SimpleDraw (Context &context, TestSpec testSpec)
65 : DrawTestsBaseClass(context, testSpec.shaders[glu::SHADERTYPE_VERTEX], testSpec.shaders[glu::SHADERTYPE_FRAGMENT], testSpec.groupParams, testSpec.topology)
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));
70 int refVertexIndex = 2;
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++));
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++));
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");
102 DE_FATAL("Unknown topology");
106 m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
111 tcu::TestStatus SimpleDraw::iterate (void)
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();
119 #ifndef CTS_USES_VULKANSC
120 if (m_groupParams->useSecondaryCmdBuffer)
122 // record secondary command buffer
123 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
125 beginSecondaryCmdBuffer(m_vk, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
126 beginDynamicRender(*m_secCmdBuffer);
129 beginSecondaryCmdBuffer(m_vk);
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);
135 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
136 endDynamicRender(*m_secCmdBuffer);
138 endCommandBuffer(m_vk, *m_secCmdBuffer);
140 // record primary command buffer
141 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
144 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
145 beginDynamicRender(*m_cmdBuffer, vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
147 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
149 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
150 endDynamicRender(*m_cmdBuffer);
152 endCommandBuffer(m_vk, *m_cmdBuffer);
154 else if (m_groupParams->useDynamicRendering)
156 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
158 beginDynamicRender(*m_cmdBuffer);
160 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
161 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
164 endDynamicRender(*m_cmdBuffer);
165 endCommandBuffer(m_vk, *m_cmdBuffer);
167 #endif // CTS_USES_VULKANSC
169 if (!m_groupParams->useDynamicRendering)
171 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
173 beginLegacyRender(*m_cmdBuffer);
175 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
176 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
179 endLegacyRender(*m_cmdBuffer);
180 endCommandBuffer(m_vk, *m_cmdBuffer);
183 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
186 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
188 referenceFrame.allocLevel(0);
190 const deInt32 frameWidth = referenceFrame.getWidth();
191 const deInt32 frameHeight = referenceFrame.getHeight();
193 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
195 ReferenceImageCoordinates refCoords;
197 for (int y = 0; y < frameHeight; y++)
199 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
201 for (int x = 0; x < frameWidth; x++)
203 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
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);
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);
217 qpTestResult res = QP_TEST_RESULT_PASS;
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;
225 return tcu::TestStatus(res, qpGetTestResultName(res));
229 void SimpleDraw::draw(vk::VkCommandBuffer cmdBuffer, deUint32 instanceCount, deUint32 firstInstance)
233 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
234 m_vk.cmdDraw(cmdBuffer, 6, instanceCount, 2, firstInstance);
236 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
237 m_vk.cmdDraw(cmdBuffer, 4, instanceCount, 2, firstInstance);
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");
252 DE_FATAL("Unknown topology");
257 SimpleDrawInstanced::SimpleDrawInstanced (Context &context, TestSpec testSpec)
258 : SimpleDraw (context, testSpec) {}
260 tcu::TestStatus SimpleDrawInstanced::iterate (void)
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();
268 #ifndef CTS_USES_VULKANSC
269 if (m_groupParams->useSecondaryCmdBuffer)
271 // record secondary command buffer
272 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
274 beginSecondaryCmdBuffer(m_vk, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
275 beginDynamicRender(*m_secCmdBuffer);
278 beginSecondaryCmdBuffer(m_vk);
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);
284 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
285 endDynamicRender(*m_secCmdBuffer);
287 endCommandBuffer(m_vk, *m_secCmdBuffer);
289 // record primary command buffer
290 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
293 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
294 beginDynamicRender(*m_cmdBuffer, vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
296 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
298 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
299 endDynamicRender(*m_cmdBuffer);
301 endCommandBuffer(m_vk, *m_cmdBuffer);
303 else if (m_groupParams->useDynamicRendering)
305 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
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);
314 endCommandBuffer(m_vk, *m_cmdBuffer);
316 #endif // CTS_USES_VULKANSC
318 if (!m_groupParams->useDynamicRendering)
320 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
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);
329 endCommandBuffer(m_vk, *m_cmdBuffer);
332 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
335 VK_CHECK(m_vk.queueWaitIdle(queue));
337 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
339 referenceFrame.allocLevel(0);
341 const deInt32 frameWidth = referenceFrame.getWidth();
342 const deInt32 frameHeight = referenceFrame.getHeight();
344 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
346 ReferenceImageInstancedCoordinates refInstancedCoords;
348 for (int y = 0; y < frameHeight; y++)
350 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
352 for (int x = 0; x < frameWidth; x++)
354 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
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);
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);
368 qpTestResult res = QP_TEST_RESULT_PASS;
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;
376 return tcu::TestStatus(res, qpGetTestResultName(res));
379 void checkSupport(Context& context, SimpleDraw::TestSpec testSpec)
381 if (testSpec.groupParams->useDynamicRendering)
382 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
387 SimpleDrawTests::SimpleDrawTests (tcu::TestContext &testCtx, const SharedGroupParams groupParams)
388 : TestCaseGroup (testCtx, "simple_draw", "drawing simple geometry")
389 , m_groupParams (groupParams)
391 /* Left blank on purpose */
394 SimpleDrawTests::~SimpleDrawTests (void) {}
396 void SimpleDrawTests::init (void)
399 SimpleDraw::TestSpec testSpec
401 { // ShaderMap shaders;
402 { glu::SHADERTYPE_VERTEX, "vulkan/draw/VertexFetch.vert" },
403 { glu::SHADERTYPE_FRAGMENT, "vulkan/draw/VertexFetch.frag" }
405 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // vk::VkPrimitiveTopology topology;
406 m_groupParams // const SharedGroupParams groupParams;
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)));
416 SimpleDrawInstanced::TestSpec testSpec
419 { glu::SHADERTYPE_VERTEX, "vulkan/draw/VertexFetchInstancedFirstInstance.vert" },
420 { glu::SHADERTYPE_FRAGMENT, "vulkan/draw/VertexFetch.frag" }
422 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
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)));