1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2019 Google Inc.
6 * Copyright (c) 2019 The Khronos Group Inc.
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 Scissoring tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktDrawScissorTests.hpp"
26
27 #include "vktDrawBaseClass.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vktTestGroupUtil.hpp"
32
33 #include "tcuTestCase.hpp"
34 #include "tcuTextureUtil.hpp"
35 #include "tcuImageCompare.hpp"
36
37 #include <string>
38
39 namespace vkt
40 {
41 namespace Draw
42 {
43 namespace
44 {
45 using namespace vk;
46 using namespace std;
47 using namespace tcu;
48
49 enum
50 {
51 WIDTH = 256,
52 HEIGHT = 256
53 };
54
55 struct ColorQuad
56 {
ColorQuadvkt::Draw::__anon0b2debf80111::ColorQuad57 ColorQuad (deUint32 x, deUint32 y, deUint32 width, deUint32 height, Vec4 color)
58 : m_x(x), m_y(y), m_width(width), m_height(height), m_color(color)
59 {
60 }
61
62 deUint32 m_x;
63 deUint32 m_y;
64 deUint32 m_width;
65 deUint32 m_height;
66 Vec4 m_color;
67 };
68
scissorQuad(ColorQuad quad,VkRect2D scissor,VkExtent2D framebufferSize)69 ColorQuad scissorQuad (ColorQuad quad, VkRect2D scissor, VkExtent2D framebufferSize)
70 {
71 int left = quad.m_x;
72 int right = quad.m_x + quad.m_width;
73 int top = quad.m_y;
74 int bottom = quad.m_y + quad.m_height;
75
76 left = de::max(left, scissor.offset.x);
77 left = de::max(left, 0);
78 right = de::min(right, scissor.offset.x + (int)scissor.extent.width);
79 right = de::min(right, (int)framebufferSize.width);
80 top = de::max(top, scissor.offset.y);
81 top = de::max(top, 0);
82 bottom = de::min(bottom, scissor.offset.y + (int)scissor.extent.height);
83 bottom = de::min(bottom, (int)framebufferSize.height);
84
85 return ColorQuad(left, top, de::max(right - left, 0), de::max(bottom - top, 0), quad.m_color);
86 }
87
88 class TestCommand
89 {
90 public:
TestCommand(void)91 TestCommand (void) {}
~TestCommand(void)92 virtual ~TestCommand (void) {}
93
getVertices(deUint32 offset)94 virtual vector<PositionColorVertex> getVertices (deUint32 offset) { DE_UNREF(offset); return vector<PositionColorVertex>(); }
95 virtual void addCommands (const DeviceInterface& vk, VkCommandBuffer cmdBuffer) = 0;
getMaxScissor(void)96 virtual deUint32 getMaxScissor (void) { return 0; }
getQuad(void)97 virtual vector<ColorQuad> getQuad (void) { return vector<ColorQuad>(); }
updateScissors(vector<VkRect2D> scissors)98 virtual vector<VkRect2D> updateScissors (vector<VkRect2D> scissors) { return scissors; }
isScissored(void)99 virtual bool isScissored (void) { return false; }
100
101
102 private:
103 };
104
105 typedef de::SharedPtr<TestCommand> TestCommandSp;
106
107 class QuadDrawTestCommand : public TestCommand
108 {
109 public:
110 QuadDrawTestCommand (deUint32 x, deUint32 y, deUint32 width, deUint32 height, Vec4 color);
~QuadDrawTestCommand(void)111 virtual ~QuadDrawTestCommand (void) {}
112
113 virtual vector<PositionColorVertex> getVertices (deUint32 offset);
114 virtual void addCommands (const DeviceInterface& vk, VkCommandBuffer cmdBuffer);
getQuad(void)115 virtual vector<ColorQuad> getQuad (void) { return vector<ColorQuad>(1, m_quad); }
isScissored(void)116 virtual bool isScissored (void) { return true; }
117 private:
118 deUint32 m_offset;
119 ColorQuad m_quad;
120 };
121
QuadDrawTestCommand(deUint32 x,deUint32 y,deUint32 width,deUint32 height,Vec4 color)122 QuadDrawTestCommand::QuadDrawTestCommand (deUint32 x, deUint32 y, deUint32 width, deUint32 height, Vec4 color)
123 : m_offset(0)
124 , m_quad(x, y, width, height, color)
125 {
126 }
127
getVertices(deUint32 offset)128 vector<PositionColorVertex> QuadDrawTestCommand::getVertices (deUint32 offset)
129 {
130 vector<PositionColorVertex> vertices;
131 float scaleWidth = 2.0f / (float)WIDTH;
132 float scaleHeight = 2.0f / (float)HEIGHT;
133 Vec4 topLeft (-1.0f + scaleWidth * (float)m_quad.m_x, -1.0f + scaleHeight * (float)m_quad.m_y, 0.0f, 1.0f);
134 Vec4 topRight (-1.0f + scaleWidth * (float)(m_quad.m_x + m_quad.m_width), -1.0f + scaleHeight * (float)m_quad.m_y, 0.0f, 1.0f);
135 Vec4 bottomLeft (-1.0f + scaleWidth * (float)m_quad.m_x, -1.0f + scaleHeight * (float)(m_quad.m_y + m_quad.m_height), 0.0f, 1.0f);
136 Vec4 bottomRight (-1.0f + scaleWidth * (float)(m_quad.m_x + m_quad.m_width), -1.0f + scaleHeight * (float)(m_quad.m_y + m_quad.m_height), 0.0f, 1.0f);
137
138 m_offset = offset;
139
140 vertices.push_back(PositionColorVertex(topLeft, m_quad.m_color));
141 vertices.push_back(PositionColorVertex(bottomRight, m_quad.m_color));
142 vertices.push_back(PositionColorVertex(bottomLeft, m_quad.m_color));
143 vertices.push_back(PositionColorVertex(topLeft, m_quad.m_color));
144 vertices.push_back(PositionColorVertex(topRight, m_quad.m_color));
145 vertices.push_back(PositionColorVertex(bottomRight, m_quad.m_color));
146
147 return vertices;
148 }
149
addCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)150 void QuadDrawTestCommand::addCommands (const DeviceInterface& vk, VkCommandBuffer cmdBuffer)
151 {
152 vk.cmdDraw(cmdBuffer, 6u, 1u, m_offset, 0u);
153 }
154
155 class RectClearTestCommand : public TestCommand
156 {
157 public:
158 RectClearTestCommand (deUint32 x, deUint32 y, deUint32 width, deUint32 height, Vec4 color);
~RectClearTestCommand(void)159 virtual ~RectClearTestCommand (void) {}
160
161 virtual void addCommands (const DeviceInterface& vk, VkCommandBuffer cmdBuffer);
getQuad(void)162 virtual vector<ColorQuad> getQuad (void) { return vector<ColorQuad>(1, m_quad); }
163 private:
164 ColorQuad m_quad;
165 };
166
RectClearTestCommand(deUint32 x,deUint32 y,deUint32 width,deUint32 height,Vec4 color)167 RectClearTestCommand::RectClearTestCommand (deUint32 x, deUint32 y, deUint32 width, deUint32 height, Vec4 color)
168 : m_quad(x, y, width, height, color)
169 {
170 }
171
addCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)172 void RectClearTestCommand::addCommands (const DeviceInterface& vk, VkCommandBuffer cmdBuffer)
173 {
174 const VkClearAttachment attachment =
175 {
176 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
177 0u, // deUint32 colorAttachment
178 makeClearValueColor(m_quad.m_color) // VkClearValue clearValue
179 };
180
181 const VkClearRect rect =
182 {
183 makeRect2D(m_quad.m_x, m_quad.m_y, m_quad.m_width, m_quad.m_height), // VkRect2D rect
184 0u, // deUint32 baseArrayLayer
185 1u // deUint32 layerCount
186 };
187
188 vk.cmdClearAttachments(cmdBuffer, 1u, &attachment, 1u, &rect);
189 }
190
191 class DynamicScissorTestCommand : public TestCommand
192 {
193 public:
194 DynamicScissorTestCommand (deUint32 firstScissor, vector<VkRect2D> scissors);
~DynamicScissorTestCommand(void)195 virtual ~DynamicScissorTestCommand (void) {}
196
197 virtual void addCommands (const DeviceInterface& vk, VkCommandBuffer cmdBuffer);
getMaxScissor(void)198 virtual deUint32 getMaxScissor (void) { return m_firstScissor + (deUint32)m_scissors.size(); }
199 virtual vector<VkRect2D> updateScissors (vector<VkRect2D> scissors);
200 private:
201 deUint32 m_firstScissor;
202 vector<VkRect2D> m_scissors;
203 };
204
DynamicScissorTestCommand(deUint32 firstScissor,vector<VkRect2D> scissors)205 DynamicScissorTestCommand::DynamicScissorTestCommand (deUint32 firstScissor, vector<VkRect2D> scissors)
206 : m_firstScissor(firstScissor)
207 , m_scissors(scissors)
208 {
209 }
210
addCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)211 void DynamicScissorTestCommand::addCommands (const DeviceInterface& vk, VkCommandBuffer cmdBuffer)
212 {
213 vk.cmdSetScissor(cmdBuffer, m_firstScissor, (deUint32)m_scissors.size(), m_scissors.data());
214 }
215
updateScissors(vector<VkRect2D> scissors)216 vector<VkRect2D> DynamicScissorTestCommand::updateScissors (vector<VkRect2D> scissors)
217 {
218 for (size_t scissorIdx = 0; scissorIdx < m_scissors.size(); scissorIdx++)
219 {
220 while (scissors.size() <= m_firstScissor + scissorIdx)
221 scissors.push_back(makeRect2D(0, 0)); // Add empty scissor
222
223 scissors[m_firstScissor + scissorIdx] = m_scissors[scissorIdx];
224 }
225
226 return scissors;
227 }
228
229 struct TestParams
230 {
TestParamsvkt::Draw::__anon0b2debf80111::TestParams231 TestParams(const SharedGroupParams gp)
232 : groupParams (gp)
233 , framebufferSize ({WIDTH,HEIGHT})
234 {}
235
236 bool dynamicScissor;
237 vector<VkRect2D> staticScissors;
238 vector<TestCommandSp> commands;
239 bool usesMultipleScissors;
240 const SharedGroupParams groupParams;
241 VkExtent2D framebufferSize;
242 };
243
countScissors(TestParams params)244 deUint32 countScissors (TestParams params)
245 {
246 if (params.dynamicScissor)
247 {
248 deUint32 numScissors = 0u;
249
250 for (size_t commandIdx = 0; commandIdx < params.commands.size(); commandIdx++)
251 numScissors = de::max(numScissors, params.commands[commandIdx]->getMaxScissor());
252
253 return numScissors;
254 }
255 else
256 return (deUint32)params.staticScissors.size();
257 }
258
259 class ScissorTestInstance : public TestInstance
260 {
261 public:
262 ScissorTestInstance (Context& context, const TestParams& params);
263 ~ScissorTestInstance (void);
264 TestStatus iterate (void);
265
266 protected:
267 void drawCommands (VkCommandBuffer cmdBuffer, VkPipeline pipeline, VkBuffer vertexBuffer) const;
268 void postRenderCommands (VkCommandBuffer cmdBuffer, VkImage colorTargetImage) const;
269
270 #ifndef CTS_USES_VULKANSC
271 void beginSecondaryCmdBuffer (VkCommandBuffer cmdBuffer, VkFormat colorAttachmentFormat, VkRenderingFlagsKHR renderingFlags = 0u) const;
272 #endif // CTS_USES_VULKANSC
273
274 private:
275 TestParams m_params;
276
277 };
278
ScissorTestInstance(Context & context,const TestParams & params)279 ScissorTestInstance::ScissorTestInstance (Context& context, const TestParams& params)
280 : vkt::TestInstance (context)
281 , m_params (params)
282 {
283 }
284
~ScissorTestInstance(void)285 ScissorTestInstance::~ScissorTestInstance (void)
286 {
287 }
288
289 class ScissorTestCase : public TestCase
290 {
291 public:
292 ScissorTestCase (TestContext& context, const char* name, const TestParams params);
293 ~ScissorTestCase (void);
294 virtual void initPrograms (SourceCollections& programCollection) const;
295 virtual TestInstance* createInstance (Context& context) const;
296 virtual void checkSupport (Context& context) const;
297
298 private:
299 TestParams m_params;
300 };
301
ScissorTestCase(TestContext & context,const char * name,const TestParams params)302 ScissorTestCase::ScissorTestCase (TestContext& context, const char* name, const TestParams params)
303 : vkt::TestCase (context, name)
304 , m_params (params)
305 {
306 m_params.usesMultipleScissors = params.staticScissors.size() > 1;
307
308 for (size_t commandIdx = 0; commandIdx < m_params.commands.size(); commandIdx++)
309 if (m_params.commands[commandIdx]->getMaxScissor() > 1)
310 m_params.usesMultipleScissors = true;
311 }
312
~ScissorTestCase(void)313 ScissorTestCase::~ScissorTestCase (void)
314 {
315 }
316
checkSupport(Context & context) const317 void ScissorTestCase::checkSupport (Context& context) const
318 {
319 if (m_params.groupParams->useDynamicRendering)
320 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
321
322 if (m_params.usesMultipleScissors)
323 {
324 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
325 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
326 }
327 }
328
initPrograms(SourceCollections & programCollection) const329 void ScissorTestCase::initPrograms (SourceCollections& programCollection) const
330 {
331 programCollection.glslSources.add("vert") << glu::VertexSource(
332 "#version 430\n"
333 "layout(location = 0) in vec4 in_position;\n"
334 "layout(location = 1) in vec4 in_color;\n"
335 "layout(location = 0) out vec4 out_color;\n"
336 "void main()\n"
337 "{\n"
338 " gl_Position = in_position;\n"
339 " out_color = in_color;\n"
340 "}\n");
341
342 // Geometry shader draws the same triangles to all viewports
343 string geomSource = string(
344 "#version 430\n"
345 "layout(invocations = ") + de::toString(countScissors(m_params)) + ") in;\n"
346 "layout(triangles) in;\n"
347 "layout(triangle_strip, max_vertices = 3) out;\n"
348 "layout(location = 0) in vec4 in_color[];\n"
349 "layout(location = 0) out vec4 out_color;\n"
350 "void main()\n"
351 "{\n"
352 " for (int i = 0; i < gl_in.length(); i++)\n"
353 " {\n"
354 " gl_ViewportIndex = gl_InvocationID;\n"
355 " gl_Position = gl_in[i].gl_Position;\n"
356 " out_color = in_color[i];\n"
357 " EmitVertex();\n"
358 " }\n"
359 " EndPrimitive();\n"
360 "}\n";
361
362 programCollection.glslSources.add("geom") << glu::GeometrySource(geomSource);
363
364 programCollection.glslSources.add("frag") << glu::FragmentSource(
365 "#version 430\n"
366 "layout(location = 0) in vec4 in_color;\n"
367 "layout(location = 0) out vec4 out_color;\n"
368 "void main()\n"
369 "{\n"
370 " out_color = in_color;\n"
371 "}\n");
372 }
373
createInstance(Context & context) const374 TestInstance* ScissorTestCase::createInstance (Context& context) const
375 {
376 return new ScissorTestInstance(context, m_params);
377 }
378
iterate(void)379 TestStatus ScissorTestInstance::iterate (void)
380 {
381 ConstPixelBufferAccess frame;
382 VkFormat colorImageFormat = VK_FORMAT_R8G8B8A8_UNORM;
383 de::SharedPtr<Image> colorTargetImage;
384 TestLog& log = m_context.getTestContext().getLog();
385 const DeviceInterface& vk = m_context.getDeviceInterface();
386 const VkDevice device = m_context.getDevice();
387 const CmdPoolCreateInfo cmdPoolCreateInfo (m_context.getUniversalQueueFamilyIndex());
388 Move<VkCommandPool> cmdPool = createCommandPool(vk, device, &cmdPoolCreateInfo);
389 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
390 Move<VkCommandBuffer> secCmdBuffer;
391 const Unique<VkShaderModule> vs (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
392 Move<VkShaderModule> gs;
393 const Unique<VkShaderModule> fs (createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
394 const deUint32 numScissors = countScissors(m_params);
395 VkDeviceSize vertexBufferSize = 0;
396 de::SharedPtr<Buffer> vertexBuffer;
397 Move<VkRenderPass> renderPass;
398 Move<VkImageView> colorTargetView;
399 Move<VkFramebuffer> framebuffer;
400 Move<VkPipeline> pipeline;
401 TextureLevel refImage;
402 VkExtent2D framebufferSize = m_params.framebufferSize;
403
404 if (m_params.usesMultipleScissors)
405 gs = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0);
406
407 // Create color buffer image
408 {
409 const VkExtent3D targetImageExtent = { WIDTH, HEIGHT, 1 };
410 const ImageCreateInfo targetImageCreateInfo (VK_IMAGE_TYPE_2D, colorImageFormat, targetImageExtent, 1, 1, VK_SAMPLE_COUNT_1_BIT,
411 VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
412 colorTargetImage = Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
413 }
414
415 const ImageViewCreateInfo colorTargetViewInfo(colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, colorImageFormat);
416 colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
417
418 // Create render pass
419 if (!m_params.groupParams->useDynamicRendering)
420 {
421 RenderPassCreateInfo renderPassCreateInfo;
422 renderPassCreateInfo.addAttachment(AttachmentDescription(colorImageFormat,
423 VK_SAMPLE_COUNT_1_BIT,
424 VK_ATTACHMENT_LOAD_OP_CLEAR,
425 VK_ATTACHMENT_STORE_OP_STORE,
426 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
427 VK_ATTACHMENT_STORE_OP_STORE,
428 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
429 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
430
431 const VkAttachmentReference colorAttachmentRef = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
432 renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 0, DE_NULL, 1, &colorAttachmentRef,
433 DE_NULL, AttachmentReference(), 0, DE_NULL));
434
435 renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
436
437 // Create framebuffer
438 vector<VkImageView> colorAttachment { *colorTargetView };
439 const FramebufferCreateInfo framebufferCreateInfo(*renderPass, colorAttachment, framebufferSize.width, framebufferSize.height, 1);
440 framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
441 }
442
443 // Create vertex buffer
444 {
445 vector<PositionColorVertex> vertices;
446
447 for (size_t commandIdx = 0; commandIdx < m_params.commands.size(); commandIdx++)
448 {
449 vector<PositionColorVertex> commandVertices = m_params.commands[commandIdx]->getVertices((deUint32)vertices.size());
450 vertices.insert(vertices.end(), commandVertices.begin(), commandVertices.end());
451 }
452
453 vertexBufferSize = vertices.size() * sizeof(PositionColorVertex);
454
455 if (vertexBufferSize > 0)
456 {
457 vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
458 deUint8* ptr = reinterpret_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr());
459
460 deMemcpy(ptr, vertices.data(), static_cast<size_t>(vertexBufferSize));
461 flushMappedMemoryRange(vk, device, vertexBuffer->getBoundMemory().getMemory(), vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
462 }
463 }
464
465 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
466 Move<VkPipelineLayout> pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
467
468 // Create pipeline
469 {
470 const PipelineCreateInfo::ColorBlendState::Attachment colorBlendState;
471
472 const VkVertexInputBindingDescription vertexInputBindingDescription =
473 {
474 0, // deUintre binding
475 (deUint32)sizeof(Vec4) * 2, // deUint32 stride
476 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate
477 };
478 const VkViewport viewport = makeViewport(WIDTH, HEIGHT);
479
480 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
481 {
482 { 0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u },
483 { 1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, (deUint32)(sizeof(float) * 4) }
484 };
485
486 PipelineCreateInfo::VertexInputState vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions);
487
488 PipelineCreateInfo pipelineCreateInfo(*pipelineLayout, *renderPass, 0, 0);
489 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT));
490 if (m_params.usesMultipleScissors)
491 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*gs, "main", VK_SHADER_STAGE_GEOMETRY_BIT));
492 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
493 pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
494 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
495 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &colorBlendState));
496 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
497 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
498 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
499
500 if (m_params.dynamicScissor)
501 {
502 pipelineCreateInfo.addState(PipelineCreateInfo::DynamicState(vector<VkDynamicState>(1, VK_DYNAMIC_STATE_SCISSOR)));
503 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(numScissors, vector<VkViewport>(numScissors, viewport), vector<VkRect2D>(numScissors, makeRect2D(0, 0))));
504 }
505 else
506 {
507 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(numScissors, vector<VkViewport>(numScissors, viewport), m_params.staticScissors));
508 }
509
510 #ifndef CTS_USES_VULKANSC
511 VkPipelineRenderingCreateInfoKHR renderingCreateInfo
512 {
513 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
514 DE_NULL,
515 0u,
516 1u,
517 &colorImageFormat,
518 VK_FORMAT_UNDEFINED,
519 VK_FORMAT_UNDEFINED
520 };
521
522 if (m_params.groupParams->useDynamicRendering)
523 pipelineCreateInfo.pNext = &renderingCreateInfo;
524 #endif // CTS_USES_VULKANSC
525
526 pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
527 }
528
529 // Queue commands and read results.
530 {
531 const ImageSubresourceRange subresourceRange (VK_IMAGE_ASPECT_COLOR_BIT);
532 const VkOffset3D zeroOffset = { 0, 0, 0 };
533 const tcu::Vec4 clearColor = { 0.0f, 0.0f, 0.0f, 1.0f };
534 const VkClearValue clearValue = makeClearValueColor(clearColor);
535 const VkBuffer vBuffer = (vertexBufferSize > 0) ? vertexBuffer->object() : DE_NULL;
536 const VkRect2D renderArea = makeRect2D(m_params.framebufferSize);
537
538 // Unreference value for Vulkan SC
539 DE_UNREF(clearValue);
540
541 clearColorImage(vk, device, m_context.getUniversalQueue(), m_context.getUniversalQueueFamilyIndex(), colorTargetImage->object(), clearColor,
542 VK_IMAGE_LAYOUT_UNDEFINED,
543 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
544 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 1u);
545
546 #ifndef CTS_USES_VULKANSC
547 if (m_params.groupParams->useSecondaryCmdBuffer)
548 {
549 secCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
550
551 // record secondary command buffer
552 if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
553 {
554 beginSecondaryCmdBuffer(*secCmdBuffer, colorImageFormat, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
555 beginRendering(vk, *secCmdBuffer, *colorTargetView, renderArea, clearValue, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR);
556 }
557 else
558 beginSecondaryCmdBuffer(*secCmdBuffer, colorImageFormat);
559
560 drawCommands(*secCmdBuffer, *pipeline, vBuffer);
561
562 if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
563 endRendering(vk, *secCmdBuffer);
564
565 endCommandBuffer(vk, *secCmdBuffer);
566
567 // record primary command buffer
568 beginCommandBuffer(vk, *cmdBuffer, 0u);
569
570 if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
571 beginRendering(vk, *cmdBuffer, *colorTargetView, renderArea, clearValue, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
572
573 vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
574
575 if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
576 endRendering(vk, *cmdBuffer);
577
578 postRenderCommands(*cmdBuffer, colorTargetImage->object());
579 endCommandBuffer(vk, *cmdBuffer);
580 }
581 else if (m_params.groupParams->useDynamicRendering)
582 {
583 beginCommandBuffer(vk, *cmdBuffer);
584
585 beginRendering(vk, *cmdBuffer, *colorTargetView, renderArea, clearValue, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR);
586 drawCommands(*cmdBuffer, *pipeline, vBuffer);
587 endRendering(vk, *cmdBuffer);
588 postRenderCommands(*cmdBuffer, colorTargetImage->object());
589
590 endCommandBuffer(vk, *cmdBuffer);
591 }
592 #endif // CTS_USES_VULKANSC
593
594 if (!m_params.groupParams->useDynamicRendering)
595 {
596 beginCommandBuffer(vk, *cmdBuffer);
597
598 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor);
599 drawCommands(*cmdBuffer, *pipeline, vBuffer);
600 endRenderPass(vk, *cmdBuffer);
601 postRenderCommands(*cmdBuffer, colorTargetImage->object());
602
603 endCommandBuffer(vk, *cmdBuffer);
604 }
605
606 submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), cmdBuffer.get());
607
608 frame = colorTargetImage->readSurface(m_context.getUniversalQueue(), m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, zeroOffset, WIDTH, HEIGHT, VK_IMAGE_ASPECT_COLOR_BIT);
609 }
610
611 // Generate reference
612 {
613 refImage.setStorage(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), WIDTH, HEIGHT);
614 clear(refImage.getAccess(), Vec4(0.0f, 0.0f, 0.0f, 1.0f));
615
616 vector<VkRect2D> scissors = m_params.staticScissors;
617
618 for (size_t commandIdx = 0; commandIdx < m_params.commands.size(); commandIdx++)
619 {
620 scissors = m_params.commands[commandIdx]->updateScissors(scissors);
621
622 vector<ColorQuad> quad = m_params.commands[commandIdx]->getQuad();
623
624 if (quad.empty())
625 continue;
626
627 for (size_t scissorIdx = 0; scissorIdx < scissors.size(); scissorIdx++)
628 {
629 ColorQuad scissoredQuad = m_params.commands[commandIdx]->isScissored() ? scissorQuad(quad[0], scissors[scissorIdx], framebufferSize) : quad[0];
630
631 if (scissoredQuad.m_width == 0 || scissoredQuad.m_height == 0)
632 continue;
633
634 clear(getSubregion(refImage.getAccess(), scissoredQuad.m_x, scissoredQuad.m_y, 0, scissoredQuad.m_width, scissoredQuad.m_height, 1), scissoredQuad.m_color);
635 }
636 }
637 }
638
639 // Compare results
640 qpTestResult res = QP_TEST_RESULT_PASS;
641
642 if (!intThresholdCompare(log, "Result", "Image comparison result", refImage.getAccess(), frame, UVec4(0), COMPARE_LOG_RESULT))
643 res = QP_TEST_RESULT_FAIL;
644
645 return TestStatus(res, qpGetTestResultName(res));
646 }
647
drawCommands(VkCommandBuffer cmdBuffer,VkPipeline pipeline,VkBuffer vertexBuffer) const648 void ScissorTestInstance::drawCommands(VkCommandBuffer cmdBuffer, VkPipeline pipeline, VkBuffer vertexBuffer) const
649 {
650 const DeviceInterface& vk = m_context.getDeviceInterface();
651 const VkDeviceSize vertexBufferOffset = 0;
652
653 if (vertexBuffer != DE_NULL)
654 vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
655 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
656
657 for (size_t commandIdx = 0; commandIdx < m_params.commands.size(); commandIdx++)
658 m_params.commands[commandIdx]->addCommands(vk, cmdBuffer);
659 }
660
postRenderCommands(VkCommandBuffer cmdBuffer,VkImage colorTargetImage) const661 void ScissorTestInstance::postRenderCommands(VkCommandBuffer cmdBuffer, VkImage colorTargetImage) const
662 {
663 const DeviceInterface& vk = m_context.getDeviceInterface();
664 transition2DImage(vk, cmdBuffer, colorTargetImage,
665 VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
666 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
667 VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
668 VK_PIPELINE_STAGE_TRANSFER_BIT);
669 }
670
671 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer,VkFormat colorAttachmentFormat,VkRenderingFlagsKHR renderingFlags) const672 void ScissorTestInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkFormat colorAttachmentFormat, VkRenderingFlagsKHR renderingFlags) const
673 {
674 VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
675 {
676 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
677 DE_NULL, // const void* pNext;
678 renderingFlags, // VkRenderingFlagsKHR flags;
679 0u, // uint32_t viewMask;
680 1u, // uint32_t colorAttachmentCount;
681 &colorAttachmentFormat, // const VkFormat* pColorAttachmentFormats;
682 VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
683 VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
684 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
685 };
686 const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
687
688 VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
689 if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
690 usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
691
692 const VkCommandBufferBeginInfo commandBufBeginParams
693 {
694 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
695 DE_NULL, // const void* pNext;
696 usageFlags, // VkCommandBufferUsageFlags flags;
697 &bufferInheritanceInfo
698 };
699
700 const DeviceInterface& vk = m_context.getDeviceInterface();
701 VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
702 }
703 #endif // CTS_USES_VULKANSC
704
createTests(TestCaseGroup * testGroup,const SharedGroupParams groupParams)705 void createTests (TestCaseGroup* testGroup, const SharedGroupParams groupParams)
706 {
707 TestContext& testCtx = testGroup->getTestContext();
708 const Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
709 const Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
710 const Vec4 blue (0.0f, 0.0f, 1.0f, 1.0f);
711 const Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f);
712
713 // Two quads with a single static scissor
714 {
715 TestParams params(groupParams);
716 params.dynamicScissor = false;
717 params.staticScissors.push_back(makeRect2D(30, 40, WIDTH - 60, HEIGHT - 80));
718 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(10, 10, 50, 50, red)));
719 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(WIDTH - 80, HEIGHT - 100, 30, 40, green)));
720
721 testGroup->addChild(new ScissorTestCase(testCtx, "static_scissor_two_quads", params));
722 }
723
724 // Two clears with a single static scissor
725 {
726 TestParams params(groupParams);
727 params.dynamicScissor = false;
728 params.staticScissors.push_back(makeRect2D(30, 40, WIDTH - 60, HEIGHT - 80));
729 params.commands.push_back(TestCommandSp(new RectClearTestCommand(10, 10, 50, 50, red)));
730 params.commands.push_back(TestCommandSp(new RectClearTestCommand(WIDTH - 80, HEIGHT - 100, 30, 40, green)));
731
732 testGroup->addChild(new ScissorTestCase(testCtx, "static_scissor_two_clears", params));
733 }
734
735 // One quad with two static scissors
736 {
737 TestParams params(groupParams);
738 params.dynamicScissor = false;
739 params.staticScissors.push_back(makeRect2D(30, 40, WIDTH - 60, HEIGHT - 70));
740 params.staticScissors.push_back(makeRect2D(40, 50, WIDTH - 60, HEIGHT - 70));
741 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(10, 10, WIDTH - 10, HEIGHT - 10, red)));
742
743 testGroup->addChild(new ScissorTestCase(testCtx, "two_static_scissors_one_quad", params));
744 }
745
746 // Static scissor extending outside viewport
747 {
748 TestParams params(groupParams);
749 params.dynamicScissor = false;
750 params.staticScissors.push_back(makeRect2D(30, 40, WIDTH, HEIGHT));
751 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(0, 0, WIDTH, HEIGHT + 30, green)));
752
753 testGroup->addChild(new ScissorTestCase(testCtx, "static_scissor_partially_outside_viewport", params));
754 }
755
756 // Static scissor completely outside viewport
757 {
758 TestParams params(groupParams);
759 params.dynamicScissor = false;
760 params.staticScissors.push_back(makeRect2D(WIDTH + 30, HEIGHT + 40, WIDTH, HEIGHT));
761 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(100, 100, 20, 30, green)));
762
763 testGroup->addChild(new ScissorTestCase(testCtx, "static_scissor_outside_viewport", params));
764 }
765
766 // Static scissor outside viewport and touching right border of viewport
767 {
768 TestParams params(groupParams);
769 params.dynamicScissor = false;
770 params.staticScissors.push_back(makeRect2D(WIDTH, 0, WIDTH, HEIGHT));
771 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(100, 100, 20, 30, green)));
772
773 testGroup->addChild(new ScissorTestCase(testCtx, "static_scissor_viewport_border", params));
774 }
775
776 // Static scissor with offset + extent equal to largest positive int32
777 {
778 TestParams params(groupParams);
779 params.dynamicScissor = false;
780 params.staticScissors.push_back(makeRect2D(100, 100, 0x7fffffff - 100, 0x7fffffff - 100));
781 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(0, 0, WIDTH, HEIGHT, green)));
782
783 testGroup->addChild(new ScissorTestCase(testCtx, "static_scissor_max_int32", params));
784 }
785
786 // 16 static scissors (minimum number required when multiViewport supported)
787 {
788 TestParams params(groupParams);
789 params.dynamicScissor = false;
790
791 for (deUint32 i = 0; i < 16; i++)
792 params.staticScissors.push_back(makeRect2D(10 + i * 3, 20 + i * 2, WIDTH / 2, HEIGHT / 2));
793
794 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(5, 6, WIDTH - 10, HEIGHT - 2, red)));
795
796 testGroup->addChild(new ScissorTestCase(testCtx, "16_static_scissors", params));
797 }
798
799 // Two quads with an empty scissor
800 {
801 TestParams params(groupParams);
802 params.dynamicScissor = false;
803 params.staticScissors.push_back(makeRect2D(0, 0, 0, 0));
804 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(10, 10, 50, 50, red)));
805 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(WIDTH - 80, HEIGHT - 100, 30, 40, green)));
806
807 testGroup->addChild(new ScissorTestCase(testCtx, "empty_static_scissor", params));
808 }
809
810 // Two quads with a single dynamic scissor
811 {
812 TestParams params(groupParams);
813 params.dynamicScissor = true;
814 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, makeRect2D(30, 40, WIDTH - 60, HEIGHT - 80)))));
815 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(10, 10, 50, 50, red)));
816 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(WIDTH - 80, HEIGHT - 100, 30, 40, green)));
817
818 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_two_quads", params));
819 }
820
821 // Empty scissor for the first draw
822 {
823 TestParams params(groupParams);
824 params.dynamicScissor = true;
825 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, makeRect2D(0, 0, 0, 0)))));
826 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(10, 10, 50, 50, red)));
827 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, makeRect2D(30, 40, WIDTH - 60, HEIGHT - 80)))));
828 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(WIDTH - 80, HEIGHT - 100, 30, 40, green)));
829
830 testGroup->addChild(new ScissorTestCase(testCtx, "empty_dynamic_scissor_first_draw", params));
831 }
832
833 // Two quads with three scissors updated in between
834 {
835 TestParams params(groupParams);
836 VkRect2D rect = makeRect2D(10, 20, WIDTH - 60, HEIGHT - 70);
837 vector<VkRect2D> scissors;
838
839 params.dynamicScissor = true;
840
841 scissors.push_back(rect);
842 rect.offset.x += 10;
843 rect.offset.y += 10;
844 scissors.push_back(rect);
845 rect.offset.x += 10;
846 rect.offset.y += 10;
847 scissors.push_back(rect);
848
849 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, scissors)));
850 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(5, 7, WIDTH - 20, HEIGHT - 9, red)));
851
852 for (size_t scissorIdx = 0; scissorIdx < scissors.size(); scissorIdx++)
853 scissors[scissorIdx].offset.x += 20;
854
855 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, scissors)));
856 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(8, 12, WIDTH - 2, HEIGHT - 19, green)));
857
858 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_updates_between_draws", params));
859 }
860
861 // Scissor updates out of order
862 {
863 TestParams params(groupParams);
864 VkRect2D rect = makeRect2D(10, 20, WIDTH - 60, HEIGHT - 70);
865 vector<VkRect2D> scissors;
866
867 params.dynamicScissor = true;
868
869 scissors.push_back(rect);
870 rect.offset.x += 10;
871 rect.offset.y += 10;
872 scissors.push_back(rect);
873 rect.offset.x += 10;
874 rect.offset.y += 10;
875 scissors.push_back(rect);
876
877 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(2, vector<VkRect2D>(1, scissors[2]))));
878 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(1, vector<VkRect2D>(1, scissors[1]))));
879 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, scissors[0]))));
880 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(5, 7, WIDTH - 20, HEIGHT - 9, red)));
881
882 for (size_t scissorIdx = 0; scissorIdx < scissors.size(); scissorIdx++)
883 scissors[scissorIdx].offset.x += 20;
884
885 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(1, vector<VkRect2D>(1, scissors[1]))));
886 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, scissors[0]))));
887 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(2, vector<VkRect2D>(1, scissors[2]))));
888 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(8, 12, WIDTH - 2, HEIGHT - 19, green)));
889
890 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_out_of_order_updates", params));
891 }
892
893 // Dynamic scissor extending outside viewport
894 {
895 TestParams params(groupParams);
896 params.dynamicScissor = true;
897 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, makeRect2D(30, 40, WIDTH, HEIGHT)))));
898 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(0, 0, WIDTH + 50, HEIGHT + 20, green)));
899
900 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_partially_outside_viewport", params));
901 }
902
903 // Dynamic scissor completely outside viewport
904 {
905 TestParams params(groupParams);
906 params.dynamicScissor = true;
907 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, makeRect2D(WIDTH + 30, HEIGHT + 40, WIDTH, HEIGHT)))));
908 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(100, 100, 20, 30, green)));
909
910 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_outside_viewport", params));
911 }
912
913 // Dynamic scissor outside viewport and touching right border of viewport
914 {
915 TestParams params(groupParams);
916 params.dynamicScissor = true;
917 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, makeRect2D(WIDTH, 0, WIDTH, HEIGHT)))));
918 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(100, 100, 20, 30, green)));
919
920 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_viewport_border", params));
921 }
922
923 // Dynamic scissor with offset + extent equal to largest positive int32
924 {
925 TestParams params(groupParams);
926 params.dynamicScissor = true;
927 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, makeRect2D(100, 100, 0x7fffffff - 100, 0x7fffffff - 100)))));
928 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(0, 0, WIDTH, HEIGHT, green)));
929
930 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_max_int32", params));
931 }
932
933 // 16 dynamic scissors (minimum number required when multiViewport supported)
934 {
935 TestParams params(groupParams);
936 vector<VkRect2D> scissors;
937 params.dynamicScissor = true;
938
939 for (deUint32 i = 0; i < 16; i++)
940 scissors.push_back(makeRect2D(10 + i * 3, 20 + i * 2, WIDTH / 2, HEIGHT / 2));
941
942 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, scissors)));
943 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(5, 6, WIDTH - 10, HEIGHT - 2, red)));
944
945 testGroup->addChild(new ScissorTestCase(testCtx, "16_dynamic_scissors", params));
946 }
947
948 // Two clears with a single dynamic scissor
949 {
950 TestParams params(groupParams);
951 params.dynamicScissor = true;
952 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, makeRect2D(30, 40, WIDTH - 60, HEIGHT - 80)))));
953 params.commands.push_back(TestCommandSp(new RectClearTestCommand(10, 10, 50, 50, red)));
954 params.commands.push_back(TestCommandSp(new RectClearTestCommand(WIDTH - 80, HEIGHT - 100, 30, 40, green)));
955
956 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_two_clears", params));
957 }
958
959 // Mixture of quad draws and clears with dynamic scissor updates
960 {
961 TestParams params(groupParams);
962 vector<VkRect2D> scissors;
963
964 params.dynamicScissor = true;
965
966 scissors.push_back(makeRect2D(30, 40, 50, 60));
967 scissors.push_back(makeRect2D(40, 20, 50, 50));
968 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, scissors)));
969 params.commands.push_back(TestCommandSp(new RectClearTestCommand(10, 10, 50, 50, red)));
970 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(40, 30, 50, 50, green)));
971 scissors[1].extent.width -= 20;
972 scissors[1].extent.height += 30;
973 scissors[1].offset.x -= 20;
974 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(1, vector<VkRect2D>(1, scissors[1]))));
975 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(70, 70, 50, 50, blue)));
976 params.commands.push_back(TestCommandSp(new RectClearTestCommand(75, 77, 50, 50, yellow)));
977
978 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_mix", params));
979 }
980
981 // Static scissor off by one, inside frame buffer border
982 {
983 VkExtent2D size =
984 {
985 WIDTH / 2 - 1,
986 HEIGHT / 2 - 1
987 };
988
989 TestParams params(groupParams);
990
991 params.framebufferSize = size;
992 params.dynamicScissor = false;
993 params.staticScissors.push_back(makeRect2D(1, 1, size.width - 2, size.height - 2));
994 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(0, 0, WIDTH * 4, HEIGHT * 4, red)));
995
996 testGroup->addChild(new ScissorTestCase(testCtx, "static_scissor_framebuffer_border_in", params));
997 }
998
999 // Dynamic scissor off by one, inside frame buffer border
1000 {
1001 VkExtent2D size =
1002 {
1003 WIDTH / 2 - 1,
1004 HEIGHT / 2 - 1
1005 };
1006
1007 TestParams params(groupParams);
1008 vector<VkRect2D> scissors;
1009
1010 params.framebufferSize = size;
1011 params.dynamicScissor = true;
1012
1013 scissors.push_back(makeRect2D(1, 1, size.width - 2, size.height - 2));
1014 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, scissors)));
1015 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(0, 0, WIDTH * 4, HEIGHT * 4, red)));
1016
1017 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_framebuffer_border_in", params));
1018 }
1019 }
1020
1021 } // anonymous
1022
createScissorTests(TestContext & testCtx,const SharedGroupParams groupParams)1023 TestCaseGroup* createScissorTests (TestContext& testCtx, const SharedGroupParams groupParams)
1024 {
1025 return createTestGroup(testCtx, "scissor", createTests, groupParams);
1026 }
1027
1028 } // Draw
1029 } // vkt
1030