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 #include "vktFragmentOperationsMakeUtil.hpp"
30
31 #include "vkDefs.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkImageUtil.hpp"
37 #include "vkCmdUtil.hpp"
38 #include "vkObjUtil.hpp"
39
40 #include "tcuTestLog.hpp"
41 #include "tcuVector.hpp"
42 #include "tcuImageCompare.hpp"
43
44 #include "deUniquePtr.hpp"
45 #include "deRandom.hpp"
46
47 namespace vkt
48 {
49 namespace FragmentOperations
50 {
51 using namespace vk;
52 using de::UniquePtr;
53 using de::MovePtr;
54 using tcu::Vec4;
55 using tcu::Vec2;
56 using tcu::IVec2;
57 using tcu::IVec4;
58
59 namespace
60 {
61
62 //! What primitives will be drawn by the test case.
63 enum TestPrimitive
64 {
65 TEST_PRIMITIVE_POINTS, //!< Many points.
66 TEST_PRIMITIVE_LINES, //!< Many short lines.
67 TEST_PRIMITIVE_TRIANGLES, //!< Many small triangles.
68 TEST_PRIMITIVE_BIG_LINE, //!< One line crossing the whole render area.
69 TEST_PRIMITIVE_BIG_TRIANGLE, //!< One triangle covering the whole render area.
70 };
71
72 struct VertexData
73 {
74 Vec4 position;
75 Vec4 color;
76 };
77
78 //! Parameters used by the test case.
79 struct CaseDef
80 {
81 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].
82 Vec4 scissorArea; //!< scissored area (ox, oy, w, h)
83 TestPrimitive primitive;
84 };
85
86 template<typename T>
sizeInBytes(const std::vector<T> & vec)87 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
88 {
89 return vec.size() * sizeof(vec[0]);
90 }
91
makeImageCreateInfo(const VkFormat format,const IVec2 & size,VkImageUsageFlags usage)92 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const IVec2& size, VkImageUsageFlags usage)
93 {
94 const VkImageCreateInfo imageParams =
95 {
96 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
97 DE_NULL, // const void* pNext;
98 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
99 VK_IMAGE_TYPE_2D, // VkImageType imageType;
100 format, // VkFormat format;
101 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
102 1u, // deUint32 mipLevels;
103 1u, // deUint32 arrayLayers;
104 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
105 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
106 usage, // VkImageUsageFlags usage;
107 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
108 0u, // deUint32 queueFamilyIndexCount;
109 DE_NULL, // const deUint32* pQueueFamilyIndices;
110 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
111 };
112 return imageParams;
113 }
114
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)115 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
116 const VkDevice device,
117 const VkPipelineLayout pipelineLayout,
118 const VkRenderPass renderPass,
119 const VkShaderModule vertexModule,
120 const VkShaderModule fragmentModule,
121 const IVec2 renderSize,
122 const IVec4 scissorArea, //!< (ox, oy, w, h)
123 const VkPrimitiveTopology topology)
124 {
125 const VkVertexInputBindingDescription vertexInputBindingDescription =
126 {
127 0u, // uint32_t binding;
128 sizeof(VertexData), // uint32_t stride;
129 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
130 };
131
132 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
133 {
134 {
135 0u, // uint32_t location;
136 0u, // uint32_t binding;
137 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
138 0u, // uint32_t offset;
139 },
140 {
141 1u, // uint32_t location;
142 0u, // uint32_t binding;
143 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
144 sizeof(Vec4), // uint32_t offset;
145 },
146 };
147
148 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
149 {
150 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
151 DE_NULL, // const void* pNext;
152 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
153 1u, // uint32_t vertexBindingDescriptionCount;
154 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
155 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
156 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
157 };
158
159 const VkRect2D scissor =
160 {
161 makeOffset2D(scissorArea.x(), scissorArea.y()),
162 makeExtent2D(scissorArea.z(), scissorArea.w())
163 };
164
165 const std::vector<VkViewport> viewports (1, makeViewport(renderSize));
166 const std::vector<VkRect2D> scissors (1, scissor);
167
168 return vk::makeGraphicsPipeline(vk, // const DeviceInterface& vk
169 device, // const VkDevice device
170 pipelineLayout, // const VkPipelineLayout pipelineLayout
171 vertexModule, // const VkShaderModule vertexShaderModule
172 DE_NULL, // const VkShaderModule tessellationControlModule
173 DE_NULL, // const VkShaderModule tessellationEvalModule
174 DE_NULL, // const VkShaderModule geometryShaderModule
175 fragmentModule, // const VkShaderModule fragmentShaderModule
176 renderPass, // const VkRenderPass renderPass
177 viewports, // const std::vector<VkViewport>& viewports
178 scissors, // const std::vector<VkRect2D>& scissors
179 topology, // const VkPrimitiveTopology topology
180 0u, // const deUint32 subpass
181 0u, // const deUint32 patchControlPoints
182 &vertexInputStateInfo); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
183 }
184
makeVertex(const float x,const float y,const Vec4 & color)185 inline VertexData makeVertex (const float x, const float y, const Vec4& color)
186 {
187 const VertexData data = { Vec4(x, y, 0.0f, 1.0f), color };
188 return data;
189 }
190
genVertices(const TestPrimitive primitive,const Vec4 & renderArea,const Vec4 & primitiveColor)191 std::vector<VertexData> genVertices (const TestPrimitive primitive, const Vec4& renderArea, const Vec4& primitiveColor)
192 {
193 std::vector<VertexData> vertices;
194 de::Random rng (1234);
195
196 const float x0 = 2.0f * renderArea.x() - 1.0f;
197 const float y0 = 2.0f * renderArea.y() - 1.0f;
198 const float rx = 2.0f * renderArea.z();
199 const float ry = 2.0f * renderArea.w();
200 const float size = 0.2f;
201
202 switch (primitive)
203 {
204 case TEST_PRIMITIVE_POINTS:
205 for (int i = 0; i < 50; ++i)
206 {
207 const float x = x0 + rng.getFloat(0.0f, rx);
208 const float y = y0 + rng.getFloat(0.0f, ry);
209 vertices.push_back(makeVertex(x, y, primitiveColor));
210 }
211 break;
212
213 case TEST_PRIMITIVE_LINES:
214 for (int i = 0; i < 30; ++i)
215 {
216 const float x = x0 + rng.getFloat(0.0f, rx - size);
217 const float y = y0 + rng.getFloat(0.0f, ry - size);
218 vertices.push_back(makeVertex(x, y, primitiveColor));
219 vertices.push_back(makeVertex(x + size, y + size, primitiveColor));
220 }
221 break;
222
223 case TEST_PRIMITIVE_TRIANGLES:
224 for (int i = 0; i < 20; ++i)
225 {
226 const float x = x0 + rng.getFloat(0.0f, rx - size);
227 const float y = y0 + rng.getFloat(0.0f, ry - size);
228 vertices.push_back(makeVertex(x, y, primitiveColor));
229 vertices.push_back(makeVertex(x + size/2.0f, y + size, primitiveColor));
230 vertices.push_back(makeVertex(x + size, y, primitiveColor));
231 }
232 break;
233
234 case TEST_PRIMITIVE_BIG_LINE:
235 vertices.push_back(makeVertex(x0, y0, primitiveColor));
236 vertices.push_back(makeVertex(x0 + rx, y0 + ry, primitiveColor));
237 break;
238
239 case TEST_PRIMITIVE_BIG_TRIANGLE:
240 vertices.push_back(makeVertex(x0, y0, primitiveColor));
241 vertices.push_back(makeVertex(x0 + rx/2.0f, y0 + ry, primitiveColor));
242 vertices.push_back(makeVertex(x0 + rx, y0, primitiveColor));
243 break;
244 }
245
246 return vertices;
247 }
248
getTopology(const TestPrimitive primitive)249 VkPrimitiveTopology getTopology (const TestPrimitive primitive)
250 {
251 switch (primitive)
252 {
253 case TEST_PRIMITIVE_POINTS: return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
254
255 case TEST_PRIMITIVE_LINES:
256 case TEST_PRIMITIVE_BIG_LINE: return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
257
258 case TEST_PRIMITIVE_TRIANGLES:
259 case TEST_PRIMITIVE_BIG_TRIANGLE: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
260
261 default:
262 DE_ASSERT(0);
263 return VK_PRIMITIVE_TOPOLOGY_LAST;
264 }
265 }
266
267 //! Transform from normalized coords to framebuffer space.
getAreaRect(const Vec4 & area,const int width,const int height)268 inline IVec4 getAreaRect (const Vec4& area, const int width, const int height)
269 {
270 return IVec4(static_cast<deInt32>(static_cast<float>(width) * area.x()),
271 static_cast<deInt32>(static_cast<float>(height) * area.y()),
272 static_cast<deInt32>(static_cast<float>(width) * area.z()),
273 static_cast<deInt32>(static_cast<float>(height) * area.w()));
274 }
275
applyScissor(tcu::PixelBufferAccess imageAccess,const Vec4 & floatScissorArea,const Vec4 & clearColor)276 void applyScissor (tcu::PixelBufferAccess imageAccess, const Vec4& floatScissorArea, const Vec4& clearColor)
277 {
278 const IVec4 scissorRect (getAreaRect(floatScissorArea, imageAccess.getWidth(), imageAccess.getHeight()));
279 const int sx0 = scissorRect.x();
280 const int sx1 = scissorRect.x() + scissorRect.z();
281 const int sy0 = scissorRect.y();
282 const int sy1 = scissorRect.y() + scissorRect.w();
283
284 for (int y = 0; y < imageAccess.getHeight(); ++y)
285 for (int x = 0; x < imageAccess.getWidth(); ++x)
286 {
287 // Fragments outside fail the scissor test.
288 if (x < sx0 || x >= sx1 || y < sy0 || y >= sy1)
289 imageAccess.setPixel(clearColor, x, y);
290 }
291 }
292
initPrograms(SourceCollections & programCollection,const CaseDef caseDef)293 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
294 {
295 DE_UNREF(caseDef);
296
297 // Vertex shader
298 {
299 const bool usePointSize = (caseDef.primitive == TEST_PRIMITIVE_POINTS);
300
301 std::ostringstream src;
302 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
303 << "\n"
304 << "layout(location = 0) in vec4 in_position;\n"
305 << "layout(location = 1) in vec4 in_color;\n"
306 << "layout(location = 0) out vec4 o_color;\n"
307 << "\n"
308 << "out gl_PerVertex {\n"
309 << " vec4 gl_Position;\n"
310 << (usePointSize ? " float gl_PointSize;\n" : "")
311 << "};\n"
312 << "\n"
313 << "void main(void)\n"
314 << "{\n"
315 << " gl_Position = in_position;\n"
316 << (usePointSize ? " gl_PointSize = 1.0;\n" : "")
317 << " o_color = in_color;\n"
318 << "}\n";
319
320 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
321 }
322
323 // Fragment shader
324 {
325 std::ostringstream src;
326 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
327 << "\n"
328 << "layout(location = 0) in vec4 in_color;\n"
329 << "layout(location = 0) out vec4 o_color;\n"
330 << "\n"
331 << "void main(void)\n"
332 << "{\n"
333 << " o_color = in_color;\n"
334 << "}\n";
335
336 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
337 }
338 }
339
340 class ScissorRenderer
341 {
342 public:
ScissorRenderer(Context & context,const CaseDef caseDef,const IVec2 & renderSize,const VkFormat colorFormat,const Vec4 & primitiveColor,const Vec4 & clearColor)343 ScissorRenderer (Context& context, const CaseDef caseDef, const IVec2& renderSize, const VkFormat colorFormat, const Vec4& primitiveColor, const Vec4& clearColor)
344 : m_renderSize (renderSize)
345 , m_colorFormat (colorFormat)
346 , m_colorSubresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
347 , m_primitiveColor (primitiveColor)
348 , m_clearColor (clearColor)
349 , m_vertices (genVertices(caseDef.primitive, caseDef.renderArea, m_primitiveColor))
350 , m_vertexBufferSize (sizeInBytes(m_vertices))
351 , m_topology (getTopology(caseDef.primitive))
352 {
353 const DeviceInterface& vk = context.getDeviceInterface();
354 const VkDevice device = context.getDevice();
355 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
356 Allocator& allocator = context.getDefaultAllocator();
357
358 m_colorImage = makeImage(vk, device, makeImageCreateInfo(m_colorFormat, m_renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
359 m_colorImageAlloc = bindImage(vk, device, allocator, *m_colorImage, MemoryRequirement::Any);
360 m_colorAttachment = makeImageView(vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange);
361
362 m_vertexBuffer = makeBuffer(vk, device, m_vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
363 m_vertexBufferAlloc = bindBuffer(vk, device, allocator, *m_vertexBuffer, MemoryRequirement::HostVisible);
364
365 {
366 deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], static_cast<std::size_t>(m_vertexBufferSize));
367 flushAlloc(vk, device, *m_vertexBufferAlloc);
368 }
369
370 m_vertexModule = createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u);
371 m_fragmentModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u);
372 m_renderPass = makeRenderPass (vk, device, m_colorFormat);
373 m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, m_colorAttachment.get(),
374 static_cast<deUint32>(m_renderSize.x()), static_cast<deUint32>(m_renderSize.y()));
375 m_pipelineLayout = makePipelineLayout (vk, device);
376 m_cmdPool = createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
377 m_cmdBuffer = allocateCommandBuffer (vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
378
379 }
380
draw(Context & context,const Vec4 & scissorAreaFloat,const VkBuffer colorBuffer) const381 void draw (Context& context, const Vec4& scissorAreaFloat, const VkBuffer colorBuffer) const
382 {
383 const DeviceInterface& vk = context.getDeviceInterface();
384 const VkDevice device = context.getDevice();
385 const VkQueue queue = context.getUniversalQueue();
386
387 // New pipeline, because we're modifying scissor (we don't use dynamic state).
388 const Unique<VkPipeline> pipeline (makeGraphicsPipeline(vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_fragmentModule,
389 m_renderSize, getAreaRect(scissorAreaFloat, m_renderSize.x(), m_renderSize.y()), m_topology));
390
391 beginCommandBuffer(vk, *m_cmdBuffer);
392
393 beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), m_clearColor);
394
395 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
396 {
397 const VkDeviceSize vertexBufferOffset = 0ull;
398 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &vertexBufferOffset);
399 }
400
401 vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_vertices.size()), 1u, 0u, 0u);
402 endRenderPass(vk, *m_cmdBuffer);
403
404 copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, colorBuffer, m_renderSize);
405
406 endCommandBuffer(vk, *m_cmdBuffer);
407 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
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