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::__anon12e10fd70111::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 dummy scissor
222
223 scissors[m_firstScissor + scissorIdx] = m_scissors[scissorIdx];
224 }
225
226 return scissors;
227 }
228
229 struct TestParams
230 {
TestParamsvkt::Draw::__anon12e10fd70111::TestParams231 TestParams() : framebufferSize({WIDTH,HEIGHT}) {}
232
233 bool dynamicScissor;
234 vector<VkRect2D> staticScissors;
235 vector<TestCommandSp> commands;
236 bool usesMultipleScissors;
237 bool usesDynamicRendering;
238 VkExtent2D framebufferSize;
239 };
240
countScissors(TestParams params)241 deUint32 countScissors (TestParams params)
242 {
243 if (params.dynamicScissor)
244 {
245 deUint32 numScissors = 0u;
246
247 for (size_t commandIdx = 0; commandIdx < params.commands.size(); commandIdx++)
248 numScissors = de::max(numScissors, params.commands[commandIdx]->getMaxScissor());
249
250 return numScissors;
251 }
252 else
253 return (deUint32)params.staticScissors.size();
254 }
255
256 class ScissorTestInstance : public TestInstance
257 {
258 public:
259 ScissorTestInstance (Context& context, const TestParams& params);
260 ~ScissorTestInstance (void);
261 TestStatus iterate (void);
262 private:
263 TestParams m_params;
264
265 };
266
ScissorTestInstance(Context & context,const TestParams & params)267 ScissorTestInstance::ScissorTestInstance (Context& context, const TestParams& params)
268 : vkt::TestInstance (context)
269 , m_params (params)
270 {
271 }
272
~ScissorTestInstance(void)273 ScissorTestInstance::~ScissorTestInstance (void)
274 {
275 }
276
277 class ScissorTestCase : public TestCase
278 {
279 public:
280 ScissorTestCase (TestContext& context, const char* name, const char* desc, const TestParams params);
281 ~ScissorTestCase (void);
282 virtual void initPrograms (SourceCollections& programCollection) const;
283 virtual TestInstance* createInstance (Context& context) const;
284 virtual void checkSupport (Context& context) const;
285
286 private:
287 TestParams m_params;
288 };
289
ScissorTestCase(TestContext & context,const char * name,const char * desc,const TestParams params)290 ScissorTestCase::ScissorTestCase (TestContext& context, const char* name, const char* desc, const TestParams params)
291 : vkt::TestCase (context, name, desc)
292 , m_params (params)
293 {
294 m_params.usesMultipleScissors = params.staticScissors.size() > 1;
295
296 for (size_t commandIdx = 0; commandIdx < m_params.commands.size(); commandIdx++)
297 if (m_params.commands[commandIdx]->getMaxScissor() > 1)
298 m_params.usesMultipleScissors = true;
299 }
300
~ScissorTestCase(void)301 ScissorTestCase::~ScissorTestCase (void)
302 {
303 }
304
checkSupport(Context & context) const305 void ScissorTestCase::checkSupport (Context& context) const
306 {
307 if (m_params.usesDynamicRendering)
308 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
309
310 if (m_params.usesMultipleScissors)
311 {
312 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
313 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
314 }
315 }
316
initPrograms(SourceCollections & programCollection) const317 void ScissorTestCase::initPrograms (SourceCollections& programCollection) const
318 {
319 programCollection.glslSources.add("vert") << glu::VertexSource(
320 "#version 430\n"
321 "layout(location = 0) in vec4 in_position;\n"
322 "layout(location = 1) in vec4 in_color;\n"
323 "layout(location = 0) out vec4 out_color;\n"
324 "void main()\n"
325 "{\n"
326 " gl_Position = in_position;\n"
327 " out_color = in_color;\n"
328 "}\n");
329
330 // Geometry shader draws the same triangles to all viewports
331 string geomSource = string(
332 "#version 430\n"
333 "layout(invocations = ") + de::toString(countScissors(m_params)) + ") in;\n"
334 "layout(triangles) in;\n"
335 "layout(triangle_strip, max_vertices = 3) out;\n"
336 "layout(location = 0) in vec4 in_color[];\n"
337 "layout(location = 0) out vec4 out_color;\n"
338 "void main()\n"
339 "{\n"
340 " for (int i = 0; i < gl_in.length(); i++)\n"
341 " {\n"
342 " gl_ViewportIndex = gl_InvocationID;\n"
343 " gl_Position = gl_in[i].gl_Position;\n"
344 " out_color = in_color[i];\n"
345 " EmitVertex();\n"
346 " }\n"
347 " EndPrimitive();\n"
348 "}\n";
349
350 programCollection.glslSources.add("geom") << glu::GeometrySource(geomSource);
351
352 programCollection.glslSources.add("frag") << glu::FragmentSource(
353 "#version 430\n"
354 "layout(location = 0) in vec4 in_color;\n"
355 "layout(location = 0) out vec4 out_color;\n"
356 "void main()\n"
357 "{\n"
358 " out_color = in_color;\n"
359 "}\n");
360 }
361
createInstance(Context & context) const362 TestInstance* ScissorTestCase::createInstance (Context& context) const
363 {
364 return new ScissorTestInstance(context, m_params);
365 }
366
iterate(void)367 TestStatus ScissorTestInstance::iterate (void)
368 {
369 ConstPixelBufferAccess frame;
370 VkFormat colorImageFormat = VK_FORMAT_R8G8B8A8_UNORM;
371 de::SharedPtr<Image> colorTargetImage;
372 TestLog& log = m_context.getTestContext().getLog();
373 const DeviceInterface& vk = m_context.getDeviceInterface();
374 const VkDevice device = m_context.getDevice();
375 const CmdPoolCreateInfo cmdPoolCreateInfo (m_context.getUniversalQueueFamilyIndex());
376 Move<VkCommandPool> cmdPool = createCommandPool(vk, device, &cmdPoolCreateInfo);
377 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
378 const Unique<VkShaderModule> vs (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
379 Move<VkShaderModule> gs;
380 const Unique<VkShaderModule> fs (createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
381 const deUint32 numScissors = countScissors(m_params);
382 VkDeviceSize vertexBufferSize = 0;
383 de::SharedPtr<Buffer> vertexBuffer;
384 Move<VkRenderPass> renderPass;
385 Move<VkImageView> colorTargetView;
386 Move<VkFramebuffer> framebuffer;
387 Move<VkPipeline> pipeline;
388 TextureLevel refImage;
389 VkExtent2D framebufferSize = m_params.framebufferSize;
390
391 if (m_params.usesMultipleScissors)
392 gs = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0);
393
394 // Create color buffer image
395 {
396 const VkExtent3D targetImageExtent = { WIDTH, HEIGHT, 1 };
397 const ImageCreateInfo targetImageCreateInfo (VK_IMAGE_TYPE_2D, colorImageFormat, targetImageExtent, 1, 1, VK_SAMPLE_COUNT_1_BIT,
398 VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
399 colorTargetImage = Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
400 }
401
402 const ImageViewCreateInfo colorTargetViewInfo(colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, colorImageFormat);
403 colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
404
405 // Create render pass
406 if (!m_params.usesDynamicRendering)
407 {
408 RenderPassCreateInfo renderPassCreateInfo;
409 renderPassCreateInfo.addAttachment(AttachmentDescription(colorImageFormat,
410 VK_SAMPLE_COUNT_1_BIT,
411 VK_ATTACHMENT_LOAD_OP_CLEAR,
412 VK_ATTACHMENT_STORE_OP_STORE,
413 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
414 VK_ATTACHMENT_STORE_OP_STORE,
415 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
416 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
417
418 const VkAttachmentReference colorAttachmentRef = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
419 renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 0, DE_NULL, 1, &colorAttachmentRef,
420 DE_NULL, AttachmentReference(), 0, DE_NULL));
421
422 renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
423
424 // Create framebuffer
425 vector<VkImageView> colorAttachment { *colorTargetView };
426 const FramebufferCreateInfo framebufferCreateInfo(*renderPass, colorAttachment, framebufferSize.width, framebufferSize.height, 1);
427 framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
428 }
429
430 // Create vertex buffer
431 {
432 vector<PositionColorVertex> vertices;
433
434 for (size_t commandIdx = 0; commandIdx < m_params.commands.size(); commandIdx++)
435 {
436 vector<PositionColorVertex> commandVertices = m_params.commands[commandIdx]->getVertices((deUint32)vertices.size());
437 vertices.insert(vertices.end(), commandVertices.begin(), commandVertices.end());
438 }
439
440 vertexBufferSize = vertices.size() * sizeof(PositionColorVertex);
441
442 if (vertexBufferSize > 0)
443 {
444 vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
445 deUint8* ptr = reinterpret_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr());
446
447 deMemcpy(ptr, vertices.data(), static_cast<size_t>(vertexBufferSize));
448 flushMappedMemoryRange(vk, device, vertexBuffer->getBoundMemory().getMemory(), vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
449 }
450 }
451
452 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
453 Move<VkPipelineLayout> pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
454
455 // Create pipeline
456 {
457 const PipelineCreateInfo::ColorBlendState::Attachment colorBlendState;
458
459 const VkVertexInputBindingDescription vertexInputBindingDescription =
460 {
461 0, // deUintre binding
462 (deUint32)sizeof(Vec4) * 2, // deUint32 stride
463 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate
464 };
465 const VkViewport viewport = makeViewport(WIDTH, HEIGHT);
466
467 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
468 {
469 { 0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u },
470 { 1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, (deUint32)(sizeof(float) * 4) }
471 };
472
473 PipelineCreateInfo::VertexInputState vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions);
474
475 PipelineCreateInfo pipelineCreateInfo(*pipelineLayout, *renderPass, 0, 0);
476 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT));
477 if (m_params.usesMultipleScissors)
478 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*gs, "main", VK_SHADER_STAGE_GEOMETRY_BIT));
479 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
480 pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
481 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
482 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &colorBlendState));
483 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
484 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
485 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
486
487 if (m_params.dynamicScissor)
488 {
489 pipelineCreateInfo.addState(PipelineCreateInfo::DynamicState(vector<VkDynamicState>(1, VK_DYNAMIC_STATE_SCISSOR)));
490 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(numScissors, vector<VkViewport>(numScissors, viewport), vector<VkRect2D>(numScissors, makeRect2D(0, 0))));
491 }
492 else
493 {
494 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(numScissors, vector<VkViewport>(numScissors, viewport), m_params.staticScissors));
495 }
496
497 VkPipelineRenderingCreateInfoKHR renderingCreateInfo
498 {
499 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
500 DE_NULL,
501 0u,
502 1u,
503 &colorImageFormat,
504 VK_FORMAT_UNDEFINED,
505 VK_FORMAT_UNDEFINED
506 };
507
508 if (m_params.usesDynamicRendering)
509 pipelineCreateInfo.pNext = &renderingCreateInfo;
510
511 pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
512 }
513
514 // Queue commands and read results.
515 {
516 const ImageSubresourceRange subresourceRange (VK_IMAGE_ASPECT_COLOR_BIT);
517 const VkRect2D renderArea = makeRect2D(framebufferSize);
518 const VkDeviceSize vertexBufferOffset = 0;
519 const VkOffset3D zeroOffset = { 0, 0, 0 };
520 const tcu::Vec4 clearColor = { 0.0f, 0.0f, 0.0f, 1.0f };
521 const VkClearValue clearValue = makeClearValueColor(clearColor);
522
523 clearColorImage(vk, device, m_context.getUniversalQueue(), m_context.getUniversalQueueFamilyIndex(), colorTargetImage->object(), clearColor,
524 VK_IMAGE_LAYOUT_UNDEFINED,
525 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
526 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
527
528 beginCommandBuffer(vk, *cmdBuffer, 0u);
529
530 if (m_params.usesDynamicRendering)
531 beginRendering(vk, *cmdBuffer, *colorTargetView, renderArea, clearValue, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_CLEAR);
532 else
533 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor);
534
535 if (vertexBufferSize > 0)
536 {
537 const VkBuffer buffer = vertexBuffer->object();
538 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &vertexBufferOffset);
539 }
540 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
541
542 for (size_t commandIdx = 0; commandIdx < m_params.commands.size(); commandIdx++)
543 m_params.commands[commandIdx]->addCommands(vk, *cmdBuffer);
544
545 if (m_params.usesDynamicRendering)
546 endRendering(vk, *cmdBuffer);
547 else
548 endRenderPass(vk, *cmdBuffer);
549
550 transition2DImage(vk, *cmdBuffer, colorTargetImage->object(),
551 VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
552 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
553 VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
554 VK_PIPELINE_STAGE_TRANSFER_BIT);
555 endCommandBuffer(vk, *cmdBuffer);
556 submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), cmdBuffer.get());
557
558 frame = colorTargetImage->readSurface(m_context.getUniversalQueue(), m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, zeroOffset, WIDTH, HEIGHT, VK_IMAGE_ASPECT_COLOR_BIT);
559 }
560
561 // Generate reference
562 {
563 refImage.setStorage(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), WIDTH, HEIGHT);
564 clear(refImage.getAccess(), Vec4(0.0f, 0.0f, 0.0f, 1.0f));
565
566 vector<VkRect2D> scissors = m_params.staticScissors;
567
568 for (size_t commandIdx = 0; commandIdx < m_params.commands.size(); commandIdx++)
569 {
570 scissors = m_params.commands[commandIdx]->updateScissors(scissors);
571
572 vector<ColorQuad> quad = m_params.commands[commandIdx]->getQuad();
573
574 if (quad.empty())
575 continue;
576
577 for (size_t scissorIdx = 0; scissorIdx < scissors.size(); scissorIdx++)
578 {
579 ColorQuad scissoredQuad = m_params.commands[commandIdx]->isScissored() ? scissorQuad(quad[0], scissors[scissorIdx], framebufferSize) : quad[0];
580
581 if (scissoredQuad.m_width == 0 || scissoredQuad.m_height == 0)
582 continue;
583
584 clear(getSubregion(refImage.getAccess(), scissoredQuad.m_x, scissoredQuad.m_y, 0, scissoredQuad.m_width, scissoredQuad.m_height, 1), scissoredQuad.m_color);
585 }
586 }
587 }
588
589 // Compare results
590 qpTestResult res = QP_TEST_RESULT_PASS;
591
592 if (!intThresholdCompare(log, "Result", "Image comparison result", refImage.getAccess(), frame, UVec4(0), COMPARE_LOG_RESULT))
593 res = QP_TEST_RESULT_FAIL;
594
595 return TestStatus(res, qpGetTestResultName(res));
596 }
597
createTests(TestCaseGroup * testGroup,bool useDynamicRendering)598 void createTests (TestCaseGroup* testGroup, bool useDynamicRendering)
599 {
600 TestContext& testCtx = testGroup->getTestContext();
601 const Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
602 const Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
603 const Vec4 blue (0.0f, 0.0f, 1.0f, 1.0f);
604 const Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f);
605
606 // Two quads with a single static scissor
607 {
608 TestParams params;
609 params.dynamicScissor = false;
610 params.usesDynamicRendering = useDynamicRendering;
611 params.staticScissors.push_back(makeRect2D(30, 40, WIDTH - 60, HEIGHT - 80));
612 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(10, 10, 50, 50, red)));
613 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(WIDTH - 80, HEIGHT - 100, 30, 40, green)));
614
615 testGroup->addChild(new ScissorTestCase(testCtx, "static_scissor_two_quads", "", params));
616 }
617
618 // Two clears with a single static scissor
619 {
620 TestParams params;
621 params.dynamicScissor = false;
622 params.usesDynamicRendering = useDynamicRendering;
623 params.staticScissors.push_back(makeRect2D(30, 40, WIDTH - 60, HEIGHT - 80));
624 params.commands.push_back(TestCommandSp(new RectClearTestCommand(10, 10, 50, 50, red)));
625 params.commands.push_back(TestCommandSp(new RectClearTestCommand(WIDTH - 80, HEIGHT - 100, 30, 40, green)));
626
627 testGroup->addChild(new ScissorTestCase(testCtx, "static_scissor_two_clears", "", params));
628 }
629
630 // One quad with two static scissors
631 {
632 TestParams params;
633 params.dynamicScissor = false;
634 params.usesDynamicRendering = useDynamicRendering;
635 params.staticScissors.push_back(makeRect2D(30, 40, WIDTH - 60, HEIGHT - 70));
636 params.staticScissors.push_back(makeRect2D(40, 50, WIDTH - 60, HEIGHT - 70));
637 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(10, 10, WIDTH - 10, HEIGHT - 10, red)));
638
639 testGroup->addChild(new ScissorTestCase(testCtx, "two_static_scissors_one_quad", "", params));
640 }
641
642 // Static scissor extending outside viewport
643 {
644 TestParams params;
645 params.dynamicScissor = false;
646 params.usesDynamicRendering = useDynamicRendering;
647 params.staticScissors.push_back(makeRect2D(30, 40, WIDTH, HEIGHT));
648 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(0, 0, WIDTH, HEIGHT + 30, green)));
649
650 testGroup->addChild(new ScissorTestCase(testCtx, "static_scissor_partially_outside_viewport", "", params));
651 }
652
653 // Static scissor completely outside viewport
654 {
655 TestParams params;
656 params.dynamicScissor = false;
657 params.usesDynamicRendering = useDynamicRendering;
658 params.staticScissors.push_back(makeRect2D(WIDTH + 30, HEIGHT + 40, WIDTH, HEIGHT));
659 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(100, 100, 20, 30, green)));
660
661 testGroup->addChild(new ScissorTestCase(testCtx, "static_scissor_outside_viewport", "", params));
662 }
663
664 // Static scissor outside viewport and touching right border of viewport
665 {
666 TestParams params;
667 params.dynamicScissor = false;
668 params.usesDynamicRendering = useDynamicRendering;
669 params.staticScissors.push_back(makeRect2D(WIDTH, 0, WIDTH, HEIGHT));
670 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(100, 100, 20, 30, green)));
671
672 testGroup->addChild(new ScissorTestCase(testCtx, "static_scissor_viewport_border", "", params));
673 }
674
675 // Static scissor with offset + extent equal to largest positive int32
676 {
677 TestParams params;
678 params.dynamicScissor = false;
679 params.usesDynamicRendering = useDynamicRendering;
680 params.staticScissors.push_back(makeRect2D(100, 100, 0x7fffffff - 100, 0x7fffffff - 100));
681 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(0, 0, WIDTH, HEIGHT, green)));
682
683 testGroup->addChild(new ScissorTestCase(testCtx, "static_scissor_max_int32", "", params));
684 }
685
686 // 16 static scissors (minimum number required when multiViewport supported)
687 {
688 TestParams params;
689 params.dynamicScissor = false;
690 params.usesDynamicRendering = useDynamicRendering;
691
692 for (deUint32 i = 0; i < 16; i++)
693 params.staticScissors.push_back(makeRect2D(10 + i * 3, 20 + i * 2, WIDTH / 2, HEIGHT / 2));
694
695 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(5, 6, WIDTH - 10, HEIGHT - 2, red)));
696
697 testGroup->addChild(new ScissorTestCase(testCtx, "16_static_scissors", "", params));
698 }
699
700 // Two quads with an empty scissor
701 {
702 TestParams params;
703 params.dynamicScissor = false;
704 params.usesDynamicRendering = useDynamicRendering;
705 params.staticScissors.push_back(makeRect2D(0, 0, 0, 0));
706 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(10, 10, 50, 50, red)));
707 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(WIDTH - 80, HEIGHT - 100, 30, 40, green)));
708
709 testGroup->addChild(new ScissorTestCase(testCtx, "empty_static_scissor", "", params));
710 }
711
712 // Two quads with a single dynamic scissor
713 {
714 TestParams params;
715 params.dynamicScissor = true;
716 params.usesDynamicRendering = useDynamicRendering;
717 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, 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, "dynamic_scissor_two_quads", "", params));
722 }
723
724 // Empty scissor for the first draw
725 {
726 TestParams params;
727 params.dynamicScissor = true;
728 params.usesDynamicRendering = useDynamicRendering;
729 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, makeRect2D(0, 0, 0, 0)))));
730 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(10, 10, 50, 50, red)));
731 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, makeRect2D(30, 40, WIDTH - 60, HEIGHT - 80)))));
732 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(WIDTH - 80, HEIGHT - 100, 30, 40, green)));
733
734 testGroup->addChild(new ScissorTestCase(testCtx, "empty_dynamic_scissor_first_draw", "", params));
735 }
736
737 // Two quads with three scissors updated in between
738 {
739 TestParams params;
740 VkRect2D rect = makeRect2D(10, 20, WIDTH - 60, HEIGHT - 70);
741 vector<VkRect2D> scissors;
742
743 params.dynamicScissor = true;
744 params.usesDynamicRendering = useDynamicRendering;
745
746 scissors.push_back(rect);
747 rect.offset.x += 10;
748 rect.offset.y += 10;
749 scissors.push_back(rect);
750 rect.offset.x += 10;
751 rect.offset.y += 10;
752 scissors.push_back(rect);
753
754 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, scissors)));
755 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(5, 7, WIDTH - 20, HEIGHT - 9, red)));
756
757 for (size_t scissorIdx = 0; scissorIdx < scissors.size(); scissorIdx++)
758 scissors[scissorIdx].offset.x += 20;
759
760 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, scissors)));
761 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(8, 12, WIDTH - 2, HEIGHT - 19, green)));
762
763 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_updates_between_draws", "", params));
764 }
765
766 // Scissor updates out of order
767 {
768 TestParams params;
769 VkRect2D rect = makeRect2D(10, 20, WIDTH - 60, HEIGHT - 70);
770 vector<VkRect2D> scissors;
771
772 params.dynamicScissor = true;
773 params.usesDynamicRendering = useDynamicRendering;
774
775 scissors.push_back(rect);
776 rect.offset.x += 10;
777 rect.offset.y += 10;
778 scissors.push_back(rect);
779 rect.offset.x += 10;
780 rect.offset.y += 10;
781 scissors.push_back(rect);
782
783 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(2, vector<VkRect2D>(1, scissors[2]))));
784 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(1, vector<VkRect2D>(1, scissors[1]))));
785 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, scissors[0]))));
786 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(5, 7, WIDTH - 20, HEIGHT - 9, red)));
787
788 for (size_t scissorIdx = 0; scissorIdx < scissors.size(); scissorIdx++)
789 scissors[scissorIdx].offset.x += 20;
790
791 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(1, vector<VkRect2D>(1, scissors[1]))));
792 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, scissors[0]))));
793 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(2, vector<VkRect2D>(1, scissors[2]))));
794 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(8, 12, WIDTH - 2, HEIGHT - 19, green)));
795
796 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_out_of_order_updates", "", params));
797 }
798
799 // Dynamic scissor extending outside viewport
800 {
801 TestParams params;
802 params.dynamicScissor = true;
803 params.usesDynamicRendering = useDynamicRendering;
804 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, makeRect2D(30, 40, WIDTH, HEIGHT)))));
805 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(0, 0, WIDTH + 50, HEIGHT + 20, green)));
806
807 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_partially_outside_viewport", "", params));
808 }
809
810 // Dynamic scissor completely outside viewport
811 {
812 TestParams params;
813 params.dynamicScissor = true;
814 params.usesDynamicRendering = useDynamicRendering;
815 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, makeRect2D(WIDTH + 30, HEIGHT + 40, WIDTH, HEIGHT)))));
816 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(100, 100, 20, 30, green)));
817
818 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_outside_viewport", "", params));
819 }
820
821 // Dynamic scissor outside viewport and touching right border of viewport
822 {
823 TestParams params;
824 params.dynamicScissor = true;
825 params.usesDynamicRendering = useDynamicRendering;
826 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, makeRect2D(WIDTH, 0, WIDTH, HEIGHT)))));
827 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(100, 100, 20, 30, green)));
828
829 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_viewport_border", "", params));
830 }
831
832 // Dynamic scissor with offset + extent equal to largest positive int32
833 {
834 TestParams params;
835 params.dynamicScissor = true;
836 params.usesDynamicRendering = useDynamicRendering;
837 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, makeRect2D(100, 100, 0x7fffffff - 100, 0x7fffffff - 100)))));
838 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(0, 0, WIDTH, HEIGHT, green)));
839
840 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_max_int32", "", params));
841 }
842
843 // 16 dynamic scissors (minimum number required when multiViewport supported)
844 {
845 TestParams params;
846 vector<VkRect2D> scissors;
847 params.dynamicScissor = true;
848 params.usesDynamicRendering = useDynamicRendering;
849
850 for (deUint32 i = 0; i < 16; i++)
851 scissors.push_back(makeRect2D(10 + i * 3, 20 + i * 2, WIDTH / 2, HEIGHT / 2));
852
853 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, scissors)));
854 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(5, 6, WIDTH - 10, HEIGHT - 2, red)));
855
856 testGroup->addChild(new ScissorTestCase(testCtx, "16_dynamic_scissors", "", params));
857 }
858
859 // Two clears with a single dynamic scissor
860 {
861 TestParams params;
862 params.dynamicScissor = true;
863 params.usesDynamicRendering = useDynamicRendering;
864 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, vector<VkRect2D>(1, makeRect2D(30, 40, WIDTH - 60, HEIGHT - 80)))));
865 params.commands.push_back(TestCommandSp(new RectClearTestCommand(10, 10, 50, 50, red)));
866 params.commands.push_back(TestCommandSp(new RectClearTestCommand(WIDTH - 80, HEIGHT - 100, 30, 40, green)));
867
868 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_two_clears", "", params));
869 }
870
871 // Mixture of quad draws and clears with dynamic scissor updates
872 {
873 TestParams params;
874 vector<VkRect2D> scissors;
875
876 params.dynamicScissor = true;
877 params.usesDynamicRendering = useDynamicRendering;
878
879 scissors.push_back(makeRect2D(30, 40, 50, 60));
880 scissors.push_back(makeRect2D(40, 20, 50, 50));
881 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, scissors)));
882 params.commands.push_back(TestCommandSp(new RectClearTestCommand(10, 10, 50, 50, red)));
883 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(40, 30, 50, 50, green)));
884 scissors[1].extent.width -= 20;
885 scissors[1].extent.height += 30;
886 scissors[1].offset.x -= 20;
887 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(1, vector<VkRect2D>(1, scissors[1]))));
888 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(70, 70, 50, 50, blue)));
889 params.commands.push_back(TestCommandSp(new RectClearTestCommand(75, 77, 50, 50, yellow)));
890
891 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_mix", "", params));
892 }
893
894 // Static scissor off by one, inside frame buffer border
895 {
896 VkExtent2D size =
897 {
898 WIDTH / 2 - 1,
899 HEIGHT / 2 - 1
900 };
901
902 TestParams params;
903
904 params.framebufferSize = size;
905 params.dynamicScissor = false;
906 params.usesDynamicRendering = useDynamicRendering;
907 params.staticScissors.push_back(makeRect2D(1, 1, size.width - 2, size.height - 2));
908 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(0, 0, WIDTH * 4, HEIGHT * 4, red)));
909
910 testGroup->addChild(new ScissorTestCase(testCtx, "static_scissor_framebuffer_border_in", "", params));
911 }
912
913 // Dynamic scissor off by one, inside frame buffer border
914 {
915 VkExtent2D size =
916 {
917 WIDTH / 2 - 1,
918 HEIGHT / 2 - 1
919 };
920
921 TestParams params;
922 vector<VkRect2D> scissors;
923
924 params.framebufferSize = size;
925 params.dynamicScissor = true;
926 params.usesDynamicRendering = useDynamicRendering;
927
928 scissors.push_back(makeRect2D(1, 1, size.width - 2, size.height - 2));
929 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, scissors)));
930 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(0, 0, WIDTH * 4, HEIGHT * 4, red)));
931
932 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_framebuffer_border_in", "", params));
933 }
934
935 // Static scissor off by one, outside frame buffer border
936 {
937 VkExtent2D size =
938 {
939 WIDTH / 2 - 1,
940 HEIGHT / 2 - 1
941 };
942
943 TestParams params;
944
945 params.framebufferSize = size;
946 params.dynamicScissor = false;
947 params.usesDynamicRendering = useDynamicRendering;
948
949 params.staticScissors.push_back(makeRect2D(0, 0, size.width + 1, size.height + 1));
950 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(0, 0, WIDTH * 4, HEIGHT * 4, red)));
951
952 testGroup->addChild(new ScissorTestCase(testCtx, "static_scissor_framebuffer_border_out", "", params));
953 }
954
955 // Dynamic scissor off by one, outside frame buffer border
956 {
957 VkExtent2D size =
958 {
959 WIDTH / 2 - 1,
960 HEIGHT / 2 - 1
961 };
962
963 TestParams params;
964 vector<VkRect2D> scissors;
965
966 params.framebufferSize = size;
967 params.dynamicScissor = true;
968 params.usesDynamicRendering = useDynamicRendering;
969
970 scissors.push_back(makeRect2D(0, 0, size.width + 1, size.height + 1));
971 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, scissors)));
972 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(0, 0, WIDTH * 4, HEIGHT * 4, red)));
973
974 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_framebuffer_border_out", "", params));
975 }
976
977 // Static oversized scissor, exceeds frame buffer and image attachment sizes
978 {
979 VkExtent2D size =
980 {
981 WIDTH / 2 - 1,
982 HEIGHT / 2 - 1
983 };
984
985 TestParams params;
986
987 params.framebufferSize = size;
988 params.dynamicScissor = false;
989 params.usesDynamicRendering = useDynamicRendering;
990
991 params.staticScissors.push_back(makeRect2D(0, 0, WIDTH * 2, HEIGHT * 2));
992 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(0, 0, WIDTH * 4, HEIGHT * 4, red)));
993
994 testGroup->addChild(new ScissorTestCase(testCtx, "static_scissor_oversized", "", params));
995 }
996
997 // Dynamic oversized scissor, exceeds frame buffer and image attachment sizes
998 {
999 VkExtent2D size =
1000 {
1001 WIDTH / 2 - 1,
1002 HEIGHT / 2 - 1
1003 };
1004
1005 TestParams params;
1006 vector<VkRect2D> scissors;
1007
1008 params.framebufferSize = size;
1009 params.dynamicScissor = true;
1010 params.usesDynamicRendering = useDynamicRendering;
1011
1012 scissors.push_back(makeRect2D(0, 0, WIDTH * 2, HEIGHT * 2));
1013 params.commands.push_back(TestCommandSp(new DynamicScissorTestCommand(0, scissors)));
1014 params.commands.push_back(TestCommandSp(new QuadDrawTestCommand(0, 0, WIDTH * 4, HEIGHT * 4, red)));
1015
1016 testGroup->addChild(new ScissorTestCase(testCtx, "dynamic_scissor_oversized", "", params));
1017 }
1018 }
1019
1020 } // anonymous
1021
createScissorTests(TestContext & testCtx,bool useDynamicRendering)1022 TestCaseGroup* createScissorTests (TestContext& testCtx, bool useDynamicRendering)
1023 {
1024 return createTestGroup(testCtx, "scissor", "Scissor tests", createTests, useDynamicRendering);
1025 }
1026
1027 } // Draw
1028 } // vkt
1029