1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2014 The Android Open Source Project
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 Scissor tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktFragmentOperationsScissorTests.hpp"
26 #include "vktFragmentOperationsScissorMultiViewportTests.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktTestGroupUtil.hpp"
29
30 #include "vkDefs.hpp"
31 #include "vkRefUtil.hpp"
32 #include "vkTypeUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkImageUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkObjUtil.hpp"
38
39 #include "tcuTestLog.hpp"
40 #include "tcuVector.hpp"
41 #include "tcuImageCompare.hpp"
42
43 #include "deUniquePtr.hpp"
44 #include "deRandom.hpp"
45
46 namespace vkt
47 {
48 namespace FragmentOperations
49 {
50 using namespace vk;
51 using de::UniquePtr;
52 using de::MovePtr;
53 using tcu::Vec4;
54 using tcu::Vec2;
55 using tcu::IVec2;
56 using tcu::IVec4;
57
58 namespace
59 {
60
61 //! What primitives will be drawn by the test case.
62 enum TestPrimitive
63 {
64 TEST_PRIMITIVE_POINTS, //!< Many points.
65 TEST_PRIMITIVE_LINES, //!< Many short lines.
66 TEST_PRIMITIVE_TRIANGLES, //!< Many small triangles.
67 TEST_PRIMITIVE_BIG_LINE, //!< One line crossing the whole render area.
68 TEST_PRIMITIVE_BIG_TRIANGLE, //!< One triangle covering the whole render area.
69 };
70
71 struct VertexData
72 {
73 Vec4 position;
74 Vec4 color;
75 };
76
77 //! Parameters used by the test case.
78 struct CaseDef
79 {
80 Vec4 renderArea; //!< (ox, oy, w, h), where origin (0,0) is the top-left corner of the viewport. Width and height are in range [0, 1].
81 Vec4 scissorArea; //!< scissored area (ox, oy, w, h)
82 TestPrimitive primitive;
83 };
84
85 template<typename T>
sizeInBytes(const std::vector<T> & vec)86 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
87 {
88 return vec.size() * sizeof(vec[0]);
89 }
90
makeImageCreateInfo(const VkFormat format,const IVec2 & size,VkImageUsageFlags usage)91 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const IVec2& size, VkImageUsageFlags usage)
92 {
93 const VkImageCreateInfo imageParams =
94 {
95 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
96 DE_NULL, // const void* pNext;
97 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
98 VK_IMAGE_TYPE_2D, // VkImageType imageType;
99 format, // VkFormat format;
100 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
101 1u, // deUint32 mipLevels;
102 1u, // deUint32 arrayLayers;
103 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
104 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
105 usage, // VkImageUsageFlags usage;
106 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
107 0u, // deUint32 queueFamilyIndexCount;
108 DE_NULL, // const deUint32* pQueueFamilyIndices;
109 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
110 };
111 return imageParams;
112 }
113
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const IVec2 renderSize,const IVec4 scissorArea,const VkPrimitiveTopology topology)114 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
115 const VkDevice device,
116 const VkPipelineLayout pipelineLayout,
117 const VkRenderPass renderPass,
118 const VkShaderModule vertexModule,
119 const VkShaderModule fragmentModule,
120 const IVec2 renderSize,
121 const IVec4 scissorArea, //!< (ox, oy, w, h)
122 const VkPrimitiveTopology topology)
123 {
124 const VkVertexInputBindingDescription vertexInputBindingDescription =
125 {
126 0u, // uint32_t binding;
127 sizeof(VertexData), // uint32_t stride;
128 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
129 };
130
131 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
132 {
133 {
134 0u, // uint32_t location;
135 0u, // uint32_t binding;
136 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
137 0u, // uint32_t offset;
138 },
139 {
140 1u, // uint32_t location;
141 0u, // uint32_t binding;
142 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
143 sizeof(Vec4), // uint32_t offset;
144 },
145 };
146
147 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
148 {
149 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
150 DE_NULL, // const void* pNext;
151 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
152 1u, // uint32_t vertexBindingDescriptionCount;
153 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
154 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
155 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
156 };
157
158 const VkRect2D scissor =
159 {
160 makeOffset2D(scissorArea.x(), scissorArea.y()),
161 makeExtent2D(scissorArea.z(), scissorArea.w())
162 };
163
164 const std::vector<VkViewport> viewports (1, makeViewport(renderSize));
165 const std::vector<VkRect2D> scissors (1, scissor);
166
167 return vk::makeGraphicsPipeline(vk, // const DeviceInterface& vk
168 device, // const VkDevice device
169 pipelineLayout, // const VkPipelineLayout pipelineLayout
170 vertexModule, // const VkShaderModule vertexShaderModule
171 DE_NULL, // const VkShaderModule tessellationControlModule
172 DE_NULL, // const VkShaderModule tessellationEvalModule
173 DE_NULL, // const VkShaderModule geometryShaderModule
174 fragmentModule, // const VkShaderModule fragmentShaderModule
175 renderPass, // const VkRenderPass renderPass
176 viewports, // const std::vector<VkViewport>& viewports
177 scissors, // const std::vector<VkRect2D>& scissors
178 topology, // const VkPrimitiveTopology topology
179 0u, // const deUint32 subpass
180 0u, // const deUint32 patchControlPoints
181 &vertexInputStateInfo); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
182 }
183
makeVertex(const float x,const float y,const Vec4 & color)184 inline VertexData makeVertex (const float x, const float y, const Vec4& color)
185 {
186 const VertexData data = { Vec4(x, y, 0.0f, 1.0f), color };
187 return data;
188 }
189
genVertices(const TestPrimitive primitive,const Vec4 & renderArea,const Vec4 & primitiveColor)190 std::vector<VertexData> genVertices (const TestPrimitive primitive, const Vec4& renderArea, const Vec4& primitiveColor)
191 {
192 std::vector<VertexData> vertices;
193 de::Random rng (1234);
194
195 const float x0 = 2.0f * renderArea.x() - 1.0f;
196 const float y0 = 2.0f * renderArea.y() - 1.0f;
197 const float rx = 2.0f * renderArea.z();
198 const float ry = 2.0f * renderArea.w();
199 const float size = 0.2f;
200
201 switch (primitive)
202 {
203 case TEST_PRIMITIVE_POINTS:
204 for (int i = 0; i < 50; ++i)
205 {
206 const float x = x0 + rng.getFloat(0.0f, rx);
207 const float y = y0 + rng.getFloat(0.0f, ry);
208 vertices.push_back(makeVertex(x, y, primitiveColor));
209 }
210 break;
211
212 case TEST_PRIMITIVE_LINES:
213 for (int i = 0; i < 30; ++i)
214 {
215 const float x = x0 + rng.getFloat(0.0f, rx - size);
216 const float y = y0 + rng.getFloat(0.0f, ry - size);
217 vertices.push_back(makeVertex(x, y, primitiveColor));
218 vertices.push_back(makeVertex(x + size, y + size, primitiveColor));
219 }
220 break;
221
222 case TEST_PRIMITIVE_TRIANGLES:
223 for (int i = 0; i < 20; ++i)
224 {
225 const float x = x0 + rng.getFloat(0.0f, rx - size);
226 const float y = y0 + rng.getFloat(0.0f, ry - size);
227 vertices.push_back(makeVertex(x, y, primitiveColor));
228 vertices.push_back(makeVertex(x + size/2.0f, y + size, primitiveColor));
229 vertices.push_back(makeVertex(x + size, y, primitiveColor));
230 }
231 break;
232
233 case TEST_PRIMITIVE_BIG_LINE:
234 vertices.push_back(makeVertex(x0, y0, primitiveColor));
235 vertices.push_back(makeVertex(x0 + rx, y0 + ry, primitiveColor));
236 break;
237
238 case TEST_PRIMITIVE_BIG_TRIANGLE:
239 vertices.push_back(makeVertex(x0, y0, primitiveColor));
240 vertices.push_back(makeVertex(x0 + rx/2.0f, y0 + ry, primitiveColor));
241 vertices.push_back(makeVertex(x0 + rx, y0, primitiveColor));
242 break;
243 }
244
245 return vertices;
246 }
247
getTopology(const TestPrimitive primitive)248 VkPrimitiveTopology getTopology (const TestPrimitive primitive)
249 {
250 switch (primitive)
251 {
252 case TEST_PRIMITIVE_POINTS: return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
253
254 case TEST_PRIMITIVE_LINES:
255 case TEST_PRIMITIVE_BIG_LINE: return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
256
257 case TEST_PRIMITIVE_TRIANGLES:
258 case TEST_PRIMITIVE_BIG_TRIANGLE: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
259
260 default:
261 DE_ASSERT(0);
262 return VK_PRIMITIVE_TOPOLOGY_LAST;
263 }
264 }
265
266 //! Transform from normalized coords to framebuffer space.
getAreaRect(const Vec4 & area,const int width,const int height)267 inline IVec4 getAreaRect (const Vec4& area, const int width, const int height)
268 {
269 return IVec4(static_cast<deInt32>(static_cast<float>(width) * area.x()),
270 static_cast<deInt32>(static_cast<float>(height) * area.y()),
271 static_cast<deInt32>(static_cast<float>(width) * area.z()),
272 static_cast<deInt32>(static_cast<float>(height) * area.w()));
273 }
274
applyScissor(tcu::PixelBufferAccess imageAccess,const Vec4 & floatScissorArea,const Vec4 & clearColor)275 void applyScissor (tcu::PixelBufferAccess imageAccess, const Vec4& floatScissorArea, const Vec4& clearColor)
276 {
277 const IVec4 scissorRect (getAreaRect(floatScissorArea, imageAccess.getWidth(), imageAccess.getHeight()));
278 const int sx0 = scissorRect.x();
279 const int sx1 = scissorRect.x() + scissorRect.z();
280 const int sy0 = scissorRect.y();
281 const int sy1 = scissorRect.y() + scissorRect.w();
282
283 for (int y = 0; y < imageAccess.getHeight(); ++y)
284 for (int x = 0; x < imageAccess.getWidth(); ++x)
285 {
286 // Fragments outside fail the scissor test.
287 if (x < sx0 || x >= sx1 || y < sy0 || y >= sy1)
288 imageAccess.setPixel(clearColor, x, y);
289 }
290 }
291
initPrograms(SourceCollections & programCollection,const CaseDef caseDef)292 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
293 {
294 DE_UNREF(caseDef);
295
296 // Vertex shader
297 {
298 const bool usePointSize = (caseDef.primitive == TEST_PRIMITIVE_POINTS);
299
300 std::ostringstream src;
301 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
302 << "\n"
303 << "layout(location = 0) in vec4 in_position;\n"
304 << "layout(location = 1) in vec4 in_color;\n"
305 << "layout(location = 0) out vec4 o_color;\n"
306 << "\n"
307 << "out gl_PerVertex {\n"
308 << " vec4 gl_Position;\n"
309 << (usePointSize ? " float gl_PointSize;\n" : "")
310 << "};\n"
311 << "\n"
312 << "void main(void)\n"
313 << "{\n"
314 << " gl_Position = in_position;\n"
315 << (usePointSize ? " gl_PointSize = 1.0;\n" : "")
316 << " o_color = in_color;\n"
317 << "}\n";
318
319 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
320 }
321
322 // Fragment shader
323 {
324 std::ostringstream src;
325 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
326 << "\n"
327 << "layout(location = 0) in vec4 in_color;\n"
328 << "layout(location = 0) out vec4 o_color;\n"
329 << "\n"
330 << "void main(void)\n"
331 << "{\n"
332 << " o_color = in_color;\n"
333 << "}\n";
334
335 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
336 }
337 }
338
339 class ScissorRenderer
340 {
341 public:
ScissorRenderer(Context & context,const CaseDef caseDef,const IVec2 & renderSize,const VkFormat colorFormat,const Vec4 & primitiveColor,const Vec4 & clearColor)342 ScissorRenderer (Context& context, const CaseDef caseDef, const IVec2& renderSize, const VkFormat colorFormat, const Vec4& primitiveColor, const Vec4& clearColor)
343 : m_renderSize (renderSize)
344 , m_colorFormat (colorFormat)
345 , m_colorSubresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
346 , m_primitiveColor (primitiveColor)
347 , m_clearColor (clearColor)
348 , m_vertices (genVertices(caseDef.primitive, caseDef.renderArea, m_primitiveColor))
349 , m_vertexBufferSize (sizeInBytes(m_vertices))
350 , m_topology (getTopology(caseDef.primitive))
351 {
352 const DeviceInterface& vk = context.getDeviceInterface();
353 const VkDevice device = context.getDevice();
354 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
355 Allocator& allocator = context.getDefaultAllocator();
356
357 m_colorImage = makeImage(vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
358 m_colorImageAlloc = bindImage(vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
359 m_colorAttachment = makeImageView(vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange);
360
361 m_vertexBuffer = makeBuffer(vk, device, m_vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
362 m_vertexBufferAlloc = bindBuffer(vk, device, allocator, *m_vertexBuffer, MemoryRequirement::HostVisible);
363
364 {
365 deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], static_cast<std::size_t>(m_vertexBufferSize));
366 flushAlloc(vk, device, *m_vertexBufferAlloc);
367 }
368
369 m_vertexModule = createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u);
370 m_fragmentModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u);
371 m_renderPass = makeRenderPass (vk, device, m_colorFormat);
372 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, m_colorAttachment.get(),
373 static_cast<deUint32>(m_renderSize.x()), static_cast<deUint32>(m_renderSize.y()));
374 m_pipelineLayout = makePipelineLayout (vk, device);
375 m_cmdPool = createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
376 m_cmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
377
378 }
379
draw(Context & context,const Vec4 & scissorAreaFloat,const VkBuffer colorBuffer) const380 void draw (Context& context, const Vec4& scissorAreaFloat, const VkBuffer colorBuffer) const
381 {
382 const DeviceInterface& vk = context.getDeviceInterface();
383 const VkDevice device = context.getDevice();
384 const VkQueue queue = context.getUniversalQueue();
385
386 // New pipeline, because we're modifying scissor (we don't use dynamic state).
387 const Unique<VkPipeline> pipeline (makeGraphicsPipeline(vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_fragmentModule,
388 m_renderSize, getAreaRect(scissorAreaFloat, m_renderSize.x(), m_renderSize.y()), m_topology));
389
390 beginCommandBuffer(vk, *m_cmdBuffer);
391
392 beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), m_clearColor);
393
394 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
395 {
396 const VkDeviceSize vertexBufferOffset = 0ull;
397 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &vertexBufferOffset);
398 }
399
400 vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_vertices.size()), 1u, 0u, 0u);
401 endRenderPass(vk, *m_cmdBuffer);
402
403 copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, colorBuffer, m_renderSize);
404
405 endCommandBuffer(vk, *m_cmdBuffer);
406 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
407 context.resetCommandPoolForVKSC(device, *m_cmdPool);
408 }
409
410 private:
411 const IVec2 m_renderSize;
412 const VkFormat m_colorFormat;
413 const VkImageSubresourceRange m_colorSubresourceRange;
414 const Vec4 m_primitiveColor;
415 const Vec4 m_clearColor;
416 const std::vector<VertexData> m_vertices;
417 const VkDeviceSize m_vertexBufferSize;
418 const VkPrimitiveTopology m_topology;
419
420 Move<VkImage> m_colorImage;
421 MovePtr<Allocation> m_colorImageAlloc;
422 Move<VkImageView> m_colorAttachment;
423 Move<VkBuffer> m_vertexBuffer;
424 MovePtr<Allocation> m_vertexBufferAlloc;
425 Move<VkShaderModule> m_vertexModule;
426 Move<VkShaderModule> m_fragmentModule;
427 Move<VkRenderPass> m_renderPass;
428 Move<VkFramebuffer> m_framebuffer;
429 Move<VkPipelineLayout> m_pipelineLayout;
430 Move<VkCommandPool> m_cmdPool;
431 Move<VkCommandBuffer> m_cmdBuffer;
432
433 // "deleted"
434 ScissorRenderer (const ScissorRenderer&);
435 ScissorRenderer& operator= (const ScissorRenderer&);
436 };
437
test(Context & context,const CaseDef caseDef)438 tcu::TestStatus test (Context& context, const CaseDef caseDef)
439 {
440 const DeviceInterface& vk = context.getDeviceInterface();
441 const VkDevice device = context.getDevice();
442 Allocator& allocator = context.getDefaultAllocator();
443
444 const IVec2 renderSize (128, 128);
445 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
446 const Vec4 scissorFullArea (0.0f, 0.0f, 1.0f, 1.0f);
447 const Vec4 primitiveColor (1.0f, 1.0f, 1.0f, 1.0f);
448 const Vec4 clearColor (0.5f, 0.5f, 1.0f, 1.0f);
449
450 const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
451 const Unique<VkBuffer> colorBufferFull (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
452 const UniquePtr<Allocation> colorBufferFullAlloc (bindBuffer(vk, device, allocator, *colorBufferFull, MemoryRequirement::HostVisible));
453
454 const Unique<VkBuffer> colorBufferScissored (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
455 const UniquePtr<Allocation> colorBufferScissoredAlloc (bindBuffer(vk, device, allocator, *colorBufferScissored, MemoryRequirement::HostVisible));
456
457 zeroBuffer(vk, device, *colorBufferFullAlloc, colorBufferSize);
458 zeroBuffer(vk, device, *colorBufferScissoredAlloc, colorBufferSize);
459
460 // Draw
461 {
462 const ScissorRenderer renderer (context, caseDef, renderSize, colorFormat, primitiveColor, clearColor);
463
464 renderer.draw(context, scissorFullArea, *colorBufferFull);
465 renderer.draw(context, caseDef.scissorArea, *colorBufferScissored);
466 }
467
468 // Log image
469 {
470 invalidateAlloc(vk, device, *colorBufferFullAlloc);
471 invalidateAlloc(vk, device, *colorBufferScissoredAlloc);
472
473 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, colorBufferScissoredAlloc->getHostPtr());
474 tcu::PixelBufferAccess referenceImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, colorBufferFullAlloc->getHostPtr());
475
476 // Apply scissor to the full image, so we can compare it with the result image.
477 applyScissor (referenceImage, caseDef.scissorArea, clearColor);
478
479 // Images should now match.
480 if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage, resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
481 return tcu::TestStatus::fail("Rendered image is not correct");
482 }
483
484 return tcu::TestStatus::pass("OK");
485 }
486
487 //! \note The ES 2.0 scissoring tests included color/depth/stencil clear cases, but these operations are not affected by scissor test in Vulkan.
488 //! Scissor is part of the pipeline state and pipeline only affects the drawing commands.
createTestsInGroup(tcu::TestCaseGroup * scissorGroup)489 void createTestsInGroup (tcu::TestCaseGroup* scissorGroup)
490 {
491 tcu::TestContext& testCtx = scissorGroup->getTestContext();
492
493 struct TestSpec
494 {
495 const char* name;
496 const char* description;
497 CaseDef caseDef;
498 };
499
500 const Vec4 areaFull (0.0f, 0.0f, 1.0f, 1.0f);
501 const Vec4 areaCropped (0.2f, 0.2f, 0.6f, 0.6f);
502 const Vec4 areaCroppedMore (0.4f, 0.4f, 0.2f, 0.2f);
503 const Vec4 areaLeftHalf (0.0f, 0.0f, 0.5f, 1.0f);
504 const Vec4 areaRightHalf (0.5f, 0.0f, 0.5f, 1.0f);
505
506 // Points
507 {
508 MovePtr<tcu::TestCaseGroup> primitiveGroup (new tcu::TestCaseGroup(testCtx, "points", ""));
509
510 const TestSpec cases[] =
511 {
512 { "inside", "Points fully inside the scissor area", { areaFull, areaFull, TEST_PRIMITIVE_POINTS } },
513 { "partially_inside", "Points partially inside the scissor area", { areaFull, areaCropped, TEST_PRIMITIVE_POINTS } },
514 { "outside", "Points fully outside the scissor area", { areaLeftHalf, areaRightHalf, TEST_PRIMITIVE_POINTS } },
515 };
516
517 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
518 addFunctionCaseWithPrograms(primitiveGroup.get(), cases[i].name, cases[i].description, initPrograms, test, cases[i].caseDef);
519
520 scissorGroup->addChild(primitiveGroup.release());
521 }
522
523 // Lines
524 {
525 MovePtr<tcu::TestCaseGroup> primitiveGroup (new tcu::TestCaseGroup(testCtx, "lines", ""));
526
527 const TestSpec cases[] =
528 {
529 { "inside", "Lines fully inside the scissor area", { areaFull, areaFull, TEST_PRIMITIVE_LINES } },
530 { "partially_inside", "Lines partially inside the scissor area", { areaFull, areaCropped, TEST_PRIMITIVE_LINES } },
531 { "outside", "Lines fully outside the scissor area", { areaLeftHalf, areaRightHalf, TEST_PRIMITIVE_LINES } },
532 { "crossing", "A line crossing the scissor area", { areaFull, areaCroppedMore, TEST_PRIMITIVE_BIG_LINE } },
533 };
534
535 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
536 addFunctionCaseWithPrograms(primitiveGroup.get(), cases[i].name, cases[i].description, initPrograms, test, cases[i].caseDef);
537
538 scissorGroup->addChild(primitiveGroup.release());
539 }
540
541 // Triangles
542 {
543 MovePtr<tcu::TestCaseGroup> primitiveGroup (new tcu::TestCaseGroup(testCtx, "triangles", ""));
544
545 const TestSpec cases[] =
546 {
547 { "inside", "Triangles fully inside the scissor area", { areaFull, areaFull, TEST_PRIMITIVE_TRIANGLES } },
548 { "partially_inside", "Triangles partially inside the scissor area", { areaFull, areaCropped, TEST_PRIMITIVE_TRIANGLES } },
549 { "outside", "Triangles fully outside the scissor area", { areaLeftHalf, areaRightHalf, TEST_PRIMITIVE_TRIANGLES } },
550 { "crossing", "A triangle crossing the scissor area", { areaFull, areaCroppedMore, TEST_PRIMITIVE_BIG_TRIANGLE } },
551 };
552
553 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
554 addFunctionCaseWithPrograms(primitiveGroup.get(), cases[i].name, cases[i].description, initPrograms, test, cases[i].caseDef);
555
556 scissorGroup->addChild(primitiveGroup.release());
557 }
558
559 // Mulit-viewport scissor
560 {
561 scissorGroup->addChild(createScissorMultiViewportTests(testCtx));
562 }
563 }
564
565 } // anonymous
566
createScissorTests(tcu::TestContext & testCtx)567 tcu::TestCaseGroup* createScissorTests (tcu::TestContext& testCtx)
568 {
569 return createTestGroup(testCtx, "scissor", "Scissor tests", createTestsInGroup);
570 }
571
572 } // FragmentOperations
573 } // vkt
574