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 Draw Indexed Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktDrawIndexedTest.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 enum
42 {
43 VERTEX_OFFSET = 13
44 };
45
46 namespace vkt
47 {
48 namespace Draw
49 {
50 namespace
51 {
52 class DrawIndexed : public DrawTestsBaseClass
53 {
54 public:
55 typedef TestSpecBase TestSpec;
56
57 DrawIndexed (Context &context, TestSpec testSpec);
58 virtual tcu::TestStatus iterate (void);
59 protected:
60 std::vector<deUint32> m_indexes;
61 de::SharedPtr<Buffer> m_indexBuffer;
62 };
63
64 class DrawInstancedIndexed : public DrawIndexed
65 {
66 public:
67 DrawInstancedIndexed (Context &context, TestSpec testSpec);
68 virtual tcu::TestStatus iterate (void);
69 };
70
DrawIndexed(Context & context,TestSpec testSpec)71 DrawIndexed::DrawIndexed (Context &context, TestSpec testSpec)
72 : DrawTestsBaseClass(context, testSpec.shaders[glu::SHADERTYPE_VERTEX], testSpec.shaders[glu::SHADERTYPE_FRAGMENT], testSpec.topology)
73 {
74 switch (m_topology)
75 {
76 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
77 m_indexes.push_back(0);
78 m_indexes.push_back(0);
79 m_indexes.push_back(2);
80 m_indexes.push_back(0);
81 m_indexes.push_back(6);
82 m_indexes.push_back(6);
83 m_indexes.push_back(0);
84 m_indexes.push_back(7);
85 break;
86 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
87 m_indexes.push_back(0);
88 m_indexes.push_back(0);
89 m_indexes.push_back(2);
90 m_indexes.push_back(0);
91 m_indexes.push_back(6);
92 m_indexes.push_back(5);
93 m_indexes.push_back(0);
94 m_indexes.push_back(7);
95 break;
96
97 case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
98 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
99 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
100 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
101 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
102 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
103 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
104 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
105 case vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
106 case vk::VK_PRIMITIVE_TOPOLOGY_LAST:
107 DE_FATAL("Topology not implemented");
108 break;
109 default:
110 DE_FATAL("Unknown topology");
111 break;
112 }
113
114 for (int unusedIdx = 0; unusedIdx < VERTEX_OFFSET; unusedIdx++)
115 {
116 m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
117 }
118
119 int vertexIndex = VERTEX_OFFSET;
120
121 m_data.push_back(VertexElementData(tcu::Vec4( -0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), vertexIndex++));
122 m_data.push_back(VertexElementData(tcu::Vec4( -1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), vertexIndex++));
123 m_data.push_back(VertexElementData(tcu::Vec4( -0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), vertexIndex++));
124 m_data.push_back(VertexElementData(tcu::Vec4( 1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), vertexIndex++));
125 m_data.push_back(VertexElementData(tcu::Vec4( -0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), vertexIndex++));
126 m_data.push_back(VertexElementData(tcu::Vec4( 0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), vertexIndex++));
127 m_data.push_back(VertexElementData(tcu::Vec4( 0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), vertexIndex++));
128 m_data.push_back(VertexElementData(tcu::Vec4( 0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), vertexIndex++));
129
130 m_data.push_back(VertexElementData(tcu::Vec4( -1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
131
132 initialize();
133 };
134
iterate(void)135 tcu::TestStatus DrawIndexed::iterate (void)
136 {
137 tcu::TestLog& log = m_context.getTestContext().getLog();
138 const vk::VkQueue queue = m_context.getUniversalQueue();
139 const vk::VkDevice device = m_context.getDevice();
140
141 beginRenderPass();
142
143 const vk::VkDeviceSize dataSize = m_indexes.size() * sizeof(deUint32);
144 m_indexBuffer = Buffer::createAndAlloc( m_vk, m_context.getDevice(),
145 BufferCreateInfo(dataSize,
146 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT),
147 m_context.getDefaultAllocator(),
148 vk::MemoryRequirement::HostVisible);
149
150 deUint8* ptr = reinterpret_cast<deUint8*>(m_indexBuffer->getBoundMemory().getHostPtr());
151 deMemcpy(ptr, &m_indexes[0], static_cast<size_t>(dataSize));
152 vk::flushAlloc(m_vk, m_context.getDevice(), m_indexBuffer->getBoundMemory());
153
154 const vk::VkDeviceSize vertexBufferOffset = 0;
155 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
156 const vk::VkBuffer indexBuffer = m_indexBuffer->object();
157
158 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
159 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, indexBuffer, 0, vk::VK_INDEX_TYPE_UINT32);
160
161 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
162
163 m_vk.cmdDrawIndexed(*m_cmdBuffer, 6, 1, 2, VERTEX_OFFSET, 0);
164
165 endRenderPass(m_vk, *m_cmdBuffer);
166 endCommandBuffer(m_vk, *m_cmdBuffer);
167
168 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
169
170 // Validation
171 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
172 referenceFrame.allocLevel(0);
173
174 const deInt32 frameWidth = referenceFrame.getWidth();
175 const deInt32 frameHeight = referenceFrame.getHeight();
176
177 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
178
179 ReferenceImageCoordinates refCoords;
180
181 for (int y = 0; y < frameHeight; y++)
182 {
183 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
184
185 for (int x = 0; x < frameWidth; x++)
186 {
187 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
188
189 if ((yCoord >= refCoords.bottom &&
190 yCoord <= refCoords.top &&
191 xCoord >= refCoords.left &&
192 xCoord <= refCoords.right))
193 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
194 }
195 }
196
197 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
198 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
199 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
200
201 qpTestResult res = QP_TEST_RESULT_PASS;
202
203 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
204 referenceFrame.getLevel(0), renderedFrame, 0.05f,
205 tcu::COMPARE_LOG_RESULT)) {
206 res = QP_TEST_RESULT_FAIL;
207 }
208
209 return tcu::TestStatus(res, qpGetTestResultName(res));
210 };
211
DrawInstancedIndexed(Context & context,TestSpec testSpec)212 DrawInstancedIndexed::DrawInstancedIndexed (Context &context, TestSpec testSpec)
213 : DrawIndexed (context, testSpec)
214 {
215 }
216
iterate(void)217 tcu::TestStatus DrawInstancedIndexed::iterate (void)
218 {
219 tcu::TestLog& log = m_context.getTestContext().getLog();
220 const vk::VkQueue queue = m_context.getUniversalQueue();
221 const vk::VkDevice device = m_context.getDevice();
222
223 beginRenderPass();
224
225 const vk::VkDeviceSize dataSize = m_indexes.size() * sizeof(deUint32);
226 m_indexBuffer = Buffer::createAndAlloc( m_vk, m_context.getDevice(),
227 BufferCreateInfo(dataSize,
228 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT),
229 m_context.getDefaultAllocator(),
230 vk::MemoryRequirement::HostVisible);
231
232 deUint8* ptr = reinterpret_cast<deUint8*>(m_indexBuffer->getBoundMemory().getHostPtr());
233
234 deMemcpy(ptr, &m_indexes[0], static_cast<size_t>(dataSize));
235 vk::flushAlloc(m_vk, m_context.getDevice(), m_indexBuffer->getBoundMemory());
236
237 const vk::VkDeviceSize vertexBufferOffset = 0;
238 const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
239 const vk::VkBuffer indexBuffer = m_indexBuffer->object();
240
241 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
242 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, indexBuffer, 0, vk::VK_INDEX_TYPE_UINT32);
243 m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
244
245 switch (m_topology)
246 {
247 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
248 m_vk.cmdDrawIndexed(*m_cmdBuffer, 6, 4, 2, VERTEX_OFFSET, 2);
249 break;
250 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
251 m_vk.cmdDrawIndexed(*m_cmdBuffer, 4, 4, 2, VERTEX_OFFSET, 2);
252 break;
253 case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
254 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
255 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
256 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
257 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
258 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
259 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
260 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
261 case vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
262 case vk::VK_PRIMITIVE_TOPOLOGY_LAST:
263 DE_FATAL("Topology not implemented");
264 break;
265 default:
266 DE_FATAL("Unknown topology");
267 break;
268 }
269
270 endRenderPass(m_vk, *m_cmdBuffer);
271 endCommandBuffer(m_vk, *m_cmdBuffer);
272
273 submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
274
275 // Validation
276 VK_CHECK(m_vk.queueWaitIdle(queue));
277
278 tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
279 referenceFrame.allocLevel(0);
280
281 const deInt32 frameWidth = referenceFrame.getWidth();
282 const deInt32 frameHeight = referenceFrame.getHeight();
283
284 tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
285
286 ReferenceImageInstancedCoordinates refInstancedCoords;
287
288 for (int y = 0; y < frameHeight; y++)
289 {
290 const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
291
292 for (int x = 0; x < frameWidth; x++)
293 {
294 const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
295
296 if ((yCoord >= refInstancedCoords.bottom &&
297 yCoord <= refInstancedCoords.top &&
298 xCoord >= refInstancedCoords.left &&
299 xCoord <= refInstancedCoords.right))
300 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
301 }
302 }
303
304 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
305 const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
306 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
307
308 qpTestResult res = QP_TEST_RESULT_PASS;
309
310 if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
311 referenceFrame.getLevel(0), renderedFrame, 0.05f,
312 tcu::COMPARE_LOG_RESULT)) {
313 res = QP_TEST_RESULT_FAIL;
314 }
315
316 return tcu::TestStatus(res, qpGetTestResultName(res));
317
318 }
319
320 } // anonymous
321
DrawIndexedTests(tcu::TestContext & testCtx)322 DrawIndexedTests::DrawIndexedTests (tcu::TestContext &testCtx)
323 : TestCaseGroup (testCtx, "indexed_draw", "drawing indexed geometry")
324 {
325 /* Left blank on purpose */
326 }
327
~DrawIndexedTests(void)328 DrawIndexedTests::~DrawIndexedTests (void) {}
329
init(void)330 void DrawIndexedTests::init (void)
331 {
332 {
333 DrawIndexed::TestSpec testSpec;
334 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetch.vert";
335 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
336
337 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
338 addChild(new InstanceFactory<DrawIndexed>(m_testCtx, "draw_indexed_triangle_list", "Draws indexed triangle list", testSpec));
339 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
340 addChild(new InstanceFactory<DrawIndexed>(m_testCtx, "draw_indexed_triangle_strip", "Draws indexed triangle strip", testSpec));
341 }
342 {
343 DrawInstancedIndexed::TestSpec testSpec;
344 testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetchInstancedFirstInstance.vert";
345 testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
346
347 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
348 addChild(new InstanceFactory<DrawInstancedIndexed>(m_testCtx, "draw_instanced_indexed_triangle_list", "Draws indexed triangle list", testSpec));
349 testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
350 addChild(new InstanceFactory<DrawInstancedIndexed>(m_testCtx, "draw_instanced_indexed_triangle_strip", "Draws indexed triangle strip", testSpec));
351 }
352 }
353
354 } // DrawTests
355 } // vkt
356